migrate from github
This commit is contained in:
@@ -0,0 +1,781 @@
|
||||
package connectserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/XingfenD/yoresee_doc/internal/repository"
|
||||
"github.com/XingfenD/yoresee_doc/internal/transport/grpcserver"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
func registerHandlers(mux *http.ServeMux, opts []connect.HandlerOption, repos *repository.Repositories) {
|
||||
authSvc := grpcserver.NewAuthServiceServer()
|
||||
docSvc := grpcserver.NewDocumentServiceServer()
|
||||
kbSvc := grpcserver.NewKnowledgeBaseServiceServer()
|
||||
sysSvc := grpcserver.NewSystemServiceServer()
|
||||
settingSvc := grpcserver.NewSettingServiceServer()
|
||||
memberSvc := grpcserver.NewMembershipServiceServer()
|
||||
inviteSvc := grpcserver.NewInvitationServiceServer(repos.User)
|
||||
notifySvc := grpcserver.NewNotificationServiceServer()
|
||||
commentSvc := grpcserver.NewCommentServiceServer(repos.User, repos.Document)
|
||||
|
||||
mux.Handle(pb.AuthService_Login_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.AuthService_Login_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.AuthLoginRequest]) (*connect.Response[pb.AuthLoginResponse], error) {
|
||||
resp, err := authSvc.Login(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.AuthService_Register_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.AuthService_Register_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.AuthRegisterRequest]) (*connect.Response[pb.AuthRegisterResponse], error) {
|
||||
resp, err := authSvc.Register(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.AuthService_UpdateProfile_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.AuthService_UpdateProfile_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateProfileRequest]) (*connect.Response[pb.UpdateProfileResponse], error) {
|
||||
resp, err := authSvc.UpdateProfile(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.AuthService_QuerySideBarDisplay_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.AuthService_QuerySideBarDisplay_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.QuerySideBarDisplayRequest]) (*connect.Response[pb.QuerySideBarDisplayResponse], error) {
|
||||
resp, err := authSvc.QuerySideBarDisplay(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.AuthService_QueryTopNavDisplay_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.AuthService_QueryTopNavDisplay_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.QueryTopNavDisplayRequest]) (*connect.Response[pb.QueryTopNavDisplayResponse], error) {
|
||||
resp, err := authSvc.QueryTopNavDisplay(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_ListDocuments_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_ListDocuments_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListDocumentsRequest]) (*connect.Response[pb.ListDocumentsResponse], error) {
|
||||
resp, err := docSvc.ListDocuments(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_GetDocumentContent_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_GetDocumentContent_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetDocumentContentRequest]) (*connect.Response[pb.GetDocumentContentResponse], error) {
|
||||
resp, err := docSvc.GetDocumentContent(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.DocumentService_GetDocumentSettings_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_GetDocumentSettings_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetDocumentSettingsRequest]) (*connect.Response[pb.GetDocumentSettingsResponse], error) {
|
||||
resp, err := docSvc.GetDocumentSettings(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.DocumentService_RecordRecentDocument_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_RecordRecentDocument_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.RecordRecentDocumentRequest]) (*connect.Response[pb.RecordRecentDocumentResponse], error) {
|
||||
resp, err := docSvc.RecordRecentDocument(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.DocumentService_ListRecentDocuments_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_ListRecentDocuments_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListRecentDocumentsRequest]) (*connect.Response[pb.ListRecentDocumentsResponse], error) {
|
||||
resp, err := docSvc.ListRecentDocuments(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_GetDocumentYjsSnapshot_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_GetDocumentYjsSnapshot_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetDocumentYjsSnapshotRequest]) (*connect.Response[pb.GetDocumentYjsSnapshotResponse], error) {
|
||||
resp, err := docSvc.GetDocumentYjsSnapshot(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_SaveDocumentYjsSnapshot_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_SaveDocumentYjsSnapshot_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.SaveDocumentYjsSnapshotRequest]) (*connect.Response[pb.SaveDocumentYjsSnapshotResponse], error) {
|
||||
resp, err := docSvc.SaveDocumentYjsSnapshot(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_GetOwnDocuments_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_GetOwnDocuments_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetOwnDocumentsRequest]) (*connect.Response[pb.GetOwnDocumentsResponse], error) {
|
||||
resp, err := docSvc.GetOwnDocuments(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_CreateDocument_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_CreateDocument_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.CreateDocumentRequest]) (*connect.Response[pb.CreateDocumentResponse], error) {
|
||||
resp, err := docSvc.CreateDocument(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_UpdateDocumentMeta_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_UpdateDocumentMeta_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateDocumentMetaRequest]) (*connect.Response[pb.UpdateDocumentMetaResponse], error) {
|
||||
resp, err := docSvc.UpdateDocumentMeta(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.DocumentService_UpdateDocumentSettings_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_UpdateDocumentSettings_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateDocumentSettingsRequest]) (*connect.Response[pb.UpdateDocumentSettingsResponse], error) {
|
||||
resp, err := docSvc.UpdateDocumentSettings(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.DocumentService_UploadDocumentAttachment_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_UploadDocumentAttachment_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UploadDocumentAttachmentRequest]) (*connect.Response[pb.UploadDocumentAttachmentResponse], error) {
|
||||
resp, err := docSvc.UploadDocumentAttachment(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.DocumentService_ListDocumentAttachments_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_ListDocumentAttachments_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListDocumentAttachmentsRequest]) (*connect.Response[pb.ListDocumentAttachmentsResponse], error) {
|
||||
resp, err := docSvc.ListDocumentAttachments(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.DocumentService_DeleteDocumentAttachment_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_DeleteDocumentAttachment_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.DeleteDocumentAttachmentRequest]) (*connect.Response[pb.DeleteDocumentAttachmentResponse], error) {
|
||||
resp, err := docSvc.DeleteDocumentAttachment(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.DocumentService_ListDocumentVersions_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_ListDocumentVersions_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListDocumentVersionsRequest]) (*connect.Response[pb.ListDocumentVersionsResponse], error) {
|
||||
resp, err := docSvc.ListDocumentVersions(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
mux.Handle(pb.DocumentService_GetDocumentVersionContent_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_GetDocumentVersionContent_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetDocumentVersionContentRequest]) (*connect.Response[pb.GetDocumentVersionContentResponse], error) {
|
||||
resp, err := docSvc.GetDocumentVersionContent(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.KnowledgeBaseService_ListKnowledgeBases_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.KnowledgeBaseService_ListKnowledgeBases_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListKnowledgeBasesRequest]) (*connect.Response[pb.ListKnowledgeBasesResponse], error) {
|
||||
resp, err := kbSvc.ListKnowledgeBases(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.KnowledgeBaseService_GetKnowledgeBase_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.KnowledgeBaseService_GetKnowledgeBase_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetKnowledgeBaseRequest]) (*connect.Response[pb.GetKnowledgeBaseResponse], error) {
|
||||
resp, err := kbSvc.GetKnowledgeBase(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.KnowledgeBaseService_CreateKnowledgeBase_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.KnowledgeBaseService_CreateKnowledgeBase_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.CreateKnowledgeBaseRequest]) (*connect.Response[pb.CreateKnowledgeBaseResponse], error) {
|
||||
resp, err := kbSvc.CreateKnowledgeBase(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.KnowledgeBaseService_ListRecentKnowledgeBases_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.KnowledgeBaseService_ListRecentKnowledgeBases_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListRecentKnowledgeBasesRequest]) (*connect.Response[pb.ListRecentKnowledgeBasesResponse], error) {
|
||||
resp, err := kbSvc.ListRecentKnowledgeBases(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.SystemService_Health_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.SystemService_Health_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.HealthRequest]) (*connect.Response[pb.HealthResponse], error) {
|
||||
resp, err := sysSvc.Health(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.SystemService_SystemInfo_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.SystemService_SystemInfo_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.SystemInfoRequest]) (*connect.Response[pb.SystemInfoResponse], error) {
|
||||
resp, err := sysSvc.SystemInfo(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.SettingService_GetSettings_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.SettingService_GetSettings_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetSettingsRequest]) (*connect.Response[pb.GetSettingsResponse], error) {
|
||||
resp, err := settingSvc.GetSettings(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.SettingService_UpdateSettings_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.SettingService_UpdateSettings_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateSettingsRequest]) (*connect.Response[pb.UpdateSettingsResponse], error) {
|
||||
resp, err := settingSvc.UpdateSettings(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_ListUserGroups_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_ListUserGroups_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListUserGroupsRequest]) (*connect.Response[pb.ListUserGroupsResponse], error) {
|
||||
resp, err := memberSvc.ListUserGroups(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_GetUserGroup_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_GetUserGroup_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetUserGroupRequest]) (*connect.Response[pb.GetUserGroupResponse], error) {
|
||||
resp, err := memberSvc.GetUserGroup(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_CreateUserGroup_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_CreateUserGroup_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.CreateUserGroupRequest]) (*connect.Response[pb.CreateUserGroupResponse], error) {
|
||||
resp, err := memberSvc.CreateUserGroup(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_UpdateUserGroup_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_UpdateUserGroup_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateUserGroupRequest]) (*connect.Response[pb.UpdateUserGroupResponse], error) {
|
||||
resp, err := memberSvc.UpdateUserGroup(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_DeleteUserGroup_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_DeleteUserGroup_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.DeleteUserGroupRequest]) (*connect.Response[pb.DeleteUserGroupResponse], error) {
|
||||
resp, err := memberSvc.DeleteUserGroup(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_ListUsers_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_ListUsers_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListUsersRequest]) (*connect.Response[pb.ListUsersResponse], error) {
|
||||
resp, err := memberSvc.ListUsers(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_UpdateUser_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_UpdateUser_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateUserRequest]) (*connect.Response[pb.UpdateUserResponse], error) {
|
||||
resp, err := memberSvc.UpdateUser(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_ListUserGroupMembers_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_ListUserGroupMembers_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListUserGroupMembersRequest]) (*connect.Response[pb.ListUserGroupMembersResponse], error) {
|
||||
resp, err := memberSvc.ListUserGroupMembers(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_ListOrgNodes_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_ListOrgNodes_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListOrgNodesRequest]) (*connect.Response[pb.ListOrgNodesResponse], error) {
|
||||
resp, err := memberSvc.ListOrgNodes(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_GetOrgNode_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_GetOrgNode_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetOrgNodeRequest]) (*connect.Response[pb.GetOrgNodeResponse], error) {
|
||||
resp, err := memberSvc.GetOrgNode(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_CreateOrgNode_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_CreateOrgNode_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.CreateOrgNodeRequest]) (*connect.Response[pb.CreateOrgNodeResponse], error) {
|
||||
resp, err := memberSvc.CreateOrgNode(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_UpdateOrgNode_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_UpdateOrgNode_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateOrgNodeRequest]) (*connect.Response[pb.UpdateOrgNodeResponse], error) {
|
||||
resp, err := memberSvc.UpdateOrgNode(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_DeleteOrgNode_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_DeleteOrgNode_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.DeleteOrgNodeRequest]) (*connect.Response[pb.DeleteOrgNodeResponse], error) {
|
||||
resp, err := memberSvc.DeleteOrgNode(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_MoveOrgNode_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_MoveOrgNode_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.MoveOrgNodeRequest]) (*connect.Response[pb.MoveOrgNodeResponse], error) {
|
||||
resp, err := memberSvc.MoveOrgNode(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.MembershipService_ListOrgNodeMembers_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.MembershipService_ListOrgNodeMembers_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListOrgNodeMembersRequest]) (*connect.Response[pb.ListOrgNodeMembersResponse], error) {
|
||||
resp, err := memberSvc.ListOrgNodeMembers(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.InvitationService_CreateInvitation_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.InvitationService_CreateInvitation_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.CreateInvitationRequest]) (*connect.Response[pb.CreateInvitationResponse], error) {
|
||||
resp, err := inviteSvc.CreateInvitation(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.InvitationService_ListInvitations_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.InvitationService_ListInvitations_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListInvitationsRequest]) (*connect.Response[pb.ListInvitationsResponse], error) {
|
||||
resp, err := inviteSvc.ListInvitations(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.InvitationService_UpdateInvitation_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.InvitationService_UpdateInvitation_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateInvitationRequest]) (*connect.Response[pb.UpdateInvitationResponse], error) {
|
||||
resp, err := inviteSvc.UpdateInvitation(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.InvitationService_DeleteInvitation_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.InvitationService_DeleteInvitation_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.DeleteInvitationRequest]) (*connect.Response[pb.DeleteInvitationResponse], error) {
|
||||
resp, err := inviteSvc.DeleteInvitation(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.InvitationService_ListInvitationRecords_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.InvitationService_ListInvitationRecords_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListInvitationRecordsRequest]) (*connect.Response[pb.ListInvitationRecordsResponse], error) {
|
||||
resp, err := inviteSvc.ListInvitationRecords(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.NotificationService_CreateNotification_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.NotificationService_CreateNotification_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.CreateNotificationRequest]) (*connect.Response[pb.CreateNotificationResponse], error) {
|
||||
resp, err := notifySvc.CreateNotification(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.NotificationService_ListNotifications_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.NotificationService_ListNotifications_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListNotificationsRequest]) (*connect.Response[pb.ListNotificationsResponse], error) {
|
||||
resp, err := notifySvc.ListNotifications(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.NotificationService_MarkNotificationsRead_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.NotificationService_MarkNotificationsRead_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.MarkNotificationsReadRequest]) (*connect.Response[pb.MarkNotificationsReadResponse], error) {
|
||||
resp, err := notifySvc.MarkNotificationsRead(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.NotificationService_MarkAllNotificationsRead_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.NotificationService_MarkAllNotificationsRead_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.MarkAllNotificationsReadRequest]) (*connect.Response[pb.MarkAllNotificationsReadResponse], error) {
|
||||
resp, err := notifySvc.MarkAllNotificationsRead(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.CommentService_CreateDocumentComment_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.CommentService_CreateDocumentComment_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.CreateDocumentCommentRequest]) (*connect.Response[pb.CreateDocumentCommentResponse], error) {
|
||||
resp, err := commentSvc.CreateDocumentComment(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.CommentService_ListDocumentComments_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.CommentService_ListDocumentComments_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListDocumentCommentsRequest]) (*connect.Response[pb.ListDocumentCommentsResponse], error) {
|
||||
resp, err := commentSvc.ListDocumentComments(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.CommentService_DeleteDocumentComment_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.CommentService_DeleteDocumentComment_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.DeleteDocumentCommentRequest]) (*connect.Response[pb.DeleteDocumentCommentResponse], error) {
|
||||
resp, err := commentSvc.DeleteDocumentComment(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.CommentService_UpdateDocumentComment_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.CommentService_UpdateDocumentComment_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateDocumentCommentRequest]) (*connect.Response[pb.UpdateDocumentCommentResponse], error) {
|
||||
resp, err := commentSvc.UpdateDocumentComment(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_UpdateDocument_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_UpdateDocument_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateDocumentRequest]) (*connect.Response[pb.UpdateDocumentResponse], error) {
|
||||
resp, err := docSvc.UpdateDocument(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_CreateTemplate_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_CreateTemplate_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.CreateTemplateRequest]) (*connect.Response[pb.CreateTemplateResponse], error) {
|
||||
resp, err := docSvc.CreateTemplate(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_GetTemplate_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_GetTemplate_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.GetTemplateRequest]) (*connect.Response[pb.GetTemplateResponse], error) {
|
||||
resp, err := docSvc.GetTemplate(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_ListTemplates_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_ListTemplates_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListTemplatesRequest]) (*connect.Response[pb.ListTemplatesResponse], error) {
|
||||
resp, err := docSvc.ListTemplates(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_ListRecentTemplates_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_ListRecentTemplates_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.ListRecentTemplatesRequest]) (*connect.Response[pb.ListRecentTemplatesResponse], error) {
|
||||
resp, err := docSvc.ListRecentTemplates(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_UpdateTemplateSettings_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_UpdateTemplateSettings_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.UpdateTemplateSettingsRequest]) (*connect.Response[pb.UpdateTemplateSettingsResponse], error) {
|
||||
resp, err := docSvc.UpdateTemplateSettings(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
|
||||
mux.Handle(pb.DocumentService_DeleteDocument_FullMethodName, connect.NewUnaryHandler(
|
||||
pb.DocumentService_DeleteDocument_FullMethodName,
|
||||
func(ctx context.Context, req *connect.Request[pb.DeleteDocumentRequest]) (*connect.Response[pb.DeleteDocumentResponse], error) {
|
||||
resp, err := docSvc.DeleteDocument(ctx, req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(resp), nil
|
||||
},
|
||||
opts...,
|
||||
))
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package connectserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/XingfenD/yoresee_doc/internal/config"
|
||||
"github.com/XingfenD/yoresee_doc/internal/middleware"
|
||||
)
|
||||
|
||||
func UnaryAuthInterceptor(allowUnauth map[string]struct{}) connect.UnaryInterceptorFunc {
|
||||
return connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
|
||||
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
|
||||
if _, ok := allowUnauth[req.Spec().Procedure]; ok {
|
||||
return next(ctx, req)
|
||||
}
|
||||
|
||||
internalKey := req.Header().Get("x-internal-key")
|
||||
if internalKey != "" && config.GlobalConfig.Backend.InternalRPCKey != "" && internalKey == config.GlobalConfig.Backend.InternalRPCKey {
|
||||
return next(ctx, req)
|
||||
}
|
||||
|
||||
authHeader := req.Header().Get("Authorization")
|
||||
if authHeader == "" {
|
||||
authHeader = req.Header().Get("authorization")
|
||||
}
|
||||
|
||||
claims, err := middleware.JWTAuth.ValidateAuthorizationHeader(authHeader)
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, err)
|
||||
}
|
||||
|
||||
ctx = context.WithValue(ctx, "user_external_id", claims.ExternalID)
|
||||
ctx = context.WithValue(ctx, "username", claims.Username)
|
||||
|
||||
return next(ctx, req)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package connectserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type probeResponse struct {
|
||||
Status string `json:"status"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
}
|
||||
|
||||
func registerProbeRoutes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("/health", handleHealthProbe)
|
||||
mux.HandleFunc("/readyz", handleReadinessProbe)
|
||||
mux.HandleFunc("/livez", handleLivenessProbe)
|
||||
}
|
||||
|
||||
func handleHealthProbe(w http.ResponseWriter, _ *http.Request) {
|
||||
writeProbeResponse(w, http.StatusOK, "ok", "")
|
||||
}
|
||||
|
||||
func handleLivenessProbe(w http.ResponseWriter, _ *http.Request) {
|
||||
writeProbeResponse(w, http.StatusOK, "ok", "")
|
||||
}
|
||||
|
||||
func handleReadinessProbe(w http.ResponseWriter, _ *http.Request) {
|
||||
if err := readinessErr(); err != nil {
|
||||
writeProbeResponse(w, http.StatusServiceUnavailable, "not_ready", err.Error())
|
||||
return
|
||||
}
|
||||
writeProbeResponse(w, http.StatusOK, "ok", "")
|
||||
}
|
||||
|
||||
func readinessErr() error {
|
||||
if draining.Load() {
|
||||
return fmt.Errorf("server is draining")
|
||||
}
|
||||
if readyDB == nil {
|
||||
return fmt.Errorf("database is not initialized")
|
||||
}
|
||||
if readyKVS == nil {
|
||||
return fmt.Errorf("redis is not initialized")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1500*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
sqlDB, err := readyDB.DB()
|
||||
if err != nil {
|
||||
return fmt.Errorf("database handle unavailable: %w", err)
|
||||
}
|
||||
if err := sqlDB.PingContext(ctx); err != nil {
|
||||
return fmt.Errorf("database ping failed: %w", err)
|
||||
}
|
||||
if err := readyKVS.Ping(ctx).Err(); err != nil {
|
||||
return fmt.Errorf("redis ping failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeProbeResponse(w http.ResponseWriter, statusCode int, status, detail string) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(statusCode)
|
||||
_ = json.NewEncoder(w).Encode(probeResponse{
|
||||
Status: status,
|
||||
Detail: detail,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package connectserver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/XingfenD/yoresee_doc/internal/repository"
|
||||
"github.com/redis/go-redis/v9"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
draining atomic.Bool
|
||||
readyDB *gorm.DB
|
||||
readyKVS *redis.Client
|
||||
)
|
||||
|
||||
func SetDraining(v bool) {
|
||||
draining.Store(v)
|
||||
}
|
||||
|
||||
func Start(grpcPort, grpcWebPort int, db *gorm.DB, kvs *redis.Client, repos *repository.Repositories) (*http.Server, *http.Server, error) {
|
||||
readyDB = db
|
||||
readyKVS = kvs
|
||||
allowUnauth := map[string]struct{}{
|
||||
pb.AuthService_Login_FullMethodName: {},
|
||||
pb.AuthService_Register_FullMethodName: {},
|
||||
pb.SystemService_Health_FullMethodName: {},
|
||||
pb.SystemService_SystemInfo_FullMethodName: {},
|
||||
}
|
||||
|
||||
interceptor := UnaryAuthInterceptor(allowUnauth)
|
||||
opts := []connect.HandlerOption{
|
||||
connect.WithInterceptors(interceptor),
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
registerHandlers(mux, opts, repos)
|
||||
registerProbeRoutes(mux)
|
||||
|
||||
handler := withCORS(mux)
|
||||
h2cHandler := h2c.NewHandler(handler, &http2.Server{})
|
||||
|
||||
grpcAddr := fmt.Sprintf(":%d", grpcPort)
|
||||
grpcServer := &http.Server{Addr: grpcAddr, Handler: h2cHandler}
|
||||
go func() {
|
||||
if err := grpcServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
logrus.Errorf("grpc server exited unexpectedly: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
grpcWebAddr := fmt.Sprintf(":%d", grpcWebPort)
|
||||
grpcWebServer := &http.Server{Addr: grpcWebAddr, Handler: h2cHandler}
|
||||
go func() {
|
||||
if err := grpcWebServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
logrus.Errorf("grpc-web server exited unexpectedly: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return grpcServer, grpcWebServer, nil
|
||||
}
|
||||
|
||||
func withCORS(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
setConnectCorsHeaders(w, r)
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func setConnectCorsHeaders(w http.ResponseWriter, r *http.Request) {
|
||||
origin := r.Header.Get("Origin")
|
||||
if origin == "" {
|
||||
origin = "*"
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Accept,Accept-Language,Content-Type,Content-Length,X-Grpc-Web,X-User-Agent,Grpc-Timeout,Authorization,Connect-Protocol-Version")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "POST,GET,OPTIONS")
|
||||
w.Header().Set("Access-Control-Expose-Headers", "Grpc-Status,Grpc-Message,Grpc-Status-Details-Bin,Connect-Protocol-Version")
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/dto"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/auth_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type AuthServiceServer struct {
|
||||
pb.UnimplementedAuthServiceServer
|
||||
}
|
||||
|
||||
func NewAuthServiceServer() *AuthServiceServer {
|
||||
return &AuthServiceServer{}
|
||||
}
|
||||
|
||||
func (s *AuthServiceServer) Login(ctx context.Context, req *pb.AuthLoginRequest) (*pb.AuthLoginResponse, error) {
|
||||
if req == nil || req.Email == "" || req.Password == "" {
|
||||
return &pb.AuthLoginResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
token, user, err := auth_service.AuthSvc.Login(req.Email, req.Password)
|
||||
if err != nil {
|
||||
return &pb.AuthLoginResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.AuthLoginResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Token: token,
|
||||
User: toUserResponse(user),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *AuthServiceServer) Register(ctx context.Context, req *pb.AuthRegisterRequest) (*pb.AuthRegisterResponse, error) {
|
||||
if req == nil || req.Username == "" || req.Password == "" || req.Email == "" {
|
||||
return &pb.AuthRegisterResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
userCreate := &dto.UserCreate{
|
||||
Username: req.Username,
|
||||
Email: req.Email,
|
||||
Password: req.Password,
|
||||
}
|
||||
if req.InvitationCode != nil {
|
||||
userCreate.InvitationCode = req.InvitationCode
|
||||
}
|
||||
|
||||
err := auth_service.AuthSvc.Register(ctx, userCreate)
|
||||
if err != nil {
|
||||
return &pb.AuthRegisterResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.AuthRegisterResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func (s *AuthServiceServer) UpdateProfile(ctx context.Context, req *pb.UpdateProfileRequest) (*pb.UpdateProfileResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.UpdateProfileResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.UpdateProfileResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.UpdateProfileRequest{
|
||||
Username: req.Username,
|
||||
Email: req.Email,
|
||||
Nickname: req.Nickname,
|
||||
Password: req.Password,
|
||||
AvatarFile: req.AvatarFile,
|
||||
AvatarFilename: req.AvatarFilename,
|
||||
AvatarContentType: req.AvatarContentType,
|
||||
}
|
||||
|
||||
user, err := auth_service.AuthSvc.UpdateProfile(userExternalID, serviceReq)
|
||||
if err != nil {
|
||||
return &pb.UpdateProfileResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.UpdateProfileResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
User: toUserResponse(user),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *AuthServiceServer) QuerySideBarDisplay(ctx context.Context, req *pb.QuerySideBarDisplayRequest) (*pb.QuerySideBarDisplayResponse, error) {
|
||||
if req == nil || req.Scene == "" {
|
||||
return &pb.QuerySideBarDisplayResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.QuerySideBarDisplayResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
|
||||
isAdmin, err := auth_service.AuthSvc.IsAdmin(userExternalID)
|
||||
if err != nil {
|
||||
return &pb.QuerySideBarDisplayResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
displayTabs, err := auth_service.AuthSvc.QuerySideBarDisplay(req.Scene, isAdmin)
|
||||
if err != nil {
|
||||
return &pb.QuerySideBarDisplayResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
return &pb.QuerySideBarDisplayResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
DisplayTabs: displayTabs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *AuthServiceServer) QueryTopNavDisplay(ctx context.Context, req *pb.QueryTopNavDisplayRequest) (*pb.QueryTopNavDisplayResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.QueryTopNavDisplayResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
|
||||
isAdmin, err := auth_service.AuthSvc.IsAdmin(userExternalID)
|
||||
if err != nil {
|
||||
return &pb.QueryTopNavDisplayResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
menus, err := auth_service.AuthSvc.QueryTopNavDisplay(isAdmin)
|
||||
if err != nil {
|
||||
return &pb.QueryTopNavDisplayResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.QueryTopNavDisplayResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
DisplayMenus: menus,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/dto"
|
||||
"github.com/XingfenD/yoresee_doc/internal/media"
|
||||
"github.com/XingfenD/yoresee_doc/internal/model"
|
||||
"github.com/XingfenD/yoresee_doc/internal/repository/document_repo"
|
||||
"github.com/XingfenD/yoresee_doc/internal/repository/user_repo"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/auth_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/comment_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type CommentServiceServer struct {
|
||||
pb.UnimplementedCommentServiceServer
|
||||
userRepo *user_repo.UserRepository
|
||||
docRepo *document_repo.DocumentRepository
|
||||
}
|
||||
|
||||
func NewCommentServiceServer(userRepo *user_repo.UserRepository, docRepo *document_repo.DocumentRepository) *CommentServiceServer {
|
||||
return &CommentServiceServer{
|
||||
userRepo: userRepo,
|
||||
docRepo: docRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CommentServiceServer) CreateDocumentComment(ctx context.Context, req *pb.CreateDocumentCommentRequest) (*pb.CreateDocumentCommentResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.CreateDocumentCommentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.CreateDocumentCommentResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
|
||||
var parentExternalID *string
|
||||
if req.ParentExternalId != nil && strings.TrimSpace(req.GetParentExternalId()) != "" {
|
||||
parentExternalID = req.ParentExternalId
|
||||
}
|
||||
var anchorID *string
|
||||
if req.AnchorId != nil && strings.TrimSpace(req.GetAnchorId()) != "" {
|
||||
anchorID = req.AnchorId
|
||||
}
|
||||
var quote *string
|
||||
if req.Quote != nil && strings.TrimSpace(req.GetQuote()) != "" {
|
||||
quote = req.Quote
|
||||
}
|
||||
|
||||
comment, err := comment_service.CommentSvc.CreateComment(&dto.CreateCommentRequest{
|
||||
DocumentExternalID: req.DocumentExternalId,
|
||||
Content: req.Content,
|
||||
ParentExternalID: parentExternalID,
|
||||
AnchorID: anchorID,
|
||||
Quote: quote,
|
||||
CreatorExternalID: userExternalID,
|
||||
MentionedUserExternalIDs: req.MentionedUserExternalIds,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.CreateDocumentCommentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
creator, _ := s.userRepo.GetByExternalID(userExternalID).Exec()
|
||||
resp := toCommentResponse(comment, req.DocumentExternalId, req.GetParentExternalId(), creator)
|
||||
return &pb.CreateDocumentCommentResponse{Base: baseResponseFromErr(nil), Comment: resp}, nil
|
||||
}
|
||||
|
||||
func (s *CommentServiceServer) ListDocumentComments(ctx context.Context, req *pb.ListDocumentCommentsRequest) (*pb.ListDocumentCommentsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListDocumentCommentsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
comments, total, err := comment_service.CommentSvc.ListComments(&dto.ListCommentsRequest{
|
||||
DocumentExternalID: req.DocumentExternalId,
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.ListDocumentCommentsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
creatorIDs := make([]int64, 0, len(comments))
|
||||
for _, item := range comments {
|
||||
creatorIDs = append(creatorIDs, item.CreatorID)
|
||||
}
|
||||
creatorMap, _ := s.userRepo.MGetUserByID(creatorIDs).Exec()
|
||||
|
||||
parentMap := make(map[int64]string, len(comments))
|
||||
for _, item := range comments {
|
||||
parentMap[item.ID] = item.ExternalID
|
||||
}
|
||||
|
||||
respItems := make([]*pb.DocumentComment, 0, len(comments))
|
||||
for _, item := range comments {
|
||||
parentExternalID := ""
|
||||
if item.ParentID != 0 {
|
||||
parentExternalID = parentMap[item.ParentID]
|
||||
}
|
||||
respItems = append(respItems, toCommentResponse(&item, req.DocumentExternalId, parentExternalID, creatorMap[item.CreatorID]))
|
||||
}
|
||||
|
||||
return &pb.ListDocumentCommentsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Comments: respItems,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *CommentServiceServer) DeleteDocumentComment(ctx context.Context, req *pb.DeleteDocumentCommentRequest) (*pb.DeleteDocumentCommentResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.DeleteDocumentCommentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.DeleteDocumentCommentResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
isAdmin, _ := auth_service.AuthSvc.IsAdmin(userExternalID)
|
||||
if err := comment_service.CommentSvc.DeleteComment(&dto.DeleteCommentRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
OperatorExternalID: userExternalID,
|
||||
}, isAdmin); err != nil {
|
||||
return &pb.DeleteDocumentCommentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
return &pb.DeleteDocumentCommentResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func (s *CommentServiceServer) UpdateDocumentComment(ctx context.Context, req *pb.UpdateDocumentCommentRequest) (*pb.UpdateDocumentCommentResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" || strings.TrimSpace(req.Content) == "" {
|
||||
return &pb.UpdateDocumentCommentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.UpdateDocumentCommentResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
isAdmin, _ := auth_service.AuthSvc.IsAdmin(userExternalID)
|
||||
comment, err := comment_service.CommentSvc.UpdateComment(&dto.UpdateCommentRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
Content: req.Content,
|
||||
OperatorExternalID: userExternalID,
|
||||
}, isAdmin)
|
||||
if err != nil {
|
||||
return &pb.UpdateDocumentCommentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
docExternalID := ""
|
||||
if comment != nil && comment.DocumentID != 0 {
|
||||
if docs, err := s.docRepo.MGetByIDs([]int64{comment.DocumentID}); err == nil && len(docs) > 0 {
|
||||
docExternalID = docs[0].ExternalID
|
||||
}
|
||||
}
|
||||
creator, _ := s.userRepo.GetByExternalID(userExternalID).Exec()
|
||||
resp := toCommentResponse(comment, docExternalID, "", creator)
|
||||
return &pb.UpdateDocumentCommentResponse{Base: baseResponseFromErr(nil), Comment: resp}, nil
|
||||
}
|
||||
|
||||
func toCommentResponse(comment *model.DocumentComment, docExternalID, parentExternalID string, creator *model.User) *pb.DocumentComment {
|
||||
if comment == nil {
|
||||
return nil
|
||||
}
|
||||
resp := &pb.DocumentComment{
|
||||
ExternalId: comment.ExternalID,
|
||||
DocumentExternalId: docExternalID,
|
||||
ParentExternalId: parentExternalID,
|
||||
Content: comment.Content,
|
||||
AnchorId: comment.AnchorID,
|
||||
Quote: "",
|
||||
CreatorUserExternalId: "",
|
||||
CreatorName: "",
|
||||
CreatorAvatar: "",
|
||||
CreatedAt: timeToString(comment.CreatedAt),
|
||||
}
|
||||
if creator != nil {
|
||||
resp.CreatorUserExternalId = creator.ExternalID
|
||||
if creator.Nickname != "" {
|
||||
resp.CreatorName = creator.Nickname
|
||||
} else {
|
||||
resp.CreatorName = creator.Username
|
||||
}
|
||||
resp.CreatorAvatar = media.BuildAvatarURL(creator.ExternalID, creator.AvatarObjectKey, creator.AvatarVersion)
|
||||
}
|
||||
return resp
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/dto"
|
||||
"github.com/XingfenD/yoresee_doc/internal/mapper/doc_type_mapper"
|
||||
"github.com/XingfenD/yoresee_doc/internal/media"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
"github.com/XingfenD/yoresee_doc/internal/utils"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
func baseResponseFromErr(err error) *pb.BaseResponse {
|
||||
if err == nil {
|
||||
return baseResponseFromStatus(status.StatusSuccess)
|
||||
}
|
||||
return baseResponseFromStatus(err)
|
||||
}
|
||||
|
||||
func baseResponseFromStatus(err error) *pb.BaseResponse {
|
||||
st, ok := err.(*status.Status)
|
||||
if !ok {
|
||||
st = status.StatusServiceInternalError.(*status.Status)
|
||||
}
|
||||
return &pb.BaseResponse{
|
||||
Code: int32(st.Code),
|
||||
Message: st.Message,
|
||||
}
|
||||
}
|
||||
|
||||
func timeToString(t time.Time) string {
|
||||
if t.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return t.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
func toDocumentResponse(doc *dto.DocumentMetaResponse) *pb.DocumentResponse {
|
||||
if doc == nil {
|
||||
return nil
|
||||
}
|
||||
resp := &pb.DocumentResponse{
|
||||
ExternalId: doc.ExternalID,
|
||||
Title: doc.Title,
|
||||
Type: doc_type_mapper.ToProtoType(doc.Type),
|
||||
Summary: doc.Summary,
|
||||
Tags: doc.Tags,
|
||||
ViewCount: int32(doc.ViewCount),
|
||||
EditCount: int32(doc.EditCount),
|
||||
CreatedAt: timeToString(doc.CreatedAt),
|
||||
UpdatedAt: timeToString(doc.UpdatedAt),
|
||||
HasChildren: doc.HasChildren,
|
||||
IsPublic: doc.IsPublic,
|
||||
}
|
||||
if len(doc.Children) > 0 {
|
||||
resp.Children = make([]*pb.DocumentResponse, 0, len(doc.Children))
|
||||
for _, child := range doc.Children {
|
||||
resp.Children = append(resp.Children, toDocumentResponse(child))
|
||||
}
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func toKnowledgeBaseResponse(kb *dto.KnowledgeBaseResponse) *pb.KnowledgeBaseResponse {
|
||||
if kb == nil {
|
||||
return nil
|
||||
}
|
||||
return &pb.KnowledgeBaseResponse{
|
||||
ExternalId: kb.ExternalID,
|
||||
Name: kb.Name,
|
||||
Description: kb.Description,
|
||||
Cover: kb.Cover,
|
||||
IsPublic: kb.IsPublic,
|
||||
CreatedAt: timeToString(kb.CreatedAt),
|
||||
UpdatedAt: timeToString(kb.UpdatedAt),
|
||||
DeletedAt: timeToString(kb.DeletedAt),
|
||||
CreatorUserExternalId: kb.CreatorUserExternalID,
|
||||
CreatorName: kb.CreatorName,
|
||||
DocumentsCount: kb.DocumentsCount,
|
||||
}
|
||||
}
|
||||
|
||||
func toUserResponse(user *dto.UserResponse) *pb.UserResponse {
|
||||
if user == nil {
|
||||
return nil
|
||||
}
|
||||
resp := &pb.UserResponse{
|
||||
ExternalId: user.ExternalID,
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
Nickname: user.Nickname,
|
||||
Avatar: media.BuildAvatarURL(user.ExternalID, user.AvatarObjectKey, user.AvatarVersion),
|
||||
Status: int32(user.Status),
|
||||
CreatedAt: timeToString(user.CreatedAt),
|
||||
UpdatedAt: timeToString(user.UpdatedAt),
|
||||
}
|
||||
if user.InvitationCode != nil {
|
||||
resp.InvitationCode = user.InvitationCode
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func toTemplateResponse(tpl *dto.TemplateResponse) *pb.TemplateResponse {
|
||||
if tpl == nil {
|
||||
return nil
|
||||
}
|
||||
return &pb.TemplateResponse{
|
||||
Id: tpl.ID,
|
||||
Name: tpl.Name,
|
||||
Description: tpl.Description,
|
||||
Content: tpl.Content,
|
||||
Type: doc_type_mapper.ToProtoType(tpl.Type),
|
||||
Scope: tpl.Scope,
|
||||
KnowledgeBaseExternalId: tpl.KnowledgeBaseExternalID,
|
||||
Tags: tpl.Tags,
|
||||
CreatedAt: timeToString(tpl.CreatedAt),
|
||||
UpdatedAt: timeToString(tpl.UpdatedAt),
|
||||
}
|
||||
}
|
||||
|
||||
func toAttachmentResponse(attachment *dto.AttachmentResponse) *pb.AttachmentResponse {
|
||||
if attachment == nil {
|
||||
return nil
|
||||
}
|
||||
return &pb.AttachmentResponse{
|
||||
ExternalId: attachment.ExternalID,
|
||||
DocumentExternalId: attachment.DocumentExternalID,
|
||||
Name: attachment.Name,
|
||||
Size: attachment.Size,
|
||||
MimeType: attachment.MimeType,
|
||||
Path: attachment.Path,
|
||||
Url: attachment.URL,
|
||||
CreatedAt: timeToString(attachment.CreatedAt),
|
||||
UpdatedAt: timeToString(attachment.UpdatedAt),
|
||||
}
|
||||
}
|
||||
|
||||
func toDocumentVersionResponse(item *dto.DocumentVersionResponse) *pb.DocumentVersionResponse {
|
||||
if item == nil {
|
||||
return nil
|
||||
}
|
||||
return &pb.DocumentVersionResponse{
|
||||
Version: int32(item.Version),
|
||||
Title: item.Title,
|
||||
Content: item.Content,
|
||||
ChangeSummary: item.ChangeSummary,
|
||||
CreatedAt: timeToString(item.CreatedAt),
|
||||
}
|
||||
}
|
||||
|
||||
func toUserGroupResponse(group *dto.UserGroupResponse) *pb.UserGroupResponse {
|
||||
if group == nil {
|
||||
return nil
|
||||
}
|
||||
resp := &pb.UserGroupResponse{
|
||||
ExternalId: group.ExternalID,
|
||||
Name: group.Name,
|
||||
Description: group.Description,
|
||||
CreatorUserExternalId: group.CreatorUserExternalID,
|
||||
MemberCount: int32(group.MemberCount),
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func toInvitationResponse(inv *dto.InvitationResponse) *pb.InvitationResponse {
|
||||
if inv == nil {
|
||||
return nil
|
||||
}
|
||||
resp := &pb.InvitationResponse{
|
||||
Code: inv.Code,
|
||||
CreatedByExternalId: inv.CreatedByExternalID,
|
||||
CreatedByName: inv.CreatedByName,
|
||||
UsedCnt: inv.UsedCnt,
|
||||
Disabled: inv.Disabled,
|
||||
CreatedAt: timeToString(inv.CreatedAt),
|
||||
}
|
||||
if inv.MaxUsedCnt != nil {
|
||||
resp.MaxUsedCnt = inv.MaxUsedCnt
|
||||
}
|
||||
if inv.ExpiresAt != nil {
|
||||
resp.ExpiresAt = utils.Of(timeToString(*inv.ExpiresAt))
|
||||
}
|
||||
if inv.Note != nil {
|
||||
resp.Note = inv.Note
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func toInvitationRecordResponse(rec *dto.InvitationRecordResponse) *pb.InvitationRecordResponse {
|
||||
if rec == nil {
|
||||
return nil
|
||||
}
|
||||
resp := &pb.InvitationRecordResponse{
|
||||
Code: rec.Code,
|
||||
UsedBy: rec.UsedBy,
|
||||
UsedAt: timeToString(rec.UsedAt),
|
||||
Status: rec.Status,
|
||||
}
|
||||
if rec.UsedByExternalID != "" {
|
||||
resp.UsedByExternalId = utils.Of(rec.UsedByExternalID)
|
||||
}
|
||||
return resp
|
||||
}
|
||||
@@ -0,0 +1,712 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/dto"
|
||||
doc_container_mapper "github.com/XingfenD/yoresee_doc/internal/mapper/doc_container_mapper"
|
||||
"github.com/XingfenD/yoresee_doc/internal/mapper/doc_type_mapper"
|
||||
"github.com/XingfenD/yoresee_doc/internal/mapper/template_container_mapper"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/document_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
"github.com/XingfenD/yoresee_doc/internal/utils"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type DocumentServiceServer struct {
|
||||
pb.UnimplementedDocumentServiceServer
|
||||
}
|
||||
|
||||
func NewDocumentServiceServer() *DocumentServiceServer {
|
||||
return &DocumentServiceServer{}
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) ListDocuments(ctx context.Context, req *pb.ListDocumentsRequest) (*pb.ListDocumentsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListDocumentsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
filterArgs := &dto.DocumentsListFilterArgs{
|
||||
TitleKeyword: req.TitleKeyword,
|
||||
DocType: req.Type,
|
||||
Tags: req.Tags,
|
||||
}
|
||||
if req.CreateTimeRange != nil {
|
||||
filterArgs.CreateTimeRangeStart = req.CreateTimeRange.Start
|
||||
filterArgs.CreateTimeRangeEnd = req.CreateTimeRange.End
|
||||
}
|
||||
if req.UpdateTimeRange != nil {
|
||||
filterArgs.UpdateTimeRangeStart = req.UpdateTimeRange.Start
|
||||
filterArgs.UpdateTimeRangeEnd = req.UpdateTimeRange.End
|
||||
}
|
||||
|
||||
sortArgs := dto.SortArgs{Field: "created_at", Desc: true}
|
||||
if req.OrderBy != nil {
|
||||
sortArgs.Field = req.GetOrderBy()
|
||||
}
|
||||
if req.OrderDesc != nil {
|
||||
sortArgs.Desc = req.GetOrderDesc()
|
||||
}
|
||||
|
||||
serviceReq := &dto.ListDocumentsByExternalRequest{
|
||||
ExternalArgs: &dto.DocumentsListExternalArgs{
|
||||
UserExternalID: req.UserExternalId,
|
||||
RootDocumentExternalID: req.RootDocumentExternalId,
|
||||
KnowledgeExternalID: req.KnowledgeBaseExternalId,
|
||||
},
|
||||
FilterArgs: filterArgs,
|
||||
SortArgs: sortArgs,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
if req.Options != nil {
|
||||
serviceReq.Options = &dto.RecursiveOptions{
|
||||
IncludeChildren: req.Options.IncludeChildren,
|
||||
Recursive: req.Options.Recursive,
|
||||
Depth: utils.Of(int(req.Options.Depth)),
|
||||
}
|
||||
}
|
||||
|
||||
docs, total, err := document_service.DocumentSvc.ListDocumentsByExternal(ctx, serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListDocumentsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respDocs := make([]*pb.DocumentResponse, 0, len(docs))
|
||||
for _, doc := range docs {
|
||||
respDocs = append(respDocs, toDocumentResponse(doc))
|
||||
}
|
||||
|
||||
return &pb.ListDocumentsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Documents: respDocs,
|
||||
TotalCount: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) GetDocumentContent(ctx context.Context, req *pb.GetDocumentContentRequest) (*pb.GetDocumentContentResponse, error) {
|
||||
if req == nil || req.DocumentExternalId == "" {
|
||||
return &pb.GetDocumentContentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
document, err := document_service.DocumentSvc.GetDocumentByExternalID(ctx, req.DocumentExternalId)
|
||||
if err != nil {
|
||||
return &pb.GetDocumentContentResponse{Base: baseResponseFromErr(status.StatusDocumentNotFound)}, nil
|
||||
}
|
||||
|
||||
return &pb.GetDocumentContentResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Document: toDocumentResponse(&document.DocumentMetaResponse),
|
||||
Content: document.Content,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) GetDocumentSettings(ctx context.Context, req *pb.GetDocumentSettingsRequest) (*pb.GetDocumentSettingsResponse, error) {
|
||||
if req == nil || req.DocumentExternalId == "" {
|
||||
return &pb.GetDocumentSettingsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
settings, err := document_service.DocumentSvc.GetDocumentSettings(ctx, &dto.GetDocumentSettingsRequest{
|
||||
ExternalID: req.DocumentExternalId,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.GetDocumentSettingsResponse{Base: baseResponseFromErr(status.StatusDocumentNotFound)}, nil
|
||||
}
|
||||
|
||||
return &pb.GetDocumentSettingsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
IsPublic: utils.Of(settings.IsPublic),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) RecordRecentDocument(ctx context.Context, req *pb.RecordRecentDocumentRequest) (*pb.RecordRecentDocumentResponse, error) {
|
||||
if req == nil || req.DocumentExternalId == "" {
|
||||
return &pb.RecordRecentDocumentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.RecordRecentDocumentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := document_service.DocumentSvc.RecordRecentDocument(&dto.RecordRecentDocumentRequest{
|
||||
UserExternalID: userExternalID,
|
||||
DocumentExternalID: req.DocumentExternalId,
|
||||
}); err != nil {
|
||||
return &pb.RecordRecentDocumentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
return &pb.RecordRecentDocumentResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) ListRecentDocuments(ctx context.Context, req *pb.ListRecentDocumentsRequest) (*pb.ListRecentDocumentsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListRecentDocumentsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.ListRecentDocumentsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
var startTime *time.Time
|
||||
if req.StartTime != nil && *req.StartTime != "" {
|
||||
t, err := time.Parse(time.RFC3339, *req.StartTime)
|
||||
if err != nil {
|
||||
return &pb.ListRecentDocumentsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
startTime = &t
|
||||
}
|
||||
var endTime *time.Time
|
||||
if req.EndTime != nil && *req.EndTime != "" {
|
||||
t, err := time.Parse(time.RFC3339, *req.EndTime)
|
||||
if err != nil {
|
||||
return &pb.ListRecentDocumentsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
endTime = &t
|
||||
}
|
||||
|
||||
serviceReq := &dto.ListRecentDocumentsRequest{
|
||||
UserExternalID: userExternalID,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
documents, total, err := document_service.DocumentSvc.ListRecentDocuments(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListRecentDocumentsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respDocs := make([]*pb.DocumentResponse, 0, len(documents))
|
||||
for _, doc := range documents {
|
||||
respDocs = append(respDocs, toDocumentResponse(&doc.DocumentMetaResponse))
|
||||
}
|
||||
|
||||
return &pb.ListRecentDocumentsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Documents: respDocs,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) GetDocumentYjsSnapshot(ctx context.Context, req *pb.GetDocumentYjsSnapshotRequest) (*pb.GetDocumentYjsSnapshotResponse, error) {
|
||||
if req == nil || req.DocumentExternalId == "" {
|
||||
return &pb.GetDocumentYjsSnapshotResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
state, err := document_service.DocumentSvc.GetDocumentYjsSnapshot(ctx, req.DocumentExternalId)
|
||||
if err != nil {
|
||||
return &pb.GetDocumentYjsSnapshotResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.GetDocumentYjsSnapshotResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
State: state,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) SaveDocumentYjsSnapshot(ctx context.Context, req *pb.SaveDocumentYjsSnapshotRequest) (*pb.SaveDocumentYjsSnapshotResponse, error) {
|
||||
if req == nil || req.DocumentExternalId == "" || len(req.State) == 0 {
|
||||
return &pb.SaveDocumentYjsSnapshotResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
if err := document_service.DocumentSvc.SaveDocumentYjsSnapshot(ctx, req.DocumentExternalId, req.State); err != nil {
|
||||
return &pb.SaveDocumentYjsSnapshotResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.SaveDocumentYjsSnapshotResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) GetOwnDocuments(ctx context.Context, req *pb.GetOwnDocumentsRequest) (*pb.GetOwnDocumentsResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.GetOwnDocumentsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
queryReq := &dto.ListDocumentsByExternalRequest{
|
||||
ExternalArgs: &dto.DocumentsListExternalArgs{
|
||||
UserExternalID: &userExternalID,
|
||||
},
|
||||
ListDocumentsBaseArgs: dto.ListDocumentsBaseArgs{
|
||||
ListOwnDoc: true,
|
||||
DirectoryOnly: req.DirectoryOnly,
|
||||
},
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
Options: &dto.RecursiveOptions{
|
||||
IncludeChildren: true,
|
||||
Recursive: true,
|
||||
},
|
||||
}
|
||||
|
||||
docs, count, err := document_service.DocumentSvc.ListDocumentsByExternal(ctx, queryReq)
|
||||
if err != nil {
|
||||
return &pb.GetOwnDocumentsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respDocs := make([]*pb.DocumentResponse, 0, len(docs))
|
||||
for _, doc := range docs {
|
||||
respDocs = append(respDocs, toDocumentResponse(doc))
|
||||
}
|
||||
|
||||
return &pb.GetOwnDocumentsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Documents: respDocs,
|
||||
TotalCount: count,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) CreateDocument(ctx context.Context, req *pb.CreateDocumentRequest) (*pb.CreateDocumentResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.CreateDocumentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil || req.Title == "" {
|
||||
return &pb.CreateDocumentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
dtoReq := &dto.CreateDocumentRequest{
|
||||
Title: req.Title,
|
||||
Type: doc_type_mapper.FromProtoType(req.Type),
|
||||
IsPublic: req.GetIsPublic(),
|
||||
CreatorExternalID: utils.Of(userExternalID),
|
||||
ParentExternalID: req.ParentExternalId,
|
||||
}
|
||||
if req.TemplateId != nil && *req.TemplateId > 0 {
|
||||
dtoReq.TemplateID = req.TemplateId
|
||||
}
|
||||
|
||||
containerType, ok := doc_container_mapper.FromProtoType(req.ContainerType)
|
||||
if !ok {
|
||||
return &pb.CreateDocumentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
dtoReq.ContainerType = containerType
|
||||
if containerType == dto.ContainerType_KnowledgeBase {
|
||||
dtoReq.KnowledgeExternalID = req.KnowledgeBaseExternalId
|
||||
}
|
||||
|
||||
resp, err := document_service.DocumentSvc.Create(ctx, dtoReq)
|
||||
if err != nil {
|
||||
return &pb.CreateDocumentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.CreateDocumentResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
ExternalId: resp.ExternalID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) UpdateDocument(ctx context.Context, req *pb.UpdateDocumentRequest) (*pb.UpdateDocumentResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.UpdateDocumentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := validateUpdateDocumentRequest(req); err != nil {
|
||||
return &pb.UpdateDocumentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.UpdateDocumentRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
Title: req.Title,
|
||||
ParentExternalID: req.ParentExternalId,
|
||||
KnowledgeBaseExternalID: req.KnowledgeBaseExternalId,
|
||||
Content: req.Content,
|
||||
}
|
||||
|
||||
if req.MoveToContainer != nil {
|
||||
moveToContainer, ok := doc_container_mapper.FromProtoType(*req.MoveToContainer)
|
||||
if !ok {
|
||||
return &pb.UpdateDocumentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
serviceReq.MoveToContainer = utils.Of(moveToContainer)
|
||||
}
|
||||
|
||||
if _, err := document_service.DocumentSvc.Update(ctx, serviceReq); err != nil {
|
||||
return &pb.UpdateDocumentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.UpdateDocumentResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) UpdateDocumentMeta(ctx context.Context, req *pb.UpdateDocumentMetaRequest) (*pb.UpdateDocumentMetaResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.UpdateDocumentMetaResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil || req.ExternalId == "" {
|
||||
return &pb.UpdateDocumentMetaResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req.Title == nil && req.Summary == nil && req.Tags == nil {
|
||||
return &pb.UpdateDocumentMetaResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.UpdateDocumentMetaRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
Title: req.Title,
|
||||
Summary: req.Summary,
|
||||
}
|
||||
if req.Tags != nil {
|
||||
tags := req.Tags
|
||||
serviceReq.Tags = &tags
|
||||
}
|
||||
|
||||
if _, err := document_service.DocumentSvc.UpdateDocumentMeta(ctx, serviceReq); err != nil {
|
||||
return &pb.UpdateDocumentMetaResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.UpdateDocumentMetaResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) UpdateDocumentSettings(ctx context.Context, req *pb.UpdateDocumentSettingsRequest) (*pb.UpdateDocumentSettingsResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.UpdateDocumentSettingsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil || req.ExternalId == "" || req.IsPublic == nil {
|
||||
return &pb.UpdateDocumentSettingsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.UpdateDocumentSettingsRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
IsPublic: req.GetIsPublic(),
|
||||
}
|
||||
updated, err := document_service.DocumentSvc.UpdateDocumentSettings(ctx, serviceReq)
|
||||
if err != nil {
|
||||
return &pb.UpdateDocumentSettingsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.UpdateDocumentSettingsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
IsPublic: utils.Of(updated.IsPublic),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) UploadDocumentAttachment(ctx context.Context, req *pb.UploadDocumentAttachmentRequest) (*pb.UploadDocumentAttachmentResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.UploadDocumentAttachmentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil || req.DocumentExternalId == "" || len(req.FileContent) == 0 {
|
||||
return &pb.UploadDocumentAttachmentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
attachment, err := document_service.DocumentSvc.UploadAttachment(
|
||||
ctx,
|
||||
userExternalID,
|
||||
req.DocumentExternalId,
|
||||
req.FileContent,
|
||||
req.FileName,
|
||||
req.GetContentType(),
|
||||
)
|
||||
if err != nil {
|
||||
return &pb.UploadDocumentAttachmentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.UploadDocumentAttachmentResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Attachment: toAttachmentResponse(attachment),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) ListDocumentAttachments(ctx context.Context, req *pb.ListDocumentAttachmentsRequest) (*pb.ListDocumentAttachmentsResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.ListDocumentAttachmentsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil || req.DocumentExternalId == "" {
|
||||
return &pb.ListDocumentAttachmentsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
attachments, err := document_service.DocumentSvc.ListAttachments(ctx, req.DocumentExternalId)
|
||||
if err != nil {
|
||||
return &pb.ListDocumentAttachmentsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
respAttachments := make([]*pb.AttachmentResponse, 0, len(attachments))
|
||||
for _, attachment := range attachments {
|
||||
respAttachments = append(respAttachments, toAttachmentResponse(attachment))
|
||||
}
|
||||
|
||||
return &pb.ListDocumentAttachmentsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Attachments: respAttachments,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) DeleteDocumentAttachment(ctx context.Context, req *pb.DeleteDocumentAttachmentRequest) (*pb.DeleteDocumentAttachmentResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.DeleteDocumentAttachmentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil || req.DocumentExternalId == "" || req.AttachmentExternalId == "" {
|
||||
return &pb.DeleteDocumentAttachmentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
if err := document_service.DocumentSvc.DeleteAttachment(ctx, req.DocumentExternalId, req.AttachmentExternalId); err != nil {
|
||||
return &pb.DeleteDocumentAttachmentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.DeleteDocumentAttachmentResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) ListDocumentVersions(ctx context.Context, req *pb.ListDocumentVersionsRequest) (*pb.ListDocumentVersionsResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.ListDocumentVersionsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil || req.DocumentExternalId == "" {
|
||||
return &pb.ListDocumentVersionsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
items, total, err := document_service.DocumentSvc.ListDocumentVersions(ctx, req.DocumentExternalId, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return &pb.ListDocumentVersionsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
respItems := make([]*pb.DocumentVersionResponse, 0, len(items))
|
||||
for _, item := range items {
|
||||
respItems = append(respItems, toDocumentVersionResponse(item))
|
||||
}
|
||||
return &pb.ListDocumentVersionsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Versions: respItems,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) GetDocumentVersionContent(ctx context.Context, req *pb.GetDocumentVersionContentRequest) (*pb.GetDocumentVersionContentResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.GetDocumentVersionContentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil || req.DocumentExternalId == "" || req.Version <= 0 {
|
||||
return &pb.GetDocumentVersionContentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
item, err := document_service.DocumentSvc.GetDocumentVersionContent(ctx, req.DocumentExternalId, req.Version)
|
||||
if err != nil {
|
||||
return &pb.GetDocumentVersionContentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
return &pb.GetDocumentVersionContentResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Version: toDocumentVersionResponse(item),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) CreateTemplate(ctx context.Context, req *pb.CreateTemplateRequest) (*pb.CreateTemplateResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.CreateTemplateResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
if req == nil {
|
||||
return &pb.CreateTemplateResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.CreateTemplateRequest{
|
||||
UserExternalID: userExternalID,
|
||||
TargetContainer: template_container_mapper.FromProtoType(req.TargetContainer),
|
||||
TemplateContent: req.TemplateContent,
|
||||
Type: doc_type_mapper.FromProtoType(req.Type),
|
||||
}
|
||||
if req.KnowledgeBaseId != "" {
|
||||
serviceReq.KnowledgeBaseExternalID = utils.Of(req.KnowledgeBaseId)
|
||||
}
|
||||
|
||||
if err := document_service.DocumentSvc.CreateTemplate(ctx, serviceReq); err != nil {
|
||||
return &pb.CreateTemplateResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.CreateTemplateResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) GetTemplate(ctx context.Context, req *pb.GetTemplateRequest) (*pb.GetTemplateResponse, error) {
|
||||
if req == nil || req.TemplateId <= 0 {
|
||||
return &pb.GetTemplateResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.GetTemplateResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
resp, err := document_service.DocumentSvc.GetTemplateByID(req.TemplateId)
|
||||
if err != nil {
|
||||
return &pb.GetTemplateResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
if req.RecordRecentLog {
|
||||
_ = document_service.DocumentSvc.CreateRecentTemplate(&dto.CreateRecentTemplateRequest{
|
||||
UserExternalID: userExternalID,
|
||||
TemplateID: req.TemplateId,
|
||||
AccessTime: time.Now(),
|
||||
})
|
||||
}
|
||||
return &pb.GetTemplateResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Template: toTemplateResponse(resp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) ListRecentTemplates(ctx context.Context, req *pb.ListRecentTemplatesRequest) (*pb.ListRecentTemplatesResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListRecentTemplatesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.ListRecentTemplatesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
var startTime *time.Time
|
||||
if req.StartTime != nil && *req.StartTime != "" {
|
||||
t, err := time.Parse(time.RFC3339, *req.StartTime)
|
||||
if err != nil {
|
||||
return &pb.ListRecentTemplatesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
startTime = &t
|
||||
}
|
||||
var endTime *time.Time
|
||||
if req.EndTime != nil && *req.EndTime != "" {
|
||||
t, err := time.Parse(time.RFC3339, *req.EndTime)
|
||||
if err != nil {
|
||||
return &pb.ListRecentTemplatesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
endTime = &t
|
||||
}
|
||||
|
||||
serviceReq := &dto.ListRecentTemplatesRequest{
|
||||
UserExternalID: userExternalID,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
templates, total, err := document_service.DocumentSvc.ListRecentTemplates(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListRecentTemplatesResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
respTemplates := make([]*pb.TemplateResponse, 0, len(templates))
|
||||
for _, tpl := range templates {
|
||||
respTemplates = append(respTemplates, toTemplateResponse(tpl))
|
||||
}
|
||||
return &pb.ListRecentTemplatesResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Templates: respTemplates,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) ListTemplates(ctx context.Context, req *pb.ListTemplatesRequest) (*pb.ListTemplatesResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.ListTemplatesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil {
|
||||
return &pb.ListTemplatesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
filterArgs := &dto.TemplateListFilterArgs{
|
||||
NameKeyword: req.NameKeyword,
|
||||
KnowledgeBaseID: req.KnowledgeBaseId,
|
||||
}
|
||||
if req.TargetContainer != nil {
|
||||
container := template_container_mapper.FromProtoType(req.GetTargetContainer())
|
||||
filterArgs.TargetContainer = utils.Of(container)
|
||||
}
|
||||
if req.Type != nil {
|
||||
filterArgs.Type = utils.Of(doc_type_mapper.FromProtoType(req.GetType()))
|
||||
}
|
||||
|
||||
sortArgs := dto.SortArgs{Field: "created_at", Desc: true}
|
||||
if req.OrderBy != nil {
|
||||
sortArgs.Field = req.GetOrderBy()
|
||||
}
|
||||
if req.OrderDesc != nil {
|
||||
sortArgs.Desc = req.GetOrderDesc()
|
||||
}
|
||||
|
||||
serviceReq := &dto.TemplateListByExternalRequest{
|
||||
FilterArgs: filterArgs,
|
||||
SortArgs: sortArgs,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
if req.OnlyMine {
|
||||
serviceReq.CreatorExternalID = userExternalID
|
||||
}
|
||||
if req.TargetContainer != nil && template_container_mapper.FromProtoType(req.GetTargetContainer()) == dto.TemplateContainerOwn {
|
||||
serviceReq.CreatorExternalID = userExternalID
|
||||
}
|
||||
|
||||
templates, total, err := document_service.DocumentSvc.ListTemplatesByExternal(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListTemplatesResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respTemplates := make([]*pb.TemplateResponse, 0, len(templates))
|
||||
for _, tpl := range templates {
|
||||
respTemplates = append(respTemplates, toTemplateResponse(tpl))
|
||||
}
|
||||
|
||||
return &pb.ListTemplatesResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Templates: respTemplates,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) UpdateTemplateSettings(ctx context.Context, req *pb.UpdateTemplateSettingsRequest) (*pb.UpdateTemplateSettingsResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.UpdateTemplateSettingsResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
if req == nil || req.TemplateId <= 0 {
|
||||
return &pb.UpdateTemplateSettingsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.UpdateTemplateSettingsRequest{
|
||||
UserExternalID: userExternalID,
|
||||
TemplateID: req.TemplateId,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
IsPublic: req.IsPublic,
|
||||
}
|
||||
|
||||
if err := document_service.DocumentSvc.UpdateTemplateSettings(ctx, serviceReq); err != nil {
|
||||
return &pb.UpdateTemplateSettingsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.UpdateTemplateSettingsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *DocumentServiceServer) DeleteDocument(ctx context.Context, req *pb.DeleteDocumentRequest) (*pb.DeleteDocumentResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.DeleteDocumentResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
if req == nil || req.DocumentExternalId == "" {
|
||||
return &pb.DeleteDocumentResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
if err := document_service.DocumentSvc.DeleteDocumentByExternalID(ctx, req.DocumentExternalId); err != nil {
|
||||
return &pb.DeleteDocumentResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.DeleteDocumentResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/config"
|
||||
"github.com/XingfenD/yoresee_doc/internal/middleware"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func UnaryAuthInterceptor(allowUnauth map[string]struct{}) grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
if _, ok := allowUnauth[info.FullMethod]; ok {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
if md, ok := metadata.FromIncomingContext(ctx); ok {
|
||||
if key := config.GlobalConfig.Backend.InternalRPCKey; key != "" {
|
||||
if values := md.Get("x-internal-key"); len(values) > 0 && values[0] == key {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
authHeader := ""
|
||||
if md, ok := metadata.FromIncomingContext(ctx); ok {
|
||||
if values := md.Get("authorization"); len(values) > 0 {
|
||||
authHeader = values[0]
|
||||
} else if values := md.Get("Authorization"); len(values) > 0 {
|
||||
authHeader = values[0]
|
||||
}
|
||||
}
|
||||
|
||||
claims, err := middleware.JWTAuth.ValidateAuthorizationHeader(authHeader)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Unauthenticated, err.Error())
|
||||
}
|
||||
|
||||
ctx = context.WithValue(ctx, "user_external_id", claims.ExternalID)
|
||||
ctx = context.WithValue(ctx, "username", claims.Username)
|
||||
|
||||
return handler(ctx, req)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/dto"
|
||||
"github.com/XingfenD/yoresee_doc/internal/repository/user_repo"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/auth_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/invitation_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
"github.com/XingfenD/yoresee_doc/internal/utils"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type InvitationServiceServer struct {
|
||||
pb.UnimplementedInvitationServiceServer
|
||||
userRepo *user_repo.UserRepository
|
||||
}
|
||||
|
||||
func NewInvitationServiceServer(userRepo *user_repo.UserRepository) *InvitationServiceServer {
|
||||
return &InvitationServiceServer{
|
||||
userRepo: userRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) requireAdmin(ctx context.Context) error {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return status.StatusTokenInvalid
|
||||
}
|
||||
isAdmin, err := auth_service.AuthSvc.IsAdmin(userExternalID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isAdmin {
|
||||
return status.StatusPermissionDenied
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseOptionalTime(input *string) (*time.Time, error) {
|
||||
if input == nil || strings.TrimSpace(*input) == "" {
|
||||
return nil, nil
|
||||
}
|
||||
tm, err := time.Parse(time.RFC3339, *input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tm, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) CreateInvitation(ctx context.Context, req *pb.CreateInvitationRequest) (*pb.CreateInvitationResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
|
||||
expiresAt, err := parseOptionalTime(req.ExpiresAt)
|
||||
if err != nil {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
inv, err := invitation_service.InvitationSvc.CreateInvitation(&dto.CreateInvitationRequest{
|
||||
CreatorExternalID: userExternalID,
|
||||
MaxUsedCnt: req.MaxUsedCnt,
|
||||
ExpiresAt: expiresAt,
|
||||
Note: req.Note,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
user, _ := s.userRepo.GetByExternalID(userExternalID).Exec()
|
||||
resp := &dto.InvitationResponse{
|
||||
Code: inv.Code,
|
||||
CreatedByExternalID: userExternalID,
|
||||
CreatedByName: "",
|
||||
UsedCnt: inv.UsedCnt,
|
||||
MaxUsedCnt: inv.MaxUsedCnt,
|
||||
ExpiresAt: inv.ExpiresAt,
|
||||
CreatedAt: inv.CreatedAt,
|
||||
Disabled: inv.Disabled,
|
||||
Note: inv.Note,
|
||||
}
|
||||
if user != nil {
|
||||
if user.Nickname != "" {
|
||||
resp.CreatedByName = user.Nickname
|
||||
} else {
|
||||
resp.CreatedByName = user.Username
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.CreateInvitationResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Invitation: toInvitationResponse(resp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) ListInvitations(ctx context.Context, req *pb.ListInvitationsRequest) (*pb.ListInvitationsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
onlyMine := req.OnlyMine != nil && req.GetOnlyMine()
|
||||
if !onlyMine {
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
var creatorID *int64
|
||||
if onlyMine {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
id, err := s.userRepo.GetIDByExternalID(userExternalID).Exec()
|
||||
if err != nil {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromErr(status.StatusUserNotFound)}, nil
|
||||
}
|
||||
creatorID = utils.Of(id)
|
||||
}
|
||||
|
||||
sortArgs := dto.SortArgs{Field: "created_at", Desc: true}
|
||||
if req.OrderBy != nil {
|
||||
sortArgs.Field = req.GetOrderBy()
|
||||
}
|
||||
if req.OrderDesc != nil {
|
||||
sortArgs.Desc = req.GetOrderDesc()
|
||||
}
|
||||
|
||||
listReq := &dto.ListInvitationsReq{
|
||||
CreatorID: creatorID,
|
||||
MaxUsedCnt: req.MaxUsedCnt,
|
||||
ExpiresAtStart: req.ExpiresAtStart,
|
||||
ExpiresAtEnd: req.ExpiresAtEnd,
|
||||
CreatedAtStart: req.CreatedAtStart,
|
||||
CreatedAtEnd: req.CreatedAtEnd,
|
||||
Disabled: req.Disabled,
|
||||
OnlyMine: req.OnlyMine,
|
||||
Keyword: req.Keyword,
|
||||
SortArgs: sortArgs,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
|
||||
invitations, total, err := invitation_service.InvitationSvc.ListInvitations(listReq)
|
||||
if err != nil {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
creatorIDs := make([]int64, 0, len(invitations))
|
||||
for _, inv := range invitations {
|
||||
creatorIDs = append(creatorIDs, inv.CreatedBy)
|
||||
}
|
||||
creatorMap, _ := s.userRepo.MGetUserByID(creatorIDs).Exec()
|
||||
|
||||
respInvites := make([]*pb.InvitationResponse, 0, len(invitations))
|
||||
for _, inv := range invitations {
|
||||
createdByExternalID := ""
|
||||
createdByName := ""
|
||||
if creator := creatorMap[inv.CreatedBy]; creator != nil {
|
||||
createdByExternalID = creator.ExternalID
|
||||
if creator.Nickname != "" {
|
||||
createdByName = creator.Nickname
|
||||
} else {
|
||||
createdByName = creator.Username
|
||||
}
|
||||
}
|
||||
resp := &dto.InvitationResponse{
|
||||
Code: inv.Code,
|
||||
CreatedByExternalID: createdByExternalID,
|
||||
CreatedByName: createdByName,
|
||||
UsedCnt: inv.UsedCnt,
|
||||
MaxUsedCnt: inv.MaxUsedCnt,
|
||||
ExpiresAt: inv.ExpiresAt,
|
||||
CreatedAt: inv.CreatedAt,
|
||||
Disabled: inv.Disabled,
|
||||
Note: inv.Note,
|
||||
}
|
||||
respInvites = append(respInvites, toInvitationResponse(resp))
|
||||
}
|
||||
|
||||
return &pb.ListInvitationsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Invitations: respInvites,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) UpdateInvitation(ctx context.Context, req *pb.UpdateInvitationRequest) (*pb.UpdateInvitationResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.Code) == "" {
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
expiresAt, err := parseOptionalTime(req.ExpiresAt)
|
||||
if err != nil {
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
if err := invitation_service.InvitationSvc.UpdateInvitation(&dto.UpdateInvitationRequest{
|
||||
Code: req.Code,
|
||||
MaxUsedCnt: req.MaxUsedCnt,
|
||||
ExpiresAt: expiresAt,
|
||||
Disabled: req.Disabled,
|
||||
Note: req.Note,
|
||||
}); err != nil {
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) DeleteInvitation(ctx context.Context, req *pb.DeleteInvitationRequest) (*pb.DeleteInvitationResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.Code) == "" {
|
||||
return &pb.DeleteInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.DeleteInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
if err := invitation_service.InvitationSvc.DeleteInvitation(&dto.DeleteInvitationRequest{Code: req.Code}); err != nil {
|
||||
return &pb.DeleteInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.DeleteInvitationResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) ListInvitationRecords(ctx context.Context, req *pb.ListInvitationRecordsRequest) (*pb.ListInvitationRecordsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
onlyMine := req.OnlyMine != nil && req.GetOnlyMine()
|
||||
if !onlyMine {
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
var creatorID *int64
|
||||
if onlyMine {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
id, err := s.userRepo.GetIDByExternalID(userExternalID).Exec()
|
||||
if err != nil {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromErr(status.StatusUserNotFound)}, nil
|
||||
}
|
||||
creatorID = utils.Of(id)
|
||||
}
|
||||
|
||||
listReq := &dto.ListInvitationRecordsRequest{
|
||||
Code: req.Code,
|
||||
Status: req.Status,
|
||||
UsedAtStart: req.UsedAtStart,
|
||||
UsedAtEnd: req.UsedAtEnd,
|
||||
CreatorID: creatorID,
|
||||
OnlyMine: req.OnlyMine,
|
||||
Keyword: req.Keyword,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
|
||||
records, total, err := invitation_service.InvitationSvc.ListInvitationRecords(listReq)
|
||||
if err != nil {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
userIDs := make([]int64, 0, len(records))
|
||||
for _, r := range records {
|
||||
if r.UsedByUserID != nil {
|
||||
userIDs = append(userIDs, *r.UsedByUserID)
|
||||
}
|
||||
}
|
||||
userMap, _ := s.userRepo.MGetUserByID(userIDs).Exec()
|
||||
|
||||
respRecords := make([]*pb.InvitationRecordResponse, 0, len(records))
|
||||
for _, r := range records {
|
||||
usedBy := r.UsedBy
|
||||
usedByExternalID := ""
|
||||
if r.UsedByUserID != nil {
|
||||
if user := userMap[*r.UsedByUserID]; user != nil {
|
||||
usedByExternalID = user.ExternalID
|
||||
if user.Nickname != "" {
|
||||
usedBy = user.Nickname
|
||||
} else if user.Username != "" {
|
||||
usedBy = user.Username
|
||||
}
|
||||
}
|
||||
}
|
||||
resp := &dto.InvitationRecordResponse{
|
||||
Code: r.Code,
|
||||
UsedBy: usedBy,
|
||||
UsedByExternalID: usedByExternalID,
|
||||
UsedAt: r.UsedAt,
|
||||
Status: r.Status,
|
||||
}
|
||||
respRecords = append(respRecords, toInvitationRecordResponse(resp))
|
||||
}
|
||||
|
||||
return &pb.ListInvitationRecordsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Records: respRecords,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/dto"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/document_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/knowledge_base_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
"github.com/XingfenD/yoresee_doc/internal/utils"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type KnowledgeBaseServiceServer struct {
|
||||
pb.UnimplementedKnowledgeBaseServiceServer
|
||||
}
|
||||
|
||||
func NewKnowledgeBaseServiceServer() *KnowledgeBaseServiceServer {
|
||||
return &KnowledgeBaseServiceServer{}
|
||||
}
|
||||
|
||||
func (s *KnowledgeBaseServiceServer) ListKnowledgeBases(ctx context.Context, req *pb.ListKnowledgeBasesRequest) (*pb.ListKnowledgeBasesResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListKnowledgeBasesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.ListKnowledgeBasesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
filterArgs := &dto.KnowledgeBaseListFilterArgs{
|
||||
IsPublic: req.IsPublic,
|
||||
NameKeyword: req.NameKeyword,
|
||||
}
|
||||
if req.CreateTimeRange != nil {
|
||||
filterArgs.CreateTimeRangeStart = req.CreateTimeRange.Start
|
||||
filterArgs.CreateTimeRangeEnd = req.CreateTimeRange.End
|
||||
}
|
||||
if req.UpdateTimeRange != nil {
|
||||
filterArgs.UpdateTimeRangeStart = req.UpdateTimeRange.Start
|
||||
filterArgs.UpdateTimeRangeEnd = req.UpdateTimeRange.End
|
||||
}
|
||||
|
||||
sortArgs := dto.SortArgs{Field: "created_at", Desc: true}
|
||||
if req.OrderBy != nil {
|
||||
sortArgs.Field = req.GetOrderBy()
|
||||
}
|
||||
if req.OrderDesc != nil {
|
||||
sortArgs.Desc = req.GetOrderDesc()
|
||||
}
|
||||
|
||||
serviceReq := &dto.KnowledgeBaseListByExternalRequest{
|
||||
CreatorExternalID: "",
|
||||
FilterArgs: filterArgs,
|
||||
SortArgs: sortArgs,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
if req.OnlyMine {
|
||||
serviceReq.CreatorExternalID = userExternalID
|
||||
}
|
||||
|
||||
kbs, total, err := knowledge_base_service.KnowledgeBaseSvc.ListByExternal(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListKnowledgeBasesResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respKBs := make([]*pb.KnowledgeBaseResponse, 0, len(kbs))
|
||||
for _, kb := range kbs {
|
||||
respKBs = append(respKBs, toKnowledgeBaseResponse(kb))
|
||||
}
|
||||
|
||||
return &pb.ListKnowledgeBasesResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
KnowledgeBases: respKBs,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *KnowledgeBaseServiceServer) GetKnowledgeBase(ctx context.Context, req *pb.GetKnowledgeBaseRequest) (*pb.GetKnowledgeBaseResponse, error) {
|
||||
if req == nil || req.KnowledgeBaseExternalId == "" {
|
||||
return &pb.GetKnowledgeBaseResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.GetKnowledgeBaseResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
kbDTO, err := knowledge_base_service.KnowledgeBaseSvc.GetByExternalID(&dto.KnowledgeBaseGetByExternalIDRequest{
|
||||
KnowledgeBaseExternalID: req.KnowledgeBaseExternalId,
|
||||
}).WithExtend().Exec()
|
||||
if err != nil {
|
||||
return &pb.GetKnowledgeBaseResponse{Base: baseResponseFromErr(status.StatusKnowledgeBaseNotFound)}, nil
|
||||
}
|
||||
|
||||
if req.RecordRecentLog {
|
||||
knowledge_base_service.KnowledgeBaseSvc.CreateRecentKnowledgeBase(&dto.CreateRecentKnowledgeBaseRequest{
|
||||
UserExternalID: userExternalID,
|
||||
KnowledgeBaseExternalID: req.KnowledgeBaseExternalId,
|
||||
AssessTime: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
svcReq := &dto.ListDocumentsByExternalRequest{
|
||||
ExternalArgs: &dto.DocumentsListExternalArgs{
|
||||
KnowledgeExternalID: utils.Of(kbDTO.ExternalID),
|
||||
},
|
||||
ListDocumentsBaseArgs: dto.ListDocumentsBaseArgs{
|
||||
DirectoryOnly: req.DirectoryOnly,
|
||||
},
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
Options: &dto.RecursiveOptions{
|
||||
IncludeChildren: true,
|
||||
Recursive: true,
|
||||
},
|
||||
}
|
||||
documents, totalCount, err := document_service.DocumentSvc.ListDocumentsByExternal(
|
||||
ctx,
|
||||
svcReq,
|
||||
)
|
||||
if err != nil {
|
||||
return &pb.GetKnowledgeBaseResponse{Base: baseResponseFromErr(status.StatusDocumentNotFound)}, nil
|
||||
}
|
||||
|
||||
respDocs := make([]*pb.DocumentResponse, 0, len(documents))
|
||||
for _, doc := range documents {
|
||||
respDocs = append(respDocs, toDocumentResponse(doc))
|
||||
}
|
||||
|
||||
return &pb.GetKnowledgeBaseResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
KnowledgeBase: toKnowledgeBaseResponse(kbDTO),
|
||||
Documents: respDocs,
|
||||
TotalCount: totalCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *KnowledgeBaseServiceServer) CreateKnowledgeBase(ctx context.Context, req *pb.CreateKnowledgeBaseRequest) (*pb.CreateKnowledgeBaseResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.CreateKnowledgeBaseResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if req == nil || req.Name == "" {
|
||||
return &pb.CreateKnowledgeBaseResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
resp, err := knowledge_base_service.KnowledgeBaseSvc.Create(&dto.CreateKnowledgeBaseRequest{
|
||||
CreatorExternalID: userExternalID,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Cover: req.Cover,
|
||||
IsPublic: req.IsPublic,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.CreateKnowledgeBaseResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.CreateKnowledgeBaseResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
ExternalId: resp.ExternalID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *KnowledgeBaseServiceServer) ListRecentKnowledgeBases(ctx context.Context, req *pb.ListRecentKnowledgeBasesRequest) (*pb.ListRecentKnowledgeBasesResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListRecentKnowledgeBasesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.ListRecentKnowledgeBasesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
var startTime *time.Time
|
||||
if req.StartTime != nil && *req.StartTime != "" {
|
||||
t, err := time.Parse(time.RFC3339, *req.StartTime)
|
||||
if err != nil {
|
||||
return &pb.ListRecentKnowledgeBasesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
startTime = &t
|
||||
}
|
||||
|
||||
var endTime *time.Time
|
||||
if req.EndTime != nil && *req.EndTime != "" {
|
||||
t, err := time.Parse(time.RFC3339, *req.EndTime)
|
||||
if err != nil {
|
||||
return &pb.ListRecentKnowledgeBasesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
endTime = &t
|
||||
}
|
||||
|
||||
serviceReq := &dto.ListRecentKnowledgeBasesRequest{
|
||||
UserExternalID: userExternalID,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
|
||||
kbs, total, err := knowledge_base_service.KnowledgeBaseSvc.ListRecentKnowledgeBases(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListRecentKnowledgeBasesResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respKBs := make([]*pb.KnowledgeBaseResponse, 0, len(kbs))
|
||||
for _, kb := range kbs {
|
||||
respKBs = append(respKBs, toKnowledgeBaseResponse(kb))
|
||||
}
|
||||
|
||||
return &pb.ListRecentKnowledgeBasesResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
KnowledgeBases: respKBs,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/dto"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/auth_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/membership_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type MembershipServiceServer struct {
|
||||
pb.UnimplementedMembershipServiceServer
|
||||
}
|
||||
|
||||
func NewMembershipServiceServer() *MembershipServiceServer {
|
||||
return &MembershipServiceServer{}
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) requireAdmin(ctx context.Context) error {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return status.StatusTokenInvalid
|
||||
}
|
||||
isAdmin, err := auth_service.AuthSvc.IsAdmin(userExternalID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isAdmin {
|
||||
return status.StatusPermissionDenied
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) ListUserGroups(ctx context.Context, req *pb.ListUserGroupsRequest) (*pb.ListUserGroupsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListUserGroupsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.ListUserGroupsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.ListUserGroupsRequest{
|
||||
Keyword: req.Keyword,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
groups, total, err := membership_service.MembershipSvc.ListUserGroups(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListUserGroupsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respGroups := make([]*pb.UserGroupResponse, 0, len(groups))
|
||||
for _, group := range groups {
|
||||
respGroups = append(respGroups, toUserGroupResponse(group))
|
||||
}
|
||||
|
||||
return &pb.ListUserGroupsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
UserGroups: respGroups,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) GetUserGroup(ctx context.Context, req *pb.GetUserGroupRequest) (*pb.GetUserGroupResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.GetUserGroupResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.GetUserGroupResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
group, err := membership_service.MembershipSvc.GetUserGroup(&dto.GetUserGroupRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.GetUserGroupResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.GetUserGroupResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
UserGroup: toUserGroupResponse(group),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) CreateUserGroup(ctx context.Context, req *pb.CreateUserGroupRequest) (*pb.CreateUserGroupResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.Name) == "" {
|
||||
return &pb.CreateUserGroupResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.CreateUserGroupResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.CreateUserGroupResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
externalID, err := membership_service.MembershipSvc.CreateUserGroup(&dto.CreateUserGroupRequest{
|
||||
CreatorUserExternalID: userExternalID,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
MemberUserExternalIDs: req.MemberUserExternalIds,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.CreateUserGroupResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.CreateUserGroupResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
ExternalId: externalID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) UpdateUserGroup(ctx context.Context, req *pb.UpdateUserGroupRequest) (*pb.UpdateUserGroupResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.UpdateUserGroupResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.UpdateUserGroupResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
err := membership_service.MembershipSvc.UpdateUserGroup(&dto.UpdateUserGroupRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
SyncMembers: req.SyncMembers,
|
||||
MemberUserExternalIDs: req.MemberUserExternalIds,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.UpdateUserGroupResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
return &pb.UpdateUserGroupResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) DeleteUserGroup(ctx context.Context, req *pb.DeleteUserGroupRequest) (*pb.DeleteUserGroupResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.DeleteUserGroupResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.DeleteUserGroupResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
if err := membership_service.MembershipSvc.DeleteUserGroup(&dto.DeleteUserGroupRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
}); err != nil {
|
||||
return &pb.DeleteUserGroupResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.DeleteUserGroupResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) ListUsers(ctx context.Context, req *pb.ListUsersRequest) (*pb.ListUsersResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListUsersResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.ListUsersResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.ListUsersRequest{
|
||||
Keyword: req.Keyword,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
users, total, err := membership_service.MembershipSvc.ListUsers(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListUsersResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respUsers := make([]*pb.UserResponse, 0, len(users))
|
||||
for _, user := range users {
|
||||
respUsers = append(respUsers, toUserResponse(user))
|
||||
}
|
||||
|
||||
return &pb.ListUsersResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Users: respUsers,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) UpdateUser(ctx context.Context, req *pb.UpdateUserRequest) (*pb.UpdateUserResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.UpdateUserResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.UpdateUserResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.UpdateUserRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
Username: req.Username,
|
||||
Email: req.Email,
|
||||
Nickname: req.Nickname,
|
||||
Status: req.Status,
|
||||
}
|
||||
if err := membership_service.MembershipSvc.UpdateUser(serviceReq); err != nil {
|
||||
return &pb.UpdateUserResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.UpdateUserResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) ListUserGroupMembers(ctx context.Context, req *pb.ListUserGroupMembersRequest) (*pb.ListUserGroupMembersResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.ListUserGroupMembersResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.ListUserGroupMembersResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.ListUserGroupMembersRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
Keyword: req.Keyword,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
users, total, err := membership_service.MembershipSvc.ListUserGroupMembers(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListUserGroupMembersResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respUsers := make([]*pb.UserResponse, 0, len(users))
|
||||
for _, user := range users {
|
||||
respUsers = append(respUsers, toUserResponse(user))
|
||||
}
|
||||
|
||||
return &pb.ListUserGroupMembersResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Users: respUsers,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) ListOrgNodes(ctx context.Context, req *pb.ListOrgNodesRequest) (*pb.ListOrgNodesResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListOrgNodesResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.ListOrgNodesResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.ListOrgNodesRequest{
|
||||
ParentExternalID: req.ParentExternalId,
|
||||
Keyword: req.Keyword,
|
||||
IncludeChildren: req.IncludeChildren,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
nodes, total, err := membership_service.MembershipSvc.ListOrgNodes(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListOrgNodesResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respNodes := make([]*pb.OrgNodeResponse, 0, len(nodes))
|
||||
for _, node := range nodes {
|
||||
respNodes = append(respNodes, toOrgNodeResponse(node))
|
||||
}
|
||||
|
||||
return &pb.ListOrgNodesResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
OrgNodes: respNodes,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) GetOrgNode(ctx context.Context, req *pb.GetOrgNodeRequest) (*pb.GetOrgNodeResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.GetOrgNodeResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.GetOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
node, err := membership_service.MembershipSvc.GetOrgNode(&dto.GetOrgNodeRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
IncludeChildren: req.IncludeChildren,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.GetOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.GetOrgNodeResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
OrgNode: toOrgNodeResponse(node),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) CreateOrgNode(ctx context.Context, req *pb.CreateOrgNodeRequest) (*pb.CreateOrgNodeResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.Name) == "" {
|
||||
return &pb.CreateOrgNodeResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.CreateOrgNodeResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.CreateOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
externalID, err := membership_service.MembershipSvc.CreateOrgNode(&dto.CreateOrgNodeRequest{
|
||||
CreatorUserExternalID: userExternalID,
|
||||
ParentExternalID: req.ParentExternalId,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
MemberUserExternalIDs: req.MemberUserExternalIds,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.CreateOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.CreateOrgNodeResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
ExternalId: externalID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) UpdateOrgNode(ctx context.Context, req *pb.UpdateOrgNodeRequest) (*pb.UpdateOrgNodeResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.UpdateOrgNodeResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.UpdateOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
err := membership_service.MembershipSvc.UpdateOrgNode(&dto.UpdateOrgNodeRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
SyncMembers: req.SyncMembers,
|
||||
MemberUserExternalIDs: req.MemberUserExternalIds,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.UpdateOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
return &pb.UpdateOrgNodeResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) DeleteOrgNode(ctx context.Context, req *pb.DeleteOrgNodeRequest) (*pb.DeleteOrgNodeResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.DeleteOrgNodeResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.DeleteOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
if err := membership_service.MembershipSvc.DeleteOrgNode(&dto.DeleteOrgNodeRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
}); err != nil {
|
||||
return &pb.DeleteOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.DeleteOrgNodeResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) MoveOrgNode(ctx context.Context, req *pb.MoveOrgNodeRequest) (*pb.MoveOrgNodeResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.MoveOrgNodeResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.MoveOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
if err := membership_service.MembershipSvc.MoveOrgNode(&dto.MoveOrgNodeRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
NewParentExternalID: req.NewParentExternalId,
|
||||
}); err != nil {
|
||||
return &pb.MoveOrgNodeResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.MoveOrgNodeResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *MembershipServiceServer) ListOrgNodeMembers(ctx context.Context, req *pb.ListOrgNodeMembersRequest) (*pb.ListOrgNodeMembersResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.ExternalId) == "" {
|
||||
return &pb.ListOrgNodeMembersResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.ListOrgNodeMembersResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
serviceReq := &dto.ListOrgNodeMembersRequest{
|
||||
ExternalID: req.ExternalId,
|
||||
Keyword: req.Keyword,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
users, total, err := membership_service.MembershipSvc.ListOrgNodeMembers(serviceReq)
|
||||
if err != nil {
|
||||
return &pb.ListOrgNodeMembersResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respUsers := make([]*pb.UserResponse, 0, len(users))
|
||||
for _, user := range users {
|
||||
respUsers = append(respUsers, toUserResponse(user))
|
||||
}
|
||||
|
||||
return &pb.ListOrgNodeMembersResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Users: respUsers,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func toOrgNodeResponse(node *dto.OrgNodeResponse) *pb.OrgNodeResponse {
|
||||
resp := &pb.OrgNodeResponse{
|
||||
ExternalId: node.ExternalID,
|
||||
ParentExternalId: node.ParentExternalID,
|
||||
Name: node.Name,
|
||||
Path: node.Path,
|
||||
Description: node.Description,
|
||||
CreatorUserExternalId: node.CreatorUserExternalID,
|
||||
MemberCount: int32(node.MemberCount),
|
||||
}
|
||||
if node.Children != nil {
|
||||
resp.Children = make([]*pb.OrgNodeResponse, 0, len(node.Children))
|
||||
for _, child := range node.Children {
|
||||
resp.Children = append(resp.Children, toOrgNodeResponse(child))
|
||||
}
|
||||
}
|
||||
return resp
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/domain_event"
|
||||
"github.com/XingfenD/yoresee_doc/internal/dto"
|
||||
"github.com/XingfenD/yoresee_doc/internal/model"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/auth_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/notification_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type NotificationServiceServer struct {
|
||||
pb.UnimplementedNotificationServiceServer
|
||||
}
|
||||
|
||||
func NewNotificationServiceServer() *NotificationServiceServer {
|
||||
return &NotificationServiceServer{}
|
||||
}
|
||||
|
||||
func (s *NotificationServiceServer) CreateNotification(ctx context.Context, req *pb.CreateNotificationRequest) (*pb.CreateNotificationResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.CreateNotificationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.CreateNotificationResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
|
||||
receiverExternalIDs := req.ReceiverExternalIds
|
||||
if len(receiverExternalIDs) == 0 {
|
||||
receiverExternalIDs = []string{userExternalID}
|
||||
}
|
||||
|
||||
if !onlySelf(receiverExternalIDs, userExternalID) {
|
||||
isAdmin, err := auth_service.AuthSvc.IsAdmin(userExternalID)
|
||||
if err != nil {
|
||||
return &pb.CreateNotificationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
if !isAdmin {
|
||||
return &pb.CreateNotificationResponse{Base: baseResponseFromStatus(status.StatusPermissionDenied)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
evt := domain_event.NotificationCreateEvent{
|
||||
ReceiverExternalIDs: receiverExternalIDs,
|
||||
Type: req.Type,
|
||||
Title: req.Title,
|
||||
Content: req.Content,
|
||||
PayloadJSON: req.PayloadJson,
|
||||
}
|
||||
if err := domain_event.PublishNotificationCreateEvent(ctx, evt); err != nil {
|
||||
return &pb.CreateNotificationResponse{Base: baseResponseFromErr(status.StatusMQNotInitialized)}, nil
|
||||
}
|
||||
|
||||
return &pb.CreateNotificationResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func (s *NotificationServiceServer) ListNotifications(ctx context.Context, req *pb.ListNotificationsRequest) (*pb.ListNotificationsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListNotificationsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.ListNotificationsResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
|
||||
var statusFilter *string
|
||||
if req.Status != nil && strings.TrimSpace(req.GetStatus()) != "" {
|
||||
statusFilter = req.Status
|
||||
}
|
||||
|
||||
list, total, err := notification_service.NotificationSvc.ListNotifications(&dto.ListNotificationsRequest{
|
||||
UserExternalID: userExternalID,
|
||||
Status: statusFilter,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.ListNotificationsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respItems := make([]*pb.Notification, 0, len(list))
|
||||
for _, item := range list {
|
||||
respItems = append(respItems, toNotificationResponse(&item))
|
||||
}
|
||||
|
||||
return &pb.ListNotificationsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Notifications: respItems,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *NotificationServiceServer) MarkNotificationsRead(ctx context.Context, req *pb.MarkNotificationsReadRequest) (*pb.MarkNotificationsReadResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.MarkNotificationsReadResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.MarkNotificationsReadResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
|
||||
err := notification_service.NotificationSvc.MarkRead(&dto.MarkNotificationsReadRequest{
|
||||
UserExternalID: userExternalID,
|
||||
ExternalIDs: req.ExternalIds,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.MarkNotificationsReadResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
return &pb.MarkNotificationsReadResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func (s *NotificationServiceServer) MarkAllNotificationsRead(ctx context.Context, req *pb.MarkAllNotificationsReadRequest) (*pb.MarkAllNotificationsReadResponse, error) {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.MarkAllNotificationsReadResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
if err := notification_service.NotificationSvc.MarkAllRead(userExternalID); err != nil {
|
||||
return &pb.MarkAllNotificationsReadResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
return &pb.MarkAllNotificationsReadResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func toNotificationResponse(item *model.Notification) *pb.Notification {
|
||||
if item == nil {
|
||||
return nil
|
||||
}
|
||||
return &pb.Notification{
|
||||
ExternalId: item.ExternalID,
|
||||
Type: item.Type,
|
||||
Status: item.Status,
|
||||
Title: item.Title,
|
||||
Content: item.Content,
|
||||
Payload: item.Payload,
|
||||
CreatedAt: timeToString(item.CreatedAt),
|
||||
}
|
||||
}
|
||||
|
||||
func onlySelf(list []string, self string) bool {
|
||||
if len(list) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, id := range list {
|
||||
if strings.TrimSpace(id) == "" {
|
||||
continue
|
||||
}
|
||||
if id != self {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/config"
|
||||
"github.com/XingfenD/yoresee_doc/internal/repository"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
"github.com/improbable-eng/grpc-web/go/grpcweb"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func Start(grpcPort, grpcWebPort int, repos *repository.Repositories) (*grpc.Server, error) {
|
||||
allowUnauth := map[string]struct{}{
|
||||
"/yoresee_doc.v1.AuthService/Login": {},
|
||||
"/yoresee_doc.v1.AuthService/Register": {},
|
||||
"/yoresee_doc.v1.SystemService/Health": {},
|
||||
"/yoresee_doc.v1.SystemService/SystemInfo": {},
|
||||
}
|
||||
|
||||
grpcServer := grpc.NewServer(
|
||||
grpc.UnaryInterceptor(UnaryAuthInterceptor(allowUnauth)),
|
||||
)
|
||||
|
||||
pb.RegisterAuthServiceServer(grpcServer, NewAuthServiceServer())
|
||||
pb.RegisterDocumentServiceServer(grpcServer, NewDocumentServiceServer())
|
||||
pb.RegisterKnowledgeBaseServiceServer(grpcServer, NewKnowledgeBaseServiceServer())
|
||||
pb.RegisterSystemServiceServer(grpcServer, NewSystemServiceServer())
|
||||
pb.RegisterMembershipServiceServer(grpcServer, NewMembershipServiceServer())
|
||||
pb.RegisterInvitationServiceServer(grpcServer, NewInvitationServiceServer(repos.User))
|
||||
|
||||
grpcListener, err := net.Listen("tcp", fmt.Sprintf(":%d", grpcPort))
|
||||
if err != nil {
|
||||
return nil, status.GenErrWithCustomMsg(status.StatusServiceInternalError, "listen grpc port failed")
|
||||
}
|
||||
|
||||
go func() {
|
||||
if serveErr := grpcServer.Serve(grpcListener); serveErr != nil {
|
||||
logrus.Errorf("grpc server exited with error: %v", serveErr)
|
||||
}
|
||||
}()
|
||||
|
||||
grpcWebServer := grpcweb.WrapServer(grpcServer,
|
||||
grpcweb.WithOriginFunc(isOriginAllowed),
|
||||
)
|
||||
|
||||
grpcWebHandler := grpcWebHTTPHandler(grpcWebServer)
|
||||
grpcWebAddr := fmt.Sprintf(":%d", grpcWebPort)
|
||||
go func() {
|
||||
if serveErr := http.ListenAndServe(grpcWebAddr, grpcWebHandler); serveErr != nil && !errors.Is(serveErr, http.ErrServerClosed) {
|
||||
logrus.Errorf("grpc-web server exited with error: %v", serveErr)
|
||||
}
|
||||
}()
|
||||
|
||||
return grpcServer, nil
|
||||
}
|
||||
|
||||
func grpcWebHTTPHandler(wrapped *grpcweb.WrappedGrpcServer) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
setGrpcWebCorsHeaders(w, r)
|
||||
if wrapped.IsGrpcWebRequest(r) || wrapped.IsGrpcWebSocketRequest(r) {
|
||||
wrapped.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
if r.Method == http.MethodOptions && wrapped.IsAcceptableGrpcCorsRequest(r) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func setGrpcWebCorsHeaders(w http.ResponseWriter, r *http.Request) {
|
||||
origin := strings.TrimSpace(r.Header.Get("Origin"))
|
||||
if allowedOrigin := resolveAllowedOrigin(origin); allowedOrigin != "" {
|
||||
w.Header().Set("Access-Control-Allow-Origin", allowedOrigin)
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Credentials", strconv.FormatBool(corsAllowCredentials()))
|
||||
w.Header().Set("Access-Control-Allow-Headers", strings.Join(corsAllowedHeaders(), ","))
|
||||
w.Header().Set("Access-Control-Allow-Methods", strings.Join(corsAllowedMethods(), ","))
|
||||
w.Header().Set("Access-Control-Expose-Headers", "Grpc-Status,Grpc-Message,Grpc-Status-Details-Bin")
|
||||
if maxAge := corsMaxAge(); maxAge > 0 {
|
||||
w.Header().Set("Access-Control-Max-Age", strconv.Itoa(maxAge))
|
||||
}
|
||||
}
|
||||
|
||||
func isOriginAllowed(origin string) bool {
|
||||
origin = strings.TrimSpace(origin)
|
||||
if origin == "" {
|
||||
return false
|
||||
}
|
||||
allowedOrigins := corsAllowedOrigins()
|
||||
if len(allowedOrigins) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, allowed := range allowedOrigins {
|
||||
allowed = strings.TrimSpace(allowed)
|
||||
if allowed == "*" || strings.EqualFold(allowed, origin) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func resolveAllowedOrigin(origin string) string {
|
||||
if origin == "" {
|
||||
if len(corsAllowedOrigins()) == 0 {
|
||||
return "*"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
if isOriginAllowed(origin) {
|
||||
return origin
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func corsAllowedOrigins() []string {
|
||||
if config.GlobalConfig == nil {
|
||||
return nil
|
||||
}
|
||||
return config.GlobalConfig.Backend.Security.CORS.AllowedOrigins
|
||||
}
|
||||
|
||||
func corsAllowedMethods() []string {
|
||||
if config.GlobalConfig != nil && len(config.GlobalConfig.Backend.Security.CORS.AllowedMethods) > 0 {
|
||||
return config.GlobalConfig.Backend.Security.CORS.AllowedMethods
|
||||
}
|
||||
return []string{"POST", "GET", "OPTIONS"}
|
||||
}
|
||||
|
||||
func corsAllowedHeaders() []string {
|
||||
if config.GlobalConfig != nil && len(config.GlobalConfig.Backend.Security.CORS.AllowedHeaders) > 0 {
|
||||
return config.GlobalConfig.Backend.Security.CORS.AllowedHeaders
|
||||
}
|
||||
return []string{"Accept", "Accept-Language", "Content-Type", "Content-Length", "X-Grpc-Web", "X-User-Agent", "Grpc-Timeout", "Authorization"}
|
||||
}
|
||||
|
||||
func corsAllowCredentials() bool {
|
||||
if config.GlobalConfig != nil {
|
||||
return config.GlobalConfig.Backend.Security.CORS.AllowCredentials
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func corsMaxAge() int {
|
||||
if config.GlobalConfig != nil {
|
||||
return config.GlobalConfig.Backend.Security.CORS.MaxAge
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/auth_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/setting_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type SettingServiceServer struct {
|
||||
pb.UnimplementedSettingServiceServer
|
||||
}
|
||||
|
||||
func NewSettingServiceServer() *SettingServiceServer {
|
||||
return &SettingServiceServer{}
|
||||
}
|
||||
|
||||
func (s *SettingServiceServer) requireAdmin(ctx context.Context) error {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return status.StatusTokenInvalid
|
||||
}
|
||||
isAdmin, err := auth_service.AuthSvc.IsAdmin(userExternalID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isAdmin {
|
||||
return status.StatusPermissionDenied
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SettingServiceServer) GetSettings(ctx context.Context, req *pb.GetSettingsRequest) (*pb.GetSettingsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.GetSettingsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.GetSettingsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
scene := strings.TrimSpace(req.Scene)
|
||||
groups, err := setting_service.SettingSvc.GetSettings(ctx, scene)
|
||||
if err != nil {
|
||||
return &pb.GetSettingsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
respGroups := make([]*pb.SettingGroup, 0, len(groups))
|
||||
for _, group := range groups {
|
||||
items := make([]*pb.SettingItem, 0, len(group.Items))
|
||||
for _, item := range group.Items {
|
||||
options := make([]*pb.SettingOption, 0, len(item.UI.Options))
|
||||
for _, opt := range item.UI.Options {
|
||||
options = append(options, &pb.SettingOption{
|
||||
Label: opt.Label,
|
||||
LabelKey: opt.LabelKey,
|
||||
Value: opt.Value,
|
||||
})
|
||||
}
|
||||
items = append(items, &pb.SettingItem{
|
||||
Key: item.Key,
|
||||
Label: item.Label,
|
||||
LabelKey: item.LabelKey,
|
||||
Description: item.Description,
|
||||
DescriptionKey: item.DescriptionKey,
|
||||
Type: item.Type,
|
||||
Ui: &pb.SettingUI{
|
||||
Component: item.UI.Component,
|
||||
Options: options,
|
||||
Placeholder: item.UI.Placeholder,
|
||||
PlaceholderKey: item.UI.PlaceholderKey,
|
||||
},
|
||||
Value: item.Value,
|
||||
DefaultValue: item.DefaultValue,
|
||||
Required: item.Required,
|
||||
Readonly: item.Readonly,
|
||||
})
|
||||
}
|
||||
respGroups = append(respGroups, &pb.SettingGroup{
|
||||
Key: group.Key,
|
||||
Title: group.Title,
|
||||
TitleKey: group.TitleKey,
|
||||
Items: items,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.GetSettingsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Groups: respGroups,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *SettingServiceServer) UpdateSettings(ctx context.Context, req *pb.UpdateSettingsRequest) (*pb.UpdateSettingsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.UpdateSettingsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.UpdateSettingsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
updates := make([]setting_service.SettingUpdate, 0, len(req.Updates))
|
||||
for _, update := range req.Updates {
|
||||
if update == nil {
|
||||
continue
|
||||
}
|
||||
updates = append(updates, setting_service.SettingUpdate{
|
||||
Key: update.Key,
|
||||
Value: update.Value,
|
||||
})
|
||||
}
|
||||
if err := setting_service.SettingSvc.UpdateSettings(ctx, updates); err != nil {
|
||||
return &pb.UpdateSettingsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
return &pb.UpdateSettingsResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/config"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/config_service"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type SystemServiceServer struct {
|
||||
pb.UnimplementedSystemServiceServer
|
||||
}
|
||||
|
||||
func NewSystemServiceServer() *SystemServiceServer {
|
||||
return &SystemServiceServer{}
|
||||
}
|
||||
|
||||
func (s *SystemServiceServer) Health(ctx context.Context, req *pb.HealthRequest) (*pb.HealthResponse, error) {
|
||||
return &pb.HealthResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
Status: "healthy",
|
||||
Version: "1.0.0",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *SystemServiceServer) SystemInfo(ctx context.Context, req *pb.SystemInfoRequest) (*pb.SystemInfoResponse, error) {
|
||||
return &pb.SystemInfoResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
SystemName: config.GlobalConfig.Backend.SystemName,
|
||||
SystemRegisterMode: config_service.ConfigSvc.GetSystemRegisterMode(ctx),
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
doc_container_mapper "github.com/XingfenD/yoresee_doc/internal/mapper/doc_container_mapper"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
func validateUpdateDocumentRequest(req *pb.UpdateDocumentRequest) error {
|
||||
if req == nil {
|
||||
return status.StatusParamError
|
||||
}
|
||||
if req.Content == nil && req.KnowledgeBaseExternalId == nil && req.ParentExternalId == nil && req.Title == nil && req.MoveToContainer == nil {
|
||||
return status.GenErrWithCustomMsg(status.StatusParamError, "no update fields")
|
||||
}
|
||||
if req.MoveToContainer != nil {
|
||||
containerType, ok := doc_container_mapper.FromProtoType(*req.MoveToContainer)
|
||||
if !ok {
|
||||
return status.GenErrWithCustomMsg(status.StatusParamError, "invalid move_to_container")
|
||||
}
|
||||
requiresKnowledgeBaseID := doc_container_mapper.RequiresKnowledgeBaseID(containerType)
|
||||
if !requiresKnowledgeBaseID && req.KnowledgeBaseExternalId != nil {
|
||||
return status.GenErrWithCustomMsg(status.StatusParamError, "KnowledgeBaseExternalId not nil")
|
||||
}
|
||||
if requiresKnowledgeBaseID && req.KnowledgeBaseExternalId == nil {
|
||||
return status.GenErrWithCustomMsg(status.StatusParamError, "KnowledgeBaseExternalId is nil")
|
||||
}
|
||||
}
|
||||
if req.MoveToContainer == nil && req.KnowledgeBaseExternalId != nil {
|
||||
return status.GenErrWithCustomMsg(status.StatusParamError, "MoveToContainer is nil")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user