diff --git a/greataped/components/api/handlers/factory.go b/greataped/components/api/handlers/factory.go index 1894215..1063de2 100644 --- a/greataped/components/api/handlers/factory.go +++ b/greataped/components/api/handlers/factory.go @@ -13,6 +13,7 @@ func (factory *httpHandlerFactory) Handlers() []IHttpHandler { GetProfileByUserHandler(), // │ G . /api/v1/profile UpdateProfileByUserHandler(), // │ P . /api/v1/profile LogoutHandler(), // │ P . /api/v1/logout + WebfingerHandler(), // │ G . /.well-known/webfinger } } diff --git a/greataped/components/api/handlers/webfinger_handler.go b/greataped/components/api/handlers/webfinger_handler.go new file mode 100644 index 0000000..c8b829b --- /dev/null +++ b/greataped/components/api/handlers/webfinger_handler.go @@ -0,0 +1,45 @@ +package handlers + +import ( + "net/http" + + . "github.com/xeronith/diamante/contracts/network/http" + pipeline "github.com/xeronith/diamante/network/http" + . "rail.town/infrastructure/components/api/protobuf" + . "rail.town/infrastructure/components/contracts" +) + +type webfingerHandler struct { +} + +func WebfingerHandler() IHttpHandler { + return &webfingerHandler{} +} + +func (handler *webfingerHandler) Method() string { + return http.MethodGet +} + +func (handler *webfingerHandler) Path() string { + return "/.well-known/webfinger" +} + +func (handler *webfingerHandler) HandlerFunc() HttpHandlerFunc { + return func(x IServerDispatcher) error { + request := &WebfingerRequest{} + result := &WebfingerResult{} + + onRequestUnmarshalled := func(request *WebfingerRequest) { + request.Resource = x.Query("resource") + } + + return pipeline.Handle(x, + "webfinger", + WEBFINGER_REQUEST, + WEBFINGER_RESULT, + request, result, + onRequestUnmarshalled, + false, + ) + } +} diff --git a/greataped/components/api/operations/factory.go b/greataped/components/api/operations/factory.go index 0318529..4eaa642 100644 --- a/greataped/components/api/operations/factory.go +++ b/greataped/components/api/operations/factory.go @@ -14,6 +14,7 @@ func (factory *operationFactory) Operations() []IOperation { GetProfileByUserOperation(), UpdateProfileByUserOperation(), LogoutOperation(), + WebfingerOperation(), } } diff --git a/greataped/components/api/operations/webfinger_operation.go b/greataped/components/api/operations/webfinger_operation.go new file mode 100644 index 0000000..cfa77e8 --- /dev/null +++ b/greataped/components/api/operations/webfinger_operation.go @@ -0,0 +1,51 @@ +package operations + +import ( + . "github.com/xeronith/diamante/contracts/operation" + . "github.com/xeronith/diamante/contracts/service" + . "github.com/xeronith/diamante/contracts/system" + . "github.com/xeronith/diamante/operation" + . "rail.town/infrastructure/components/api/protobuf" + . "rail.town/infrastructure/components/api/services" + . "rail.town/infrastructure/components/contracts" +) + +type webfingerOperation struct { + Operation + + run func(IContext, *WebfingerRequest) (*WebfingerResult, error) +} + +func WebfingerOperation() IOperation { + return &webfingerOperation{ + run: WebfingerService, + } +} + +func (operation *webfingerOperation) Id() (ID, ID) { + return WEBFINGER_REQUEST, WEBFINGER_RESULT +} + +func (operation *webfingerOperation) InputContainer() Pointer { + return new(WebfingerRequest) +} + +func (operation *webfingerOperation) OutputContainer() Pointer { + return new(WebfingerResult) +} + +func (operation *webfingerOperation) Execute(context IContext, payload Pointer) (Pointer, error) { + return operation.run(context, payload.(*WebfingerRequest)) +} + +/* +func (operation *webfingerOperation) ExecutionTimeLimits() (Duration, Duration, Duration) { + var ( + TIME_LIMIT_WARNING Duration = 20_000_000 + TIME_LIMIT_ALERT Duration = 35_000_000 + TIME_LIMIT_CRITICAL Duration = 50_000_000 + ) + + return TIME_LIMIT_WARNING, TIME_LIMIT_ALERT, TIME_LIMIT_CRITICAL +} +*/ diff --git a/greataped/components/api/protobuf/spis.pb.go b/greataped/components/api/protobuf/spis.pb.go index 224084e..42d1237 100644 --- a/greataped/components/api/protobuf/spis.pb.go +++ b/greataped/components/api/protobuf/spis.pb.go @@ -912,6 +912,118 @@ func (*LogoutResult) Descriptor() ([]byte, []int) { return file_spis_proto_rawDescGZIP(), []int{15} } +// API: Webfinger +// ----------------------------------------------------------- +type WebfingerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resource string `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` +} + +func (x *WebfingerRequest) Reset() { + *x = WebfingerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_spis_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WebfingerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WebfingerRequest) ProtoMessage() {} + +func (x *WebfingerRequest) ProtoReflect() protoreflect.Message { + mi := &file_spis_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WebfingerRequest.ProtoReflect.Descriptor instead. +func (*WebfingerRequest) Descriptor() ([]byte, []int) { + return file_spis_proto_rawDescGZIP(), []int{16} +} + +func (x *WebfingerRequest) GetResource() string { + if x != nil { + return x.Resource + } + return "" +} + +type WebfingerResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Aliases []string `protobuf:"bytes,1,rep,name=aliases,proto3" json:"aliases,omitempty"` + Links []*ActivityPubLink `protobuf:"bytes,2,rep,name=links,proto3" json:"links,omitempty"` + Subject string `protobuf:"bytes,3,opt,name=subject,proto3" json:"subject,omitempty"` +} + +func (x *WebfingerResult) Reset() { + *x = WebfingerResult{} + if protoimpl.UnsafeEnabled { + mi := &file_spis_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WebfingerResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WebfingerResult) ProtoMessage() {} + +func (x *WebfingerResult) ProtoReflect() protoreflect.Message { + mi := &file_spis_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WebfingerResult.ProtoReflect.Descriptor instead. +func (*WebfingerResult) Descriptor() ([]byte, []int) { + return file_spis_proto_rawDescGZIP(), []int{17} +} + +func (x *WebfingerResult) GetAliases() []string { + if x != nil { + return x.Aliases + } + return nil +} + +func (x *WebfingerResult) GetLinks() []*ActivityPubLink { + if x != nil { + return x.Links + } + return nil +} + +func (x *WebfingerResult) GetSubject() string { + if x != nil { + return x.Subject + } + return "" +} + var File_spis_proto protoreflect.FileDescriptor var file_spis_proto_rawDesc = []byte{ @@ -990,8 +1102,18 @@ var file_spis_proto_rawDesc = []byte{ 0x69, 0x74, 0x68, 0x75, 0x62, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x22, 0x0f, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x42, 0x04, 0x5a, 0x02, 0x2e, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x73, 0x75, 0x6c, 0x74, 0x22, 0x2e, 0x0a, 0x10, 0x57, 0x65, 0x62, 0x66, 0x69, 0x6e, 0x67, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x22, 0x76, 0x0a, 0x0f, 0x57, 0x65, 0x62, 0x66, 0x69, 0x6e, 0x67, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, + 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x50, 0x75, 0x62, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x05, 0x6c, 0x69, 0x6e, + 0x6b, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x04, 0x5a, 0x02, + 0x2e, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1006,7 +1128,7 @@ func file_spis_proto_rawDescGZIP() []byte { return file_spis_proto_rawDescData } -var file_spis_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_spis_proto_msgTypes = make([]protoimpl.MessageInfo, 18) var file_spis_proto_goTypes = []interface{}{ (*SystemCallRequest)(nil), // 0: protobuf.SystemCallRequest (*SystemCallResult)(nil), // 1: protobuf.SystemCallResult @@ -1024,16 +1146,20 @@ var file_spis_proto_goTypes = []interface{}{ (*UpdateProfileByUserResult)(nil), // 13: protobuf.UpdateProfileByUserResult (*LogoutRequest)(nil), // 14: protobuf.LogoutRequest (*LogoutResult)(nil), // 15: protobuf.LogoutResult - (*Document)(nil), // 16: protobuf.Document + (*WebfingerRequest)(nil), // 16: protobuf.WebfingerRequest + (*WebfingerResult)(nil), // 17: protobuf.WebfingerResult + (*Document)(nil), // 18: protobuf.Document + (*ActivityPubLink)(nil), // 19: protobuf.ActivityPubLink } var file_spis_proto_depIdxs = []int32{ - 16, // 0: protobuf.EchoRequest.document:type_name -> protobuf.Document - 16, // 1: protobuf.EchoResult.document:type_name -> protobuf.Document - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 18, // 0: protobuf.EchoRequest.document:type_name -> protobuf.Document + 18, // 1: protobuf.EchoResult.document:type_name -> protobuf.Document + 19, // 2: protobuf.WebfingerResult.links:type_name -> protobuf.ActivityPubLink + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_spis_proto_init() } @@ -1235,6 +1361,30 @@ func file_spis_proto_init() { return nil } } + file_spis_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WebfingerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_spis_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WebfingerResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1242,7 +1392,7 @@ func file_spis_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_spis_proto_rawDesc, NumEnums: 0, - NumMessages: 16, + NumMessages: 18, NumExtensions: 0, NumServices: 0, }, diff --git a/greataped/components/api/protobuf/spis.proto b/greataped/components/api/protobuf/spis.proto index f82658c..477427a 100644 --- a/greataped/components/api/protobuf/spis.proto +++ b/greataped/components/api/protobuf/spis.proto @@ -102,4 +102,16 @@ message LogoutRequest { message LogoutResult { } +// API: Webfinger +//----------------------------------------------------------- +message WebfingerRequest { + string resource = 0x00000001; +} + +message WebfingerResult { + repeated string aliases = 0x00000001; + repeated ActivityPubLink links = 0x00000002; + string subject = 0x00000003; +} + //----------------------------------------------------------- diff --git a/greataped/components/api/services/webfinger_service.go b/greataped/components/api/services/webfinger_service.go new file mode 100644 index 0000000..fd2c46f --- /dev/null +++ b/greataped/components/api/services/webfinger_service.go @@ -0,0 +1,45 @@ +package services + +import ( + . "github.com/xeronith/diamante/contracts/service" + . "rail.town/infrastructure/components/api/protobuf" + . "rail.town/infrastructure/components/contracts" + "rail.town/infrastructure/components/core" +) + +// noinspection GoUnusedParameter +func WebfingerService(context IContext, input *WebfingerRequest) (result *WebfingerResult, err error) { + conductor := core.Conductor + _ = WEBFINGER_REQUEST + + conductor.LogRemoteCall(context, INITIALIZE, "webfinger", input, result, err) + defer func() { conductor.LogRemoteCall(context, FINALIZE, "webfinger", input, result, err) }() + + _result, _err := conductor.Webfinger(input.Resource, context.Identity()) + if _err != nil { + err = _err + return nil, err + } + + _ = _result + + outputLinks := make([]*ActivityPubLink, 0) + for _, link := range _result.Links() { + if link == nil { + continue + } + + outputLinks = append(outputLinks, &ActivityPubLink{ + Href: link.Href(), + Rel: link.Rel(), + Type: link.Type(), + Template: link.Template(), + }) + } + + result = context.ResultContainer().(*WebfingerResult) + result.Aliases = _result.Aliases() + result.Links = outputLinks + result.Subject = _result.Subject() + return result, nil +} diff --git a/greataped/components/constants/errors.go b/greataped/components/constants/errors.go index 7ddf91b..a527c73 100644 --- a/greataped/components/constants/errors.go +++ b/greataped/components/constants/errors.go @@ -55,6 +55,7 @@ const ( ERROR_MESSAGE_INVALID_EMAIL_FOR_VERIFY = "ERROR_MESSAGE_INVALID_EMAIL_FOR_VERIFY" ERROR_MESSAGE_INVALID_EMAIL_FOR_LOGIN = "ERROR_MESSAGE_INVALID_EMAIL_FOR_LOGIN" ERROR_MESSAGE_INVALID_PASSWORD_FOR_LOGIN = "ERROR_MESSAGE_INVALID_PASSWORD_FOR_LOGIN" + ERROR_MESSAGE_INVALID_RESOURCE_FOR_WEBFINGER = "ERROR_MESSAGE_INVALID_RESOURCE_FOR_WEBFINGER" // CUSTOM_ERRORS ERROR_MESSAGE_DATA_INTEGRITY_VIOLATION = "ERROR_MESSAGE_DATA_INTEGRITY_VIOLATION" ERROR_MESSAGE_INVALID_STATE = "ERROR_MESSAGE_INVALID_STATE" @@ -119,6 +120,7 @@ var ( ERROR_INVALID_EMAIL_FOR_VERIFY = errors.New(ERROR_MESSAGE_INVALID_EMAIL_FOR_VERIFY) ERROR_INVALID_EMAIL_FOR_LOGIN = errors.New(ERROR_MESSAGE_INVALID_EMAIL_FOR_LOGIN) ERROR_INVALID_PASSWORD_FOR_LOGIN = errors.New(ERROR_MESSAGE_INVALID_PASSWORD_FOR_LOGIN) + ERROR_INVALID_RESOURCE_FOR_WEBFINGER = errors.New(ERROR_MESSAGE_INVALID_RESOURCE_FOR_WEBFINGER) // CUSTOM_ERRORS ERROR_DATA_INTEGRITY_VIOLATION = errors.New(ERROR_MESSAGE_DATA_INTEGRITY_VIOLATION) ERROR_INVALID_STATE = errors.New(ERROR_MESSAGE_INVALID_STATE) diff --git a/greataped/components/constants/resources.en-US.go b/greataped/components/constants/resources.en-US.go index 452c208..5449ac7 100644 --- a/greataped/components/constants/resources.en-US.go +++ b/greataped/components/constants/resources.en-US.go @@ -52,6 +52,7 @@ var Errors = Resource{ ERROR_MESSAGE_INVALID_EMAIL_FOR_VERIFY: "invalid_email", ERROR_MESSAGE_INVALID_EMAIL_FOR_LOGIN: "invalid_email", ERROR_MESSAGE_INVALID_PASSWORD_FOR_LOGIN: "invalid_password", + ERROR_MESSAGE_INVALID_RESOURCE_FOR_WEBFINGER: "invalid_resource", // CUSTOM_ERRORS ERROR_MESSAGE_DATA_INTEGRITY_VIOLATION: "data_integrity_violation", ERROR_MESSAGE_INVALID_STATE: "invalid_state", diff --git a/greataped/components/contracts/api.go b/greataped/components/contracts/api.go index d1fb485..da65cfa 100644 --- a/greataped/components/contracts/api.go +++ b/greataped/components/contracts/api.go @@ -14,4 +14,5 @@ type IApi interface { GetProfileByUser(*GetProfileByUserRequest) (*GetProfileByUserResult, error) UpdateProfileByUser(*UpdateProfileByUserRequest) (*UpdateProfileByUserResult, error) Logout(*LogoutRequest) (*LogoutResult, error) + Webfinger(*WebfingerRequest) (*WebfingerResult, error) } diff --git a/greataped/components/contracts/opcodes.go b/greataped/components/contracts/opcodes.go index eb60b0e..8514227 100644 --- a/greataped/components/contracts/opcodes.go +++ b/greataped/components/contracts/opcodes.go @@ -35,6 +35,10 @@ const ( //LogoutOperation LOGOUT_REQUEST = 0x447AFA34 LOGOUT_RESULT = 0x9412D17F + + //WebfingerOperation + WEBFINGER_REQUEST = 0x01FD357C + WEBFINGER_RESULT = 0xCC81EC52 ) var OPCODES = Opcodes{ @@ -53,4 +57,6 @@ var OPCODES = Opcodes{ 0x678A8BAF: "UpdateProfileByUser", 0x447AFA34: "LOGOUT", 0x9412D17F: "Logout", + 0x01FD357C: "WEBFINGER", + 0xCC81EC52: "Webfinger", } diff --git a/greataped/components/contracts/spi.go b/greataped/components/contracts/spi.go index fbcc957..8f92f16 100644 --- a/greataped/components/contracts/spi.go +++ b/greataped/components/contracts/spi.go @@ -61,6 +61,7 @@ type ( GetProfileByUser(editor Identity) (IGetProfileByUserResult, error) UpdateProfileByUser(displayName string, avatar string, banner string, summary string, github string, editor Identity) (IUpdateProfileByUserResult, error) Logout(editor Identity) (ILogoutResult, error) + Webfinger(resource string, editor Identity) (IWebfingerResult, error) } IEchoResult interface { @@ -100,4 +101,10 @@ type ( ILogoutResult interface { } + + IWebfingerResult interface { + Aliases() []string + Links() []IActivityPubLink + Subject() string + } ) diff --git a/greataped/components/contracts/system_component.go b/greataped/components/contracts/system_component.go index b71d2f1..b49cf7f 100644 --- a/greataped/components/contracts/system_component.go +++ b/greataped/components/contracts/system_component.go @@ -264,6 +264,7 @@ type ( GetProfileByUser(editor Identity) (IGetProfileByUserResult, error) UpdateProfileByUser(displayName string, avatar string, banner string, summary string, github string, editor Identity) (IUpdateProfileByUserResult, error) Logout(editor Identity) (ILogoutResult, error) + Webfinger(resource string, editor Identity) (IWebfingerResult, error) NewDocument(id int64, content string) (IDocument, error) NewSystemSchedule(id int64, enabled bool, config string) (ISystemSchedule, error) @@ -289,6 +290,7 @@ type ( NewGetProfileByUserResult(username string, displayName string, avatar string, banner string, summary string, github string, ignored interface{}) IGetProfileByUserResult NewUpdateProfileByUserResult(displayName string, avatar string, banner string, summary string, github string, ignored interface{}) IUpdateProfileByUserResult NewLogoutResult(ignored interface{}) ILogoutResult + NewWebfingerResult(aliases []string, links []IActivityPubLink, subject string, ignored interface{}) IWebfingerResult } ISystemComponent interface { diff --git a/greataped/components/contracts/system_dispatcher.go b/greataped/components/contracts/system_dispatcher.go index 143848c..b4b87c2 100644 --- a/greataped/components/contracts/system_dispatcher.go +++ b/greataped/components/contracts/system_dispatcher.go @@ -1038,6 +1038,7 @@ type IDispatcher interface { GetProfileByUser() (IGetProfileByUserResult, error) UpdateProfileByUser(displayName string, avatar string, banner string, summary string, github string) (IUpdateProfileByUserResult, error) Logout() (ILogoutResult, error) + Webfinger(resource string) (IWebfingerResult, error) // NewDocument creates a new 'Document' instance using the provided property values. NewDocument(id int64, content string) (IDocument, error) @@ -1121,6 +1122,8 @@ type IDispatcher interface { NewUpdateProfileByUserResult(displayName string, avatar string, banner string, summary string, github string) IUpdateProfileByUserResult // NewLogoutResult creates a new result container for 'Logout' system action. NewLogoutResult() ILogoutResult + // NewWebfingerResult creates a new result container for 'Webfinger' system action. + NewWebfingerResult(aliases []string, links []IActivityPubLink, subject string) IWebfingerResult // Assert asserts the provided condition and panics if the assertion is not valid. Assert(condition bool) IAssertionResult // AssertNoError panics if the provided error is not nil. diff --git a/greataped/components/core/api_methods.go b/greataped/components/core/api_methods.go index 2428c4c..dcd7d98 100644 --- a/greataped/components/core/api_methods.go +++ b/greataped/components/core/api_methods.go @@ -85,6 +85,16 @@ func (api *api) Logout(request *LogoutRequest) (*LogoutResult, error) { } } +func (api *api) Webfinger(request *WebfingerRequest) (*WebfingerResult, error) { + result, err := api.call(WEBFINGER_REQUEST, request) + + if err != nil { + return nil, err + } else { + return result.(*WebfingerResult), nil + } +} + func init() { API_RESULT[SYSTEM_CALL_RESULT] = SystemCallResult{} API_RESULT[ECHO_RESULT] = EchoResult{} @@ -94,4 +104,5 @@ func init() { API_RESULT[GET_PROFILE_BY_USER_RESULT] = GetProfileByUserResult{} API_RESULT[UPDATE_PROFILE_BY_USER_RESULT] = UpdateProfileByUserResult{} API_RESULT[LOGOUT_RESULT] = LogoutResult{} + API_RESULT[WEBFINGER_RESULT] = WebfingerResult{} } diff --git a/greataped/components/core/initializer.go b/greataped/components/core/initializer.go index ad1177f..b2e1050 100644 --- a/greataped/components/core/initializer.go +++ b/greataped/components/core/initializer.go @@ -1123,6 +1123,10 @@ func (conductor *conductor) Logout(editor Identity) (ILogoutResult, error) { return conductor.spiManager.Logout(editor) } +func (conductor *conductor) Webfinger(resource string, editor Identity) (IWebfingerResult, error) { + return conductor.spiManager.Webfinger(resource, editor) +} + func (conductor *conductor) NewDocument(id int64, content string) (IDocument, error) { return NewDocument(id, content) } @@ -1219,6 +1223,10 @@ func (conductor *conductor) NewLogoutResult(_ interface{}) ILogoutResult { return NewLogoutResult(nil) } +func (conductor *conductor) NewWebfingerResult(aliases []string, links []IActivityPubLink, subject string, _ interface{}) IWebfingerResult { + return NewWebfingerResult(aliases, links, subject, nil) +} + func (conductor *conductor) LogRemoteCall(context IContext, eventType uint32, source string, input, result interface{}, err error) { errorMessage := "" if err != nil { diff --git a/greataped/components/core/spi.go b/greataped/components/core/spi.go index 9e579db..701b60a 100644 --- a/greataped/components/core/spi.go +++ b/greataped/components/core/spi.go @@ -262,3 +262,7 @@ func (dispatcher *dispatcher) UpdateProfileByUser(displayName string, avatar str func (dispatcher *dispatcher) Logout() (ILogoutResult, error) { return dispatcher.conductor.SpiManager().Logout(dispatcher.identity) } + +func (dispatcher *dispatcher) Webfinger(resource string) (IWebfingerResult, error) { + return dispatcher.conductor.SpiManager().Webfinger(resource, dispatcher.identity) +} diff --git a/greataped/components/core/spi_manager.go b/greataped/components/core/spi_manager.go index 737a6ec..7c32103 100644 --- a/greataped/components/core/spi_manager.go +++ b/greataped/components/core/spi_manager.go @@ -531,3 +531,56 @@ func (manager *spiManager) Logout(editor Identity) (result ILogoutResult, err er return result, nil } } + +//region IWebfingerResult Implementation + +type webfingerResult struct { + aliases []string + links []IActivityPubLink + subject string +} + +func NewWebfingerResult(aliases []string, links []IActivityPubLink, subject string, _ interface{}) IWebfingerResult { + return &webfingerResult{ + aliases: aliases, + links: links, + subject: subject, + } +} + +func (result webfingerResult) Aliases() []string { + return result.aliases +} + +func (result webfingerResult) Links() []IActivityPubLink { + return result.links +} + +func (result webfingerResult) Subject() string { + return result.subject +} + +//endregion + +func (manager *spiManager) Webfinger(resource string, editor Identity) (result IWebfingerResult, err error) { + if match, err := manager.Match(WEBFINGER, resource); err != nil { + return nil, err + } else if !match { + return nil, ERROR_INVALID_RESOURCE_FOR_WEBFINGER + } + + defer func() { + if reason := recover(); reason != nil { + err = manager.Error(reason) + } + }() + + editor.Lock(WEBFINGER_REQUEST) + defer editor.Unlock(WEBFINGER_REQUEST) + + if result, err = commands.Webfinger(NewDispatcher(Conductor, editor), resource); err != nil { + return nil, err + } else { + return result, nil + } +} diff --git a/greataped/components/core/system_results.go b/greataped/components/core/system_results.go index 020a583..fcb848c 100644 --- a/greataped/components/core/system_results.go +++ b/greataped/components/core/system_results.go @@ -32,4 +32,8 @@ func (dispatcher *dispatcher) NewLogoutResult() ILogoutResult { return NewLogoutResult(nil) } +func (dispatcher *dispatcher) NewWebfingerResult(aliases []string, links []IActivityPubLink, subject string) IWebfingerResult { + return NewWebfingerResult(aliases, links, subject, nil) +} + //endregion diff --git a/greataped/go.mod b/greataped/go.mod index 5efd030..b305afe 100644 --- a/greataped/go.mod +++ b/greataped/go.mod @@ -6,7 +6,7 @@ require ( github.com/google/uuid v1.3.0 github.com/robfig/cron v1.2.0 github.com/sendgrid/sendgrid-go v3.12.0+incompatible - github.com/xeronith/diamante v1.5.2 + github.com/xeronith/diamante v1.5.3 google.golang.org/protobuf v1.28.1 ) diff --git a/greataped/go.sum b/greataped/go.sum index be059a7..86bb35a 100644 --- a/greataped/go.sum +++ b/greataped/go.sum @@ -68,8 +68,8 @@ github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/xeronith/diamante v1.5.2 h1:Q665puGNc62RpxyhyoLcC/hS/KjgddkkO3upDmVlsig= -github.com/xeronith/diamante v1.5.2/go.mod h1:AcsIxTtJIYfIp/Sk6kMOp0qfPGNhDDPWksvYzpbZtG0= +github.com/xeronith/diamante v1.5.3 h1:6vGyUP6p8HVE4spd9roEvtFUG83GxJXax63OfWF8vbQ= +github.com/xeronith/diamante v1.5.3/go.mod h1:AcsIxTtJIYfIp/Sk6kMOp0qfPGNhDDPWksvYzpbZtG0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=