diff --git a/server/router/api/v1/memo_service.go b/server/router/api/v1/memo_service.go index 58f36c23..cee3be85 100644 --- a/server/router/api/v1/memo_service.go +++ b/server/router/api/v1/memo_service.go @@ -225,7 +225,8 @@ func (s *APIV1Service) UpdateMemo(ctx context.Context, request *v1pb.UpdateMemoR if err != nil { return nil, status.Errorf(codes.Internal, "failed to get current user") } - if memo.CreatorID != user.ID { + // Only the creator or admin can update the memo. + if memo.CreatorID != user.ID && !isSuperUser(user) { return nil, status.Errorf(codes.PermissionDenied, "permission denied") } @@ -336,7 +337,8 @@ func (s *APIV1Service) DeleteMemo(ctx context.Context, request *v1pb.DeleteMemoR if err != nil { return nil, status.Errorf(codes.Internal, "failed to get current user") } - if memo.CreatorID != user.ID { + // Only the creator or admin can update the memo. + if memo.CreatorID != user.ID && !isSuperUser(user) { return nil, status.Errorf(codes.PermissionDenied, "permission denied") } @@ -1167,3 +1169,7 @@ func substring(s string, length int) string { return s[:byteIndex] } + +func isSuperUser(user *store.User) bool { + return user.Role == store.RoleAdmin || user.Role == store.RoleHost +} diff --git a/web/src/components/MemoView.tsx b/web/src/components/MemoView.tsx index a81576fa..5c0a8a95 100644 --- a/web/src/components/MemoView.tsx +++ b/web/src/components/MemoView.tsx @@ -8,6 +8,7 @@ import useNavigateTo from "@/hooks/useNavigateTo"; import { useUserStore, useWorkspaceSettingStore } from "@/store/v1"; import { MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service"; import { Memo, Visibility } from "@/types/proto/api/v1/memo_service"; +import { User_Role } from "@/types/proto/api/v1/user_service"; import { WorkspaceMemoRelatedSetting } from "@/types/proto/api/v1/workspace_setting_service"; import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting"; import { useTranslate } from "@/utils/i18n"; @@ -53,7 +54,7 @@ const MemoView: React.FC = (props: Props) => { (relation) => relation.type === MemoRelation_Type.COMMENT && relation.relatedMemo === memo.name, ).length; const relativeTimeFormat = Date.now() - memo.displayTime!.getTime() > 1000 * 60 * 60 * 24 ? "datetime" : "auto"; - const readonly = memo.creator !== user?.name; + const readonly = memo.creator !== user?.name && user.role === User_Role.USER; const isInMemoDetailPage = location.pathname.startsWith(`/m/${memo.uid}`); // Initial related data: creator.