✨ Banner
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
				
			|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
					// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
				
			||||||
// versions:
 | 
					// versions:
 | 
				
			||||||
// 	protoc-gen-go v1.32.0
 | 
					// 	protoc-gen-go v1.33.0
 | 
				
			||||||
// 	protoc        v4.25.3
 | 
					// 	protoc        v4.25.3
 | 
				
			||||||
// source: auth.proto
 | 
					// source: auth.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,7 +30,8 @@ type Userinfo struct {
 | 
				
			|||||||
	Nick        string  `protobuf:"bytes,3,opt,name=nick,proto3" json:"nick,omitempty"`
 | 
						Nick        string  `protobuf:"bytes,3,opt,name=nick,proto3" json:"nick,omitempty"`
 | 
				
			||||||
	Email       string  `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"`
 | 
						Email       string  `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"`
 | 
				
			||||||
	Avatar      string  `protobuf:"bytes,5,opt,name=avatar,proto3" json:"avatar,omitempty"`
 | 
						Avatar      string  `protobuf:"bytes,5,opt,name=avatar,proto3" json:"avatar,omitempty"`
 | 
				
			||||||
	Description *string `protobuf:"bytes,6,opt,name=description,proto3,oneof" json:"description,omitempty"`
 | 
						Banner      string  `protobuf:"bytes,6,opt,name=banner,proto3" json:"banner,omitempty"`
 | 
				
			||||||
 | 
						Description *string `protobuf:"bytes,7,opt,name=description,proto3,oneof" json:"description,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *Userinfo) Reset() {
 | 
					func (x *Userinfo) Reset() {
 | 
				
			||||||
@@ -100,6 +101,13 @@ func (x *Userinfo) GetAvatar() string {
 | 
				
			|||||||
	return ""
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *Userinfo) GetBanner() string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Banner
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *Userinfo) GetDescription() string {
 | 
					func (x *Userinfo) GetDescription() string {
 | 
				
			||||||
	if x != nil && x.Description != nil {
 | 
						if x != nil && x.Description != nil {
 | 
				
			||||||
		return *x.Description
 | 
							return *x.Description
 | 
				
			||||||
@@ -237,43 +245,45 @@ var File_auth_proto protoreflect.FileDescriptor
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var file_auth_proto_rawDesc = []byte{
 | 
					var file_auth_proto_rawDesc = []byte{
 | 
				
			||||||
	0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72,
 | 
						0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72,
 | 
				
			||||||
	0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x01, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f,
 | 
						0x6f, 0x74, 0x6f, 0x22, 0xbf, 0x01, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f,
 | 
				
			||||||
	0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64,
 | 
						0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64,
 | 
				
			||||||
	0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
 | 
						0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
 | 
				
			||||||
	0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x69, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01,
 | 
						0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x69, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01,
 | 
				
			||||||
	0x28, 0x09, 0x52, 0x04, 0x6e, 0x69, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69,
 | 
						0x28, 0x09, 0x52, 0x04, 0x6e, 0x69, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69,
 | 
				
			||||||
	0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x16,
 | 
						0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x16,
 | 
				
			||||||
	0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
 | 
						0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
 | 
				
			||||||
	0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
 | 
						0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x72,
 | 
				
			||||||
	0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x64,
 | 
						0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x25,
 | 
				
			||||||
	0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a,
 | 
						0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20,
 | 
				
			||||||
	0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6c, 0x0a,
 | 
						0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
 | 
				
			||||||
	0x0b, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c,
 | 
						0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
 | 
				
			||||||
	0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01,
 | 
						0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6c, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71,
 | 
				
			||||||
	0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12,
 | 
						0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74,
 | 
				
			||||||
	0x28, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
 | 
						0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65,
 | 
				
			||||||
	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73,
 | 
						0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x28, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65,
 | 
				
			||||||
	0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x72, 0x65,
 | 
						0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
 | 
				
			||||||
	0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xda, 0x01, 0x0a, 0x09,
 | 
						0x52, 0x0c, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x88, 0x01,
 | 
				
			||||||
	0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f,
 | 
						0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f,
 | 
				
			||||||
	0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x56,
 | 
						0x6b, 0x65, 0x6e, 0x22, 0xda, 0x01, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6c,
 | 
				
			||||||
	0x61, 0x6c, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74,
 | 
						0x79, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20,
 | 
				
			||||||
	0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x63,
 | 
						0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x0c,
 | 
				
			||||||
	0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x28, 0x0a, 0x0d,
 | 
						0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01,
 | 
				
			||||||
	0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20,
 | 
						0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65,
 | 
				
			||||||
	0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f,
 | 
						0x6e, 0x88, 0x01, 0x01, 0x12, 0x28, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f,
 | 
				
			||||||
	0x6b, 0x65, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x69, 0x6e,
 | 
						0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0c, 0x72,
 | 
				
			||||||
	0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 | 
						0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x30,
 | 
				
			||||||
	0x2e, 0x55, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x48, 0x02, 0x52, 0x08, 0x75, 0x73, 0x65,
 | 
						0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
 | 
				
			||||||
	0x72, 0x69, 0x6e, 0x66, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x61, 0x63, 0x63,
 | 
						0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66,
 | 
				
			||||||
	0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x72, 0x65,
 | 
						0x6f, 0x48, 0x02, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x88, 0x01, 0x01,
 | 
				
			||||||
	0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x5f,
 | 
						0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65,
 | 
				
			||||||
	0x75, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x32, 0x3e, 0x0a, 0x04, 0x41, 0x75, 0x74, 0x68,
 | 
						0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f,
 | 
				
			||||||
	0x12, 0x36, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
 | 
						0x6b, 0x65, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f,
 | 
				
			||||||
	0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71,
 | 
						0x32, 0x3e, 0x0a, 0x04, 0x41, 0x75, 0x74, 0x68, 0x12, 0x36, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68,
 | 
				
			||||||
	0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74,
 | 
						0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 | 
				
			||||||
	0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x3b, 0x70, 0x72,
 | 
						0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x70,
 | 
				
			||||||
	0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
						0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00,
 | 
				
			||||||
 | 
						0x42, 0x09, 0x5a, 0x07, 0x2e, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f,
 | 
				
			||||||
 | 
						0x74, 0x6f, 0x33,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,8 @@ message Userinfo {
 | 
				
			|||||||
  string nick = 3;
 | 
					  string nick = 3;
 | 
				
			||||||
  string email = 4;
 | 
					  string email = 4;
 | 
				
			||||||
  string avatar = 5;
 | 
					  string avatar = 5;
 | 
				
			||||||
  optional string description = 6;
 | 
					  string banner = 6;
 | 
				
			||||||
 | 
					  optional string description = 7;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message AuthRequest {
 | 
					message AuthRequest {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,17 @@
 | 
				
			|||||||
package grpc
 | 
					package grpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.smartsheep.studio/hydrogen/identity/pkg/grpc/proto"
 | 
						"code.smartsheep.studio/hydrogen/identity/pkg/grpc/proto"
 | 
				
			||||||
	"code.smartsheep.studio/hydrogen/identity/pkg/models"
 | 
						"code.smartsheep.studio/hydrogen/identity/pkg/models"
 | 
				
			||||||
	"code.smartsheep.studio/hydrogen/identity/pkg/services"
 | 
						"code.smartsheep.studio/hydrogen/identity/pkg/services"
 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"github.com/samber/lo"
 | 
						"github.com/samber/lo"
 | 
				
			||||||
	"github.com/spf13/viper"
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
	"google.golang.org/grpc"
 | 
						"google.golang.org/grpc"
 | 
				
			||||||
	"google.golang.org/grpc/reflection"
 | 
						"google.golang.org/grpc/reflection"
 | 
				
			||||||
	"net"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Server struct {
 | 
					type Server struct {
 | 
				
			||||||
@@ -35,7 +36,8 @@ func (v *Server) Authenticate(_ context.Context, in *proto.AuthRequest) (*proto.
 | 
				
			|||||||
				Nick:        user.Nick,
 | 
									Nick:        user.Nick,
 | 
				
			||||||
				Email:       user.GetPrimaryEmail().Content,
 | 
									Email:       user.GetPrimaryEmail().Content,
 | 
				
			||||||
				Avatar:      fmt.Sprintf("https://%s/api/avatar/%s", viper.GetString("domain"), user.Avatar),
 | 
									Avatar:      fmt.Sprintf("https://%s/api/avatar/%s", viper.GetString("domain"), user.Avatar),
 | 
				
			||||||
				Description: nil,
 | 
									Banner:      fmt.Sprintf("https://%s/api/avatar/%s", viper.GetString("domain"), user.Banner),
 | 
				
			||||||
 | 
									Description: &user.Description,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, nil
 | 
							}, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
package models
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/samber/lo"
 | 
					 | 
				
			||||||
	"github.com/spf13/viper"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/samber/lo"
 | 
				
			||||||
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Account struct {
 | 
					type Account struct {
 | 
				
			||||||
@@ -14,6 +15,7 @@ type Account struct {
 | 
				
			|||||||
	Nick              string                   `json:"nick"`
 | 
						Nick              string                   `json:"nick"`
 | 
				
			||||||
	Description       string                   `json:"description"`
 | 
						Description       string                   `json:"description"`
 | 
				
			||||||
	Avatar            string                   `json:"avatar"`
 | 
						Avatar            string                   `json:"avatar"`
 | 
				
			||||||
 | 
						Banner            string                   `json:"banner"`
 | 
				
			||||||
	Profile           AccountProfile           `json:"profile"`
 | 
						Profile           AccountProfile           `json:"profile"`
 | 
				
			||||||
	Sessions          []AuthSession            `json:"sessions"`
 | 
						Sessions          []AuthSession            `json:"sessions"`
 | 
				
			||||||
	Challenges        []AuthChallenge          `json:"challenges"`
 | 
						Challenges        []AuthChallenge          `json:"challenges"`
 | 
				
			||||||
@@ -40,6 +42,11 @@ func (v Account) GetAvatarPath() string {
 | 
				
			|||||||
	return filepath.Join(basepath, v.Avatar)
 | 
						return filepath.Join(basepath, v.Avatar)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (v Account) GetBannerPath() string {
 | 
				
			||||||
 | 
						basepath := viper.GetString("content")
 | 
				
			||||||
 | 
						return filepath.Join(basepath, v.Banner)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type AccountContactType = int8
 | 
					type AccountContactType = int8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
package server
 | 
					package server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.smartsheep.studio/hydrogen/identity/pkg/database"
 | 
						"code.smartsheep.studio/hydrogen/identity/pkg/database"
 | 
				
			||||||
	"code.smartsheep.studio/hydrogen/identity/pkg/models"
 | 
						"code.smartsheep.studio/hydrogen/identity/pkg/models"
 | 
				
			||||||
	"github.com/gofiber/fiber/v2"
 | 
						"github.com/gofiber/fiber/v2"
 | 
				
			||||||
	"github.com/google/uuid"
 | 
						"github.com/google/uuid"
 | 
				
			||||||
	"github.com/spf13/viper"
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getAvatar(c *fiber.Ctx) error {
 | 
					func getAvatar(c *fiber.Ctx) error {
 | 
				
			||||||
@@ -23,12 +25,58 @@ func setAvatar(c *fiber.Ctx) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var previous string
 | 
				
			||||||
 | 
						if len(user.Avatar) > 0 {
 | 
				
			||||||
 | 
							previous = user.GetAvatarPath()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	user.Avatar = uuid.NewString()
 | 
						user.Avatar = uuid.NewString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.SaveFile(file, user.GetAvatarPath()); err != nil {
 | 
						if err := c.SaveFile(file, user.GetAvatarPath()); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		database.C.Save(&user)
 | 
							database.C.Save(&user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Clean up
 | 
				
			||||||
 | 
							if len(previous) > 0 {
 | 
				
			||||||
 | 
								basepath := viper.GetString("content")
 | 
				
			||||||
 | 
								filepath := filepath.Join(basepath, previous)
 | 
				
			||||||
 | 
								if info, err := os.Stat(filepath); err == nil && !info.IsDir() {
 | 
				
			||||||
 | 
									os.Remove(filepath)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c.SendStatus(fiber.StatusOK)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func setBanner(c *fiber.Ctx) error {
 | 
				
			||||||
 | 
						user := c.Locals("principal").(models.Account)
 | 
				
			||||||
 | 
						file, err := c.FormFile("banner")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var previous string
 | 
				
			||||||
 | 
						if len(user.Banner) > 0 {
 | 
				
			||||||
 | 
							previous = user.GetBannerPath()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user.Banner = uuid.NewString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := c.SaveFile(file, user.GetBannerPath()); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							database.C.Save(&user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Clean up
 | 
				
			||||||
 | 
							if len(previous) > 0 {
 | 
				
			||||||
 | 
								basepath := viper.GetString("content")
 | 
				
			||||||
 | 
								filepath := filepath.Join(basepath, previous)
 | 
				
			||||||
 | 
								if info, err := os.Stat(filepath); err == nil && !info.IsDir() {
 | 
				
			||||||
 | 
									os.Remove(filepath)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return c.SendStatus(fiber.StatusOK)
 | 
						return c.SendStatus(fiber.StatusOK)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,10 @@
 | 
				
			|||||||
package server
 | 
					package server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.smartsheep.studio/hydrogen/identity/pkg/views"
 | 
						"code.smartsheep.studio/hydrogen/identity/pkg/views"
 | 
				
			||||||
	"github.com/gofiber/fiber/v2"
 | 
						"github.com/gofiber/fiber/v2"
 | 
				
			||||||
	"github.com/gofiber/fiber/v2/middleware/cache"
 | 
						"github.com/gofiber/fiber/v2/middleware/cache"
 | 
				
			||||||
@@ -11,9 +15,6 @@ import (
 | 
				
			|||||||
	jsoniter "github.com/json-iterator/go"
 | 
						jsoniter "github.com/json-iterator/go"
 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
	"github.com/spf13/viper"
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var A *fiber.App
 | 
					var A *fiber.App
 | 
				
			||||||
@@ -58,21 +59,28 @@ func NewServer() {
 | 
				
			|||||||
	api := A.Group("/api").Name("API")
 | 
						api := A.Group("/api").Name("API")
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		api.Get("/avatar/:avatarId", getAvatar)
 | 
							api.Get("/avatar/:avatarId", getAvatar)
 | 
				
			||||||
		api.Put("/avatar", authMiddleware, setAvatar)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		api.Get("/notifications", authMiddleware, getNotifications)
 | 
							api.Get("/notifications", authMiddleware, getNotifications)
 | 
				
			||||||
		api.Put("/notifications/:notificationId/read", authMiddleware, markNotificationRead)
 | 
							api.Put("/notifications/:notificationId/read", authMiddleware, markNotificationRead)
 | 
				
			||||||
		api.Post("/notifications/subscribe", authMiddleware, addNotifySubscriber)
 | 
							api.Post("/notifications/subscribe", authMiddleware, addNotifySubscriber)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		api.Get("/users/me", authMiddleware, getUserinfo)
 | 
							me := api.Group("/users/me").Name("Myself Operations")
 | 
				
			||||||
		api.Put("/users/me", authMiddleware, editUserinfo)
 | 
							{
 | 
				
			||||||
		api.Get("/users/me/events", authMiddleware, getEvents)
 | 
					
 | 
				
			||||||
		api.Get("/users/me/challenges", authMiddleware, getChallenges)
 | 
								me.Put("/avatar", authMiddleware, setAvatar)
 | 
				
			||||||
		api.Get("/users/me/sessions", authMiddleware, getSessions)
 | 
								me.Put("/banner", authMiddleware, setBanner)
 | 
				
			||||||
		api.Delete("/users/me/sessions/:sessionId", authMiddleware, killSession)
 | 
					
 | 
				
			||||||
 | 
								me.Get("/", authMiddleware, getUserinfo)
 | 
				
			||||||
 | 
								me.Put("/", authMiddleware, editUserinfo)
 | 
				
			||||||
 | 
								me.Get("/events", authMiddleware, getEvents)
 | 
				
			||||||
 | 
								me.Get("/challenges", authMiddleware, getChallenges)
 | 
				
			||||||
 | 
								me.Get("/sessions", authMiddleware, getSessions)
 | 
				
			||||||
 | 
								me.Delete("/sessions/:sessionId", authMiddleware, killSession)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								me.Post("/confirm", doRegisterConfirm)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		api.Post("/users", doRegister)
 | 
							api.Post("/users", doRegister)
 | 
				
			||||||
		api.Post("/users/me/confirm", doRegisterConfirm)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		api.Put("/auth", startChallenge)
 | 
							api.Put("/auth", startChallenge)
 | 
				
			||||||
		api.Post("/auth", doChallenge)
 | 
							api.Post("/auth", doChallenge)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
  <v-app-bar height="64" color="primary" scroll-behavior="elevate" flat>
 | 
					  <v-app-bar height="64" color="primary" scroll-behavior="elevate" flat>
 | 
				
			||||||
    <div class="max-md:px-5 md:px-12 flex flex-grow-1 items-center">
 | 
					    <div class="max-md:px-5 md:px-12 flex flex-grow-1 items-center">
 | 
				
			||||||
      <router-link :to="{ name: 'dashboard' }" class="flex gap-1">
 | 
					      <router-link :to="{ name: 'dashboard' }" class="flex gap-1">
 | 
				
			||||||
        <img src="/favicon.png" width="24" height="24" class="icon-filter" />
 | 
					        <img src="/favicon.png" width="27" height="24" class="icon-filter" />
 | 
				
			||||||
        <h2 class="ml-2 text-lg font-500">Solarpass</h2>
 | 
					        <h2 class="ml-2 text-lg font-500">Solarpass</h2>
 | 
				
			||||||
      </router-link>
 | 
					      </router-link>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <v-container class="pt-6 px-6">
 | 
					  <v-container class="pt-6 px-6">
 | 
				
			||||||
    <v-row>
 | 
					    <v-row>
 | 
				
			||||||
      <v-col :xs="12" :sm="12" :md="4" :lg="3">
 | 
					      <v-col :cols="12" :xs="12" :sm="12" :md="4" :lg="3">
 | 
				
			||||||
        <v-card title="Navigation">
 | 
					        <v-card title="Navigation">
 | 
				
			||||||
          <v-list density="comfortable">
 | 
					          <v-list density="comfortable">
 | 
				
			||||||
            <v-list-item title="Dashboard" prepend-icon="mdi-view-dashboard" :to="{ name: 'dashboard' }" exact />
 | 
					            <v-list-item title="Dashboard" prepend-icon="mdi-view-dashboard" :to="{ name: 'dashboard' }" exact />
 | 
				
			||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
        </v-card>
 | 
					        </v-card>
 | 
				
			||||||
      </v-col>
 | 
					      </v-col>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <v-col :xs="12" :sm="12" :md="8" :lg="9">
 | 
					      <v-col :cols="12" :xs="12" :sm="12" :md="8" :lg="9">
 | 
				
			||||||
        <router-view />
 | 
					        <router-view />
 | 
				
			||||||
      </v-col>
 | 
					      </v-col>
 | 
				
			||||||
    </v-row>
 | 
					    </v-row>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,29 +70,44 @@
 | 
				
			|||||||
    </v-card>
 | 
					    </v-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <v-card>
 | 
					    <v-card>
 | 
				
			||||||
      <template #text>
 | 
					      <v-card-text class="flex items-center gap-3">
 | 
				
			||||||
        <div class="flex items-center gap-3">
 | 
					        <v-avatar
 | 
				
			||||||
          <v-avatar
 | 
					          color="grey-lighten-2"
 | 
				
			||||||
            color="grey-lighten-2"
 | 
					          icon="mdi-account-circle"
 | 
				
			||||||
            icon="mdi-account-circle"
 | 
					          class="rounded-card"
 | 
				
			||||||
            class="rounded-card"
 | 
					          size="large"
 | 
				
			||||||
            size="large"
 | 
					          :image="'/api/avatar/' + id.userinfo.data.avatar"
 | 
				
			||||||
            :image="'/api/avatar/' + id.userinfo.data.avatar"
 | 
					        />
 | 
				
			||||||
          />
 | 
					        <v-file-input
 | 
				
			||||||
          <v-file-input
 | 
					          clearable
 | 
				
			||||||
            clearable
 | 
					          hide-details
 | 
				
			||||||
            hide-details
 | 
					          label="Upload another avatar"
 | 
				
			||||||
            label="Upload another avatar"
 | 
					          variant="outlined"
 | 
				
			||||||
            variant="outlined"
 | 
					          density="comfortable"
 | 
				
			||||||
            density="comfortable"
 | 
					          accept="image/*"
 | 
				
			||||||
            accept="image/*"
 | 
					          prepend-icon=""
 | 
				
			||||||
            prepend-icon=""
 | 
					          append-icon="mdi-upload"
 | 
				
			||||||
            append-icon="mdi-upload"
 | 
					          v-model="avatar"
 | 
				
			||||||
            v-model="avatar"
 | 
					          @click:append="applyAvatar"
 | 
				
			||||||
            @click:append="applyAvatar"
 | 
					        />
 | 
				
			||||||
          />
 | 
					      </v-card-text>
 | 
				
			||||||
        </div>
 | 
					
 | 
				
			||||||
      </template>
 | 
					      <v-img cover class="bg-grey-lighten-2" :height="320" :src="'/api/avatar/' + id.userinfo.data.banner" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <v-card-text>
 | 
				
			||||||
 | 
					        <v-file-input
 | 
				
			||||||
 | 
					          clearable
 | 
				
			||||||
 | 
					          hide-details
 | 
				
			||||||
 | 
					          label="Update your banner"
 | 
				
			||||||
 | 
					          variant="outlined"
 | 
				
			||||||
 | 
					          density="compact"
 | 
				
			||||||
 | 
					          accept="image/*"
 | 
				
			||||||
 | 
					          prepend-icon=""
 | 
				
			||||||
 | 
					          append-icon="mdi-upload"
 | 
				
			||||||
 | 
					          v-model="banner"
 | 
				
			||||||
 | 
					          @click:append="applyBanner"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </v-card-text>
 | 
				
			||||||
    </v-card>
 | 
					    </v-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <v-snackbar v-model="done" :timeout="3000"> Your personal information has been updated. </v-snackbar>
 | 
					    <v-snackbar v-model="done" :timeout="3000"> Your personal information has been updated. </v-snackbar>
 | 
				
			||||||
@@ -115,6 +130,7 @@ const loading = ref(false)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const data = ref<any>({})
 | 
					const data = ref<any>({})
 | 
				
			||||||
const avatar = ref<any>(null)
 | 
					const avatar = ref<any>(null)
 | 
				
			||||||
 | 
					const banner = ref<any>(null)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(
 | 
					watch(
 | 
				
			||||||
  id,
 | 
					  id,
 | 
				
			||||||
@@ -161,7 +177,7 @@ async function applyAvatar() {
 | 
				
			|||||||
  payload.set("avatar", avatar.value[0])
 | 
					  payload.set("avatar", avatar.value[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  loading.value = true
 | 
					  loading.value = true
 | 
				
			||||||
  const res = await request("/api/avatar", {
 | 
					  const res = await request("/api/users/me/avatar", {
 | 
				
			||||||
    method: "PUT",
 | 
					    method: "PUT",
 | 
				
			||||||
    headers: { Authorization: `Bearer ${getAtk()}` },
 | 
					    headers: { Authorization: `Bearer ${getAtk()}` },
 | 
				
			||||||
    body: payload,
 | 
					    body: payload,
 | 
				
			||||||
@@ -176,6 +192,31 @@ async function applyAvatar() {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  loading.value = false
 | 
					  loading.value = false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function applyBanner() {
 | 
				
			||||||
 | 
					  if (!banner.value) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (loading.value) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const payload = new FormData()
 | 
				
			||||||
 | 
					  payload.set("banner", banner.value[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  loading.value = true
 | 
				
			||||||
 | 
					  const res = await request("/api/users/me/banner", {
 | 
				
			||||||
 | 
					    method: "PUT",
 | 
				
			||||||
 | 
					    headers: { Authorization: `Bearer ${getAtk()}` },
 | 
				
			||||||
 | 
					    body: payload,
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  if (res.status !== 200) {
 | 
				
			||||||
 | 
					    error.value = await res.text()
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    await id.readProfiles()
 | 
				
			||||||
 | 
					    done.value = true
 | 
				
			||||||
 | 
					    error.value = null
 | 
				
			||||||
 | 
					    banner.value = null
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  loading.value = false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style>
 | 
					<style>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user