From 341358887e73e58c2a40c17d994912c9b4411462 Mon Sep 17 00:00:00 2001 From: dafengzhen Date: Sun, 17 Mar 2024 18:31:55 +0800 Subject: [PATCH] add permission checks for backend related buttons --- .../service/user/impl/UserServiceImpl.java | 83 ++++++++++--------- .../db/migration/V1_5__init_action.sql | 7 +- .../db/migration/V1_8__init_role_action.sql | 6 +- .../[locale]/admin/actions/[id]/delete.tsx | 8 +- .../admin/actions/[id]/update-roles.tsx | 10 ++- .../[locale]/admin/actions/[id]/update.tsx | 7 ++ web/app/[locale]/admin/actions/create.tsx | 7 ++ web/app/[locale]/admin/admin.tsx | 6 +- .../admin/comments/posts/[id]/page.tsx | 76 ++++++++++------- .../comments/posts/[id]/update-state.tsx | 7 ++ .../[locale]/admin/configs/jwt/jwt-config.tsx | 10 ++- .../admin/configs/point/point-config.tsx | 10 ++- web/app/[locale]/admin/menus/[id]/delete.tsx | 8 +- .../admin/menus/[id]/update-roles.tsx | 10 ++- web/app/[locale]/admin/menus/[id]/update.tsx | 8 +- web/app/[locale]/admin/menus/create.tsx | 8 +- web/app/[locale]/admin/messages/create.tsx | 10 ++- .../admin/permissions/[id]/delete.tsx | 10 ++- .../admin/permissions/[id]/update-roles.tsx | 10 ++- .../admin/permissions/[id]/update.tsx | 10 ++- web/app/[locale]/admin/permissions/create.tsx | 8 +- .../point-permission-rules.tsx | 42 ++++++---- .../admin/points/rules/point-rules.tsx | 42 ++++++---- web/app/[locale]/admin/posts/[id]/delete.tsx | 8 +- .../admin/posts/[id]/update-section.tsx | 10 ++- .../admin/posts/[id]/update-states.tsx | 10 ++- .../[locale]/admin/posts/[id]/update-tags.tsx | 10 ++- .../posts/review-queues/approved/approved.tsx | 7 ++ .../not-approved/not-approved.tsx | 7 ++ .../posts/review-queues/receive/receive.tsx | 7 ++ .../posts/review-queues/return/return.tsx | 7 ++ web/app/[locale]/admin/providers.tsx | 2 + web/app/[locale]/admin/roles/[id]/delete.tsx | 8 +- .../admin/roles/[id]/update-permissions.tsx | 10 ++- web/app/[locale]/admin/roles/[id]/update.tsx | 8 +- web/app/[locale]/admin/roles/create.tsx | 8 +- .../admin/section-groups/[id]/delete.tsx | 10 ++- .../section-groups/[id]/update-sections.tsx | 11 ++- .../admin/section-groups/[id]/update.tsx | 10 ++- .../[locale]/admin/section-groups/create.tsx | 8 +- .../[locale]/admin/sections/[id]/delete.tsx | 8 +- .../admin/sections/[id]/update-admins.tsx | 10 ++- .../admin/sections/[id]/update-states.tsx | 10 ++- .../admin/sections/[id]/update-tag-groups.tsx | 10 ++- .../admin/sections/[id]/update-tags.tsx | 10 ++- .../[locale]/admin/sections/[id]/update.tsx | 8 +- web/app/[locale]/admin/sections/create.tsx | 10 ++- .../[locale]/admin/submenus/[id]/delete.tsx | 8 +- .../admin/submenus/[id]/update-roles.tsx | 10 ++- .../[locale]/admin/submenus/[id]/update.tsx | 8 +- web/app/[locale]/admin/submenus/create.tsx | 8 +- .../[locale]/admin/tag-groups/[id]/delete.tsx | 10 ++- .../admin/tag-groups/[id]/update-tags.tsx | 10 ++- .../[locale]/admin/tag-groups/[id]/update.tsx | 10 ++- web/app/[locale]/admin/tag-groups/create.tsx | 8 +- web/app/[locale]/admin/tags/[id]/delete.tsx | 8 +- web/app/[locale]/admin/tags/[id]/update.tsx | 8 +- web/app/[locale]/admin/tags/create.tsx | 8 +- web/app/[locale]/admin/users/[id]/delete.tsx | 8 +- .../admin/users/[id]/update-roles.tsx | 10 ++- .../admin/users/[id]/update-states.tsx | 10 ++- web/app/[locale]/constants/index.ts | 4 +- .../hooks/useMenuActionPermission.tsx | 69 +++++++++++++++ web/app/[locale]/posts/[id]/navbar.tsx | 9 +- web/messages/en.json | 4 +- web/messages/zh.json | 4 +- 66 files changed, 664 insertions(+), 160 deletions(-) create mode 100644 web/app/[locale]/hooks/useMenuActionPermission.tsx diff --git a/src/main/java/com/youdeyiwu/service/user/impl/UserServiceImpl.java b/src/main/java/com/youdeyiwu/service/user/impl/UserServiceImpl.java index d8d5e012..8fe3af24 100644 --- a/src/main/java/com/youdeyiwu/service/user/impl/UserServiceImpl.java +++ b/src/main/java/com/youdeyiwu/service/user/impl/UserServiceImpl.java @@ -29,6 +29,7 @@ import com.youdeyiwu.model.dto.user.UsersCountByDateDto; import com.youdeyiwu.model.entity.forum.PostEntity; import com.youdeyiwu.model.entity.user.ActionEntity; +import com.youdeyiwu.model.entity.user.MenuEntity; import com.youdeyiwu.model.entity.user.SubmenuEntity; import com.youdeyiwu.model.entity.user.UserEntity; import com.youdeyiwu.model.vo.PageVo; @@ -592,48 +593,50 @@ private List getAuthenticatedUserMenus() { .filter(roleEntity -> !roleEntity.getMenus().isEmpty()) .flatMap(roleEntity -> roleEntity.getMenus() .stream() + .sorted( + Comparator.comparing(MenuEntity::getSort) + .thenComparing(MenuEntity::getId).reversed() + ) .map(menuEntity -> { MenuEntityVo vo = menuMapper.entityToVo(menuEntity); - if (menuEntity.getSubmenus().isEmpty()) { - vo.setActions( - menuEntity.getActions() - .stream() - .filter(actionEntity -> actionEntity.getRoles().contains(roleEntity)) - .sorted( - Comparator.comparing(ActionEntity::getSort) - .thenComparing(ActionEntity::getId).reversed() - ) - .map(actionMapper::entityToVo) - .collect(Collectors.toCollection(LinkedHashSet::new)) - ); - vo.setSubmenus(new HashSet<>()); - } else { - Set submenuEntityVos = menuEntity.getSubmenus() - .stream() - .filter(submenuEntity -> submenuEntity.getRoles().contains(roleEntity)) - .sorted( - Comparator.comparing(SubmenuEntity::getSort) - .thenComparing(SubmenuEntity::getId).reversed() - ) - .map(submenuEntity -> { - SubmenuEntityVo submenuEntityVo = submenuMapper.entityToVo(submenuEntity); - submenuEntityVo.setActions( - submenuEntity.getActions() - .stream() - .filter(actionEntity -> actionEntity.getRoles().contains(roleEntity)) - .sorted( - Comparator.comparing(ActionEntity::getSort) - .thenComparing(ActionEntity::getId).reversed() - ) - .map(actionMapper::entityToVo) - .collect(Collectors.toCollection(LinkedHashSet::new)) - ); - return submenuEntityVo; - }) - .collect(Collectors.toCollection(LinkedHashSet::new)); - vo.setActions(new HashSet<>()); - vo.setSubmenus(submenuEntityVos); - } + vo.setActions( + menuEntity.getActions() + .stream() + .filter(actionEntity -> actionEntity.getRoles().contains(roleEntity)) + .sorted( + Comparator.comparing(ActionEntity::getSort) + .thenComparing(ActionEntity::getId).reversed() + ) + .map(actionMapper::entityToVo) + .collect(Collectors.toCollection(LinkedHashSet::new)) + ); + + vo.setSubmenus( + menuEntity.getSubmenus() + .stream() + .filter(submenuEntity -> submenuEntity.getRoles().contains(roleEntity)) + .sorted( + Comparator.comparing(SubmenuEntity::getSort) + .thenComparing(SubmenuEntity::getId).reversed() + ) + .map(submenuEntity -> { + SubmenuEntityVo submenuEntityVo = submenuMapper.entityToVo(submenuEntity); + submenuEntityVo.setActions( + submenuEntity.getActions() + .stream() + .filter(actionEntity -> actionEntity.getRoles().contains(roleEntity)) + .sorted( + Comparator.comparing(ActionEntity::getSort) + .thenComparing(ActionEntity::getId).reversed() + ) + .map(actionMapper::entityToVo) + .collect(Collectors.toCollection(LinkedHashSet::new)) + ); + return submenuEntityVo; + }) + .collect(Collectors.toCollection(LinkedHashSet::new)) + ); + return vo; }) ) diff --git a/src/main/resources/db/migration/V1_5__init_action.sql b/src/main/resources/db/migration/V1_5__init_action.sql index 04cafa55..01f85a06 100644 --- a/src/main/resources/db/migration/V1_5__init_action.sql +++ b/src/main/resources/db/migration/V1_5__init_action.sql @@ -51,4 +51,9 @@ VALUES (1, null, now(), false, null, now(), 0, 'Section Create', 'Sections#Creat (50, null, now(), false, null, now(), 0, 'Actions Update Roles', 'Actions#Update Roles', 0, 17, null), (51, null, now(), false, null, now(), 0, 'Actions Delete', 'Actions#Delete', 0, 17, null), (52, null, now(), false, null, now(), 0, 'JwtConfigs Update', 'JwtConfigs#Update', 0, 18, null), - (53, null, now(), false, null, now(), 0, 'PointConfigs Update', 'PointConfigs#Update', 0, 18, null); + (53, null, now(), false, null, now(), 0, 'PointConfigs Update', 'PointConfigs#Update', 0, 18, null), + (54, null, now(), false, null, now(), 0, 'Post Delete', 'Posts#Delete', 0, 6, null), + (55, null, now(), false, null, now(), 0, 'Section Update', 'Sections#Delete', 0, 2, null), + (56, null, now(), false, null, now(), 0, 'Section Groups Delete', 'Section Groups#Delete', 0, 3, null), + (57, null, now(), false, null, now(), 0, 'Comments Update State', 'Comments#Update State', 0, 8, null); + diff --git a/src/main/resources/db/migration/V1_8__init_role_action.sql b/src/main/resources/db/migration/V1_8__init_role_action.sql index 6bba3e38..b89012f3 100644 --- a/src/main/resources/db/migration/V1_8__init_role_action.sql +++ b/src/main/resources/db/migration/V1_8__init_role_action.sql @@ -51,4 +51,8 @@ VALUES (1, 1), (50, 1), (51, 1), (52, 1), - (53, 1); + (53, 1), + (54, 1), + (55, 1), + (56, 1), + (57, 1); diff --git a/web/app/[locale]/admin/actions/[id]/delete.tsx b/web/app/[locale]/admin/actions/[id]/delete.tsx index 13169583..9af86c22 100644 --- a/web/app/[locale]/admin/actions/[id]/delete.tsx +++ b/web/app/[locale]/admin/actions/[id]/delete.tsx @@ -7,9 +7,14 @@ import { GlobalContext } from '@/app/[locale]/contexts'; import RefreshAction from '@/app/[locale]/actions/refresh-action'; import type { IAction } from '@/app/[locale]/interfaces/menus'; import DeleteActionAction from '@/app/[locale]/actions/actions/delete-action-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ action }: { action: IAction }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/actions', + 'Actions#Delete', + ); const deleteActionActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -79,12 +84,13 @@ export default function Delete({ action }: { action: IAction }) {
+
diff --git a/web/app/[locale]/admin/actions/[id]/update-roles.tsx b/web/app/[locale]/admin/actions/[id]/update-roles.tsx index 13369e68..eb493059 100644 --- a/web/app/[locale]/admin/actions/[id]/update-roles.tsx +++ b/web/app/[locale]/admin/actions/[id]/update-roles.tsx @@ -10,12 +10,17 @@ import UpdateRolesActionAction, { } from '@/app/[locale]/actions/actions/update-roles-action-action'; import { nonNum } from '@/app/[locale]/common/client'; import SimpleDynamicInput from '@/app/[locale]/common/simple-dynamic-input'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateRoles({ action }: { action: IAction }) { const { toast } = useContext(GlobalContext); const [roles, setRoles] = useState( action.roles.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/actions', + 'Actions#Update Roles', + ); const updateRolesActionActionMutation = useMutation({ mutationFn: async (variables: { @@ -81,7 +86,9 @@ export default function UpdateRoles({ action }: { action: IAction }) {
+
diff --git a/web/app/[locale]/admin/actions/[id]/update.tsx b/web/app/[locale]/admin/actions/[id]/update.tsx index fa45d68c..bc10a9df 100644 --- a/web/app/[locale]/admin/actions/[id]/update.tsx +++ b/web/app/[locale]/admin/actions/[id]/update.tsx @@ -10,6 +10,7 @@ import UpdateActionAction, { type IUpdateActionActionVariables, } from '@/app/[locale]/actions/actions/update-action-action'; import { ACTION_PAGES_DATA } from '@/app/[locale]/constants'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; const ACTION_PAGES = Object.keys(ACTION_PAGES_DATA); @@ -32,6 +33,10 @@ export default function Update({ action }: { action: IAction }) { menu: (action.menu?.id ?? '') + '' ?? '', submenu: (action.submenu?.id ?? '') + '' ?? '', }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/actions', + 'Actions#Update', + ); const updateActionActionMutation = useMutation({ mutationFn: async (variables: { @@ -230,6 +235,7 @@ export default function Update({ action }: { action: IAction }) {
diff --git a/web/app/[locale]/admin/actions/create.tsx b/web/app/[locale]/admin/actions/create.tsx index c1e8627e..dde4862e 100644 --- a/web/app/[locale]/admin/actions/create.tsx +++ b/web/app/[locale]/admin/actions/create.tsx @@ -9,6 +9,7 @@ import CreateActionAction, { type ICreateActionActionVariables, } from '@/app/[locale]/actions/actions/create-action-action'; import { ACTION_PAGES_DATA } from '@/app/[locale]/constants'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; const ACTION_PAGES = Object.keys(ACTION_PAGES_DATA); @@ -27,6 +28,10 @@ export default function Create() { alias: '', sort: 0, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/actions', + 'Actions#Create', + ); const createActionActionMutation = useMutation({ mutationFn: async (variables: ICreateActionActionVariables) => { @@ -182,6 +187,7 @@ export default function Create() {
diff --git a/web/app/[locale]/admin/admin.tsx b/web/app/[locale]/admin/admin.tsx index 6d5ab3bf..6bd407a6 100644 --- a/web/app/[locale]/admin/admin.tsx +++ b/web/app/[locale]/admin/admin.tsx @@ -1,9 +1,10 @@ 'use client'; -import { TUsersCountByDate } from '@/app/[locale]/interfaces/users'; +import type { TUsersCountByDate } from '@/app/[locale]/interfaces/users'; import { useEffect, useRef } from 'react'; import Chart from '@/app/[locale]/common/chart'; import type { ChartData, ChartOptions } from 'chart.js'; +import { useTranslations } from 'next-intl'; export default function Admin({ usersCountByDate, @@ -12,6 +13,7 @@ export default function Admin({ }) { const canvas = useRef(null); const chartRef = useRef>(); + const t = useTranslations(); useEffect(() => { const current = canvas.current; @@ -76,7 +78,7 @@ export default function Admin({
- Statistics of User Registrations in the Past 15 Days + {t('common.userRegistrationStatisticsForTheLast15Days')}
diff --git a/web/app/[locale]/admin/comments/posts/[id]/page.tsx b/web/app/[locale]/admin/comments/posts/[id]/page.tsx index 195dea91..edfe4a66 100644 --- a/web/app/[locale]/admin/comments/posts/[id]/page.tsx +++ b/web/app/[locale]/admin/comments/posts/[id]/page.tsx @@ -8,11 +8,18 @@ import UpdateState from '@/app/[locale]/admin/comments/posts/[id]/update-state'; import QueryCommentAction from '@/app/[locale]/actions/comments/query-comment-action'; import QueryReplyAction from '@/app/[locale]/actions/replies/query-reply-action'; import ErrorPage from '@/app/[locale]/common/error-page'; +import queryString from 'query-string'; export const metadata: Metadata = { title: 'Update Comment', }; +export interface ISearchParamsAdminPostCommentPage { + type?: 'state'; + cid?: string; + rid?: string; +} + export default async function Page({ params, searchParams, @@ -20,53 +27,48 @@ export default async function Page({ params: { id: string; }; - searchParams: { - type?: 'state'; - cid?: string; - rid?: string; - }; + searchParams: ISearchParamsAdminPostCommentPage; }) { const id = params.id; if (!isNum(id)) { notFound(); } - if (searchParams.type === 'state') { - const cid = searchParams.cid; - const rid = searchParams.rid; + const _searchParams = parseSearchParams(searchParams); + if (_searchParams.type === 'state') { + const cid = _searchParams.cid; + const rid = _searchParams.rid; - if (!cid && !rid) { - notFound(); - } - if (cid && !isNum(cid)) { - notFound(); - } - if (rid && !isNum(rid)) { + if (typeof cid !== 'number' && typeof rid !== 'number') { notFound(); } - const responses = await Promise.all([ - QueryCommentAction({ id: cid as string }), - QueryReplyAction({ - id: rid!, - }), - ]); - const commentResponse = responses[0]; - const replyResponse = responses[1]; + let commentResponse; + let replyResponse; - if (commentResponse.isError) { - return ; + if (typeof cid === 'number') { + commentResponse = await QueryCommentAction({ id: cid }); + if (commentResponse.isError) { + return ; + } } - if (replyResponse.isError) { - return ; + if (typeof rid === 'number') { + replyResponse = await QueryReplyAction({ id: rid }); + if (replyResponse.isError) { + return ; + } } return ( ); } @@ -93,3 +95,17 @@ export default async function Page({ /> ); } + +const parseSearchParams = (searchParams: ISearchParamsAdminPostCommentPage) => { + const { type, cid, rid } = searchParams; + const params = { + type, + cid, + rid, + }; + + const parse = queryString.parse(queryString.stringify(params), { + parseNumbers: true, + }) as Record; + return { ...parse }; +}; diff --git a/web/app/[locale]/admin/comments/posts/[id]/update-state.tsx b/web/app/[locale]/admin/comments/posts/[id]/update-state.tsx index 7e67674c..da5a114d 100644 --- a/web/app/[locale]/admin/comments/posts/[id]/update-state.tsx +++ b/web/app/[locale]/admin/comments/posts/[id]/update-state.tsx @@ -20,6 +20,7 @@ import UpdateStateCommentAction, { import UpdateStateReplyAction, { type IUpdateStateReplyActionVariables, } from '@/app/[locale]/actions/replies/update-state-reply-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateStates({ details, @@ -38,6 +39,10 @@ export default function UpdateStates({ reason: '', reviewState: details.reviewState ?? 'APPROVED', }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/comments', + 'Comments#Update State', + ); const updateStateCommentActionMutation = useMutation({ mutationFn: async (variables: { @@ -198,6 +203,7 @@ export default function UpdateStates({
diff --git a/web/app/[locale]/admin/configs/jwt/jwt-config.tsx b/web/app/[locale]/admin/configs/jwt/jwt-config.tsx index 7793a0e8..2485b9f9 100644 --- a/web/app/[locale]/admin/configs/jwt/jwt-config.tsx +++ b/web/app/[locale]/admin/configs/jwt/jwt-config.tsx @@ -10,6 +10,7 @@ import UpdateJwtConfigAction, { type IUpdateJwtActionVariables, } from '@/app/[locale]/actions/configs/jwt/update-jwt-config-action'; import type { IJwtConfig } from '@/app/[locale]/interfaces/configs'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function JwtConfig({ config }: { config: IJwtConfig }) { const { toast } = useContext(GlobalContext); @@ -18,6 +19,10 @@ export default function JwtConfig({ config }: { config: IJwtConfig }) { }>({ secret: config.secret ?? '', }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/configs', + 'JwtConfigs#Update', + ); const generateRandomSecretJwtConfigActionMutation = useMutation({ mutationFn: async () => { @@ -138,7 +143,9 @@ export default function JwtConfig({ config }: { config: IJwtConfig }) {
+
diff --git a/web/app/[locale]/admin/configs/point/point-config.tsx b/web/app/[locale]/admin/configs/point/point-config.tsx index 3bea9e0f..0bd042d0 100644 --- a/web/app/[locale]/admin/configs/point/point-config.tsx +++ b/web/app/[locale]/admin/configs/point/point-config.tsx @@ -9,6 +9,7 @@ import type { IPointConfig } from '@/app/[locale]/interfaces/configs'; import UpdatePointConfigAction, { type IUpdatePointActionVariables, } from '@/app/[locale]/actions/configs/point/update-point-config-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function PointConfig({ config }: { config: IPointConfig }) { const { toast } = useContext(GlobalContext); @@ -19,6 +20,10 @@ export default function PointConfig({ config }: { config: IPointConfig }) { enable: config.enable ?? false, initPoints: config.initPoints ?? 100, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/configs', + 'PointConfigs#Update', + ); const updatePointConfigActionMutation = useMutation({ mutationFn: async (variables: IUpdatePointActionVariables) => { @@ -109,7 +114,9 @@ export default function PointConfig({ config }: { config: IPointConfig }) {
+
diff --git a/web/app/[locale]/admin/menus/[id]/delete.tsx b/web/app/[locale]/admin/menus/[id]/delete.tsx index 09fcec4e..1c9b6d85 100644 --- a/web/app/[locale]/admin/menus/[id]/delete.tsx +++ b/web/app/[locale]/admin/menus/[id]/delete.tsx @@ -7,9 +7,14 @@ import { GlobalContext } from '@/app/[locale]/contexts'; import RefreshAction from '@/app/[locale]/actions/refresh-action'; import type { IMenu } from '@/app/[locale]/interfaces/menus'; import DeleteMenuAction from '@/app/[locale]/actions/menus/delete-menu-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ menu }: { menu: IMenu }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/menus', + 'Menus#Delete', + ); const deleteMenuActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -75,12 +80,13 @@ export default function Delete({ menu }: { menu: IMenu }) {
+
diff --git a/web/app/[locale]/admin/menus/[id]/update-roles.tsx b/web/app/[locale]/admin/menus/[id]/update-roles.tsx index 7089ec45..09442e57 100644 --- a/web/app/[locale]/admin/menus/[id]/update-roles.tsx +++ b/web/app/[locale]/admin/menus/[id]/update-roles.tsx @@ -10,12 +10,17 @@ import type { IMenu } from '@/app/[locale]/interfaces/menus'; import UpdateRolesMenuAction, { type IUpdateRolesMenuActionVariables, } from '@/app/[locale]/actions/menus/update-roles-menu-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateRoles({ menu }: { menu: IMenu }) { const { toast } = useContext(GlobalContext); const [roles, setRoles] = useState( menu.roles.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/menus', + 'Menus#Update Roles', + ); const updateRolesMenuActionMutation = useMutation({ mutationFn: async (variables: { @@ -81,7 +86,9 @@ export default function UpdateRoles({ menu }: { menu: IMenu }) {
+
diff --git a/web/app/[locale]/admin/menus/[id]/update.tsx b/web/app/[locale]/admin/menus/[id]/update.tsx index eb059736..958e917f 100644 --- a/web/app/[locale]/admin/menus/[id]/update.tsx +++ b/web/app/[locale]/admin/menus/[id]/update.tsx @@ -10,6 +10,7 @@ import UpdateMenuAction, { type IUpdateMenuActionVariables, } from '@/app/[locale]/actions/menus/update-menu-action'; import SimpleDynamicInput from '@/app/[locale]/common/simple-dynamic-input'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Update({ menu }: { menu: IMenu }) { const { toast } = useContext(GlobalContext); @@ -28,6 +29,10 @@ export default function Update({ menu }: { menu: IMenu }) { const [actions, setActions] = useState( menu.actions.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/menus', + 'Menus#Update', + ); const updateMenuActionMutation = useMutation({ mutationFn: async (variables: { @@ -203,12 +208,13 @@ export default function Update({ menu }: { menu: IMenu }) {
+
diff --git a/web/app/[locale]/admin/menus/create.tsx b/web/app/[locale]/admin/menus/create.tsx index 1936bb56..7677c1a6 100644 --- a/web/app/[locale]/admin/menus/create.tsx +++ b/web/app/[locale]/admin/menus/create.tsx @@ -8,6 +8,7 @@ import { trimObjectStrings } from '@/app/[locale]/common/client'; import CreateMenuAction, { type ICreateMenuActionVariables, } from '@/app/[locale]/actions/menus/create-menu-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Create() { const { toast } = useContext(GlobalContext); @@ -20,6 +21,10 @@ export default function Create() { link: '', sort: 0, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/menus', + 'Menus#Create', + ); const createMenuActionMutation = useMutation({ mutationFn: async (variables: ICreateMenuActionVariables) => { @@ -141,12 +146,13 @@ export default function Create() {
+
diff --git a/web/app/[locale]/admin/messages/create.tsx b/web/app/[locale]/admin/messages/create.tsx index 9d0c0479..070b46f4 100644 --- a/web/app/[locale]/admin/messages/create.tsx +++ b/web/app/[locale]/admin/messages/create.tsx @@ -12,11 +12,12 @@ import { import CreateGlobalMessageAction, { type ICreateGlobalMessageActionVariables, } from '@/app/[locale]/actions/messages/create-global-message-action'; -import { TMessageRange } from '@/app/[locale]/interfaces/messages'; +import type { TMessageRange } from '@/app/[locale]/interfaces/messages'; import Link from 'next/link'; import CreateMessageAction, { type ICreateMessageActionVariables, } from '@/app/[locale]/actions/messages/create-message-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Create() { const { toast } = useContext(GlobalContext); @@ -39,6 +40,10 @@ export default function Create() { messageRange: 'ALL_USER', receiver: '', }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/messages', + 'Messages#Create', + ); const createGlobalMessageActionMutation = useMutation({ mutationFn: async (variables: ICreateGlobalMessageActionVariables) => { @@ -364,6 +369,7 @@ export default function Create() {
diff --git a/web/app/[locale]/admin/permissions/[id]/delete.tsx b/web/app/[locale]/admin/permissions/[id]/delete.tsx index f1655785..b0b6567e 100644 --- a/web/app/[locale]/admin/permissions/[id]/delete.tsx +++ b/web/app/[locale]/admin/permissions/[id]/delete.tsx @@ -7,9 +7,14 @@ import { GlobalContext } from '@/app/[locale]/contexts'; import RefreshAction from '@/app/[locale]/actions/refresh-action'; import type { IPermission } from '@/app/[locale]/interfaces/permissions'; import DeletePermissionAction from '@/app/[locale]/actions/permissions/delete-permission-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ permission }: { permission: IPermission }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/permissions', + 'Permissions#Delete', + ); const deletePermissionActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -75,12 +80,15 @@ export default function Delete({ permission }: { permission: IPermission }) {
+
diff --git a/web/app/[locale]/admin/permissions/[id]/update-roles.tsx b/web/app/[locale]/admin/permissions/[id]/update-roles.tsx index 35500967..95864673 100644 --- a/web/app/[locale]/admin/permissions/[id]/update-roles.tsx +++ b/web/app/[locale]/admin/permissions/[id]/update-roles.tsx @@ -10,6 +10,7 @@ import type { IPermission } from '@/app/[locale]/interfaces/permissions'; import UpdateRolesPermissionAction, { type IUpdateRolesPermissionActionVariables, } from '@/app/[locale]/actions/permissions/update-roles-permission-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateRoles({ permission, @@ -20,6 +21,10 @@ export default function UpdateRoles({ const [roles, setRoles] = useState( permission.roles.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/permissions', + 'Permissions#Update Roles', + ); const updateRolesPermissionActionMutation = useMutation({ mutationFn: async (variables: { @@ -84,7 +89,9 @@ export default function UpdateRoles({
+
diff --git a/web/app/[locale]/admin/permissions/[id]/update.tsx b/web/app/[locale]/admin/permissions/[id]/update.tsx index e782fdb6..f10466e2 100644 --- a/web/app/[locale]/admin/permissions/[id]/update.tsx +++ b/web/app/[locale]/admin/permissions/[id]/update.tsx @@ -14,6 +14,7 @@ import UpdatePermissionAction, { type IUpdatePermissionActionVariables, } from '@/app/[locale]/actions/permissions/update-permission-action'; import SimpleDynamicInput from '@/app/[locale]/common/simple-dynamic-input'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Update({ permission }: { permission: IPermission }) { const { toast } = useContext(GlobalContext); @@ -39,6 +40,10 @@ export default function Update({ permission }: { permission: IPermission }) { const [matchers, setMatchers] = useState( permission.matchers.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/permissions', + 'Permissions#Update', + ); const updatePermissionActionMutation = useMutation({ mutationFn: async (variables: { @@ -273,7 +278,9 @@ export default function Update({ permission }: { permission: IPermission }) {
+
diff --git a/web/app/[locale]/admin/permissions/create.tsx b/web/app/[locale]/admin/permissions/create.tsx index 08365420..b3f962ab 100644 --- a/web/app/[locale]/admin/permissions/create.tsx +++ b/web/app/[locale]/admin/permissions/create.tsx @@ -13,6 +13,7 @@ import CreatePermissionAction, { type ICreatePermissionActionVariables, } from '@/app/[locale]/actions/permissions/create-permission-action'; import SimpleDynamicInput from '@/app/[locale]/common/simple-dynamic-input'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Create() { const { toast } = useContext(GlobalContext); @@ -36,6 +37,10 @@ export default function Create() { matchers: [], }); const [matchers, setMatchers] = useState([]); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/permissions', + 'Permissions#Create', + ); const createPermissionActionMutation = useMutation({ mutationFn: async (variables: ICreatePermissionActionVariables) => { @@ -274,7 +279,7 @@ export default function Create() {
diff --git a/web/app/[locale]/admin/points/permission-rules/point-permission-rules.tsx b/web/app/[locale]/admin/points/permission-rules/point-permission-rules.tsx index 0e9f6e27..9e44fbd3 100644 --- a/web/app/[locale]/admin/points/permission-rules/point-permission-rules.tsx +++ b/web/app/[locale]/admin/points/permission-rules/point-permission-rules.tsx @@ -13,6 +13,7 @@ import { useMutation } from '@tanstack/react-query'; import SavePermissionRulesPointsAction, { type ISavePermissionRulesPointsActionVariables, } from '@/app/[locale]/actions/points/permission-rules/save-permission-rules-points-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; const tips = { CREATE_POST: 'permission to create a new post', @@ -51,6 +52,10 @@ export default function PointPermissionRules({ ); const [isUpdate, setIsUpdate] = useState(false); const [saving, setSaving] = useState(false); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/points/permission-rules', + 'Point Permissions#Update', + ); const savePermissionRulesPointsActionMutation = useMutation({ mutationFn: async ( @@ -106,27 +111,32 @@ export default function PointPermissionRules({
- - - {isUpdate && ( +
+
+ + {isUpdate && ( +
+ + +
)}
diff --git a/web/app/[locale]/admin/points/rules/point-rules.tsx b/web/app/[locale]/admin/points/rules/point-rules.tsx index d51f4785..e2a9e945 100644 --- a/web/app/[locale]/admin/points/rules/point-rules.tsx +++ b/web/app/[locale]/admin/points/rules/point-rules.tsx @@ -13,6 +13,7 @@ import { useMutation } from '@tanstack/react-query'; import SaveRulesPointsAction, { type ISaveRulesPointsActionVariables, } from '@/app/[locale]/actions/points/rules/save-rules-points-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; const tips = { LIKE_POST: 'earning points for liking a post', @@ -52,6 +53,10 @@ export default function PointRules({ data }: { data: IPointRule[] }) { ); const [isUpdate, setIsUpdate] = useState(false); const [saving, setSaving] = useState(false); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/points/rules', + 'Point Rules#Update', + ); const saveRulesPointsActionMutation = useMutation({ mutationFn: async (variables: ISaveRulesPointsActionVariables) => { @@ -105,27 +110,32 @@ export default function PointRules({ data }: { data: IPointRule[] }) {
- - - {isUpdate && ( +
+
+ + {isUpdate && ( +
+ + +
)}
diff --git a/web/app/[locale]/admin/posts/[id]/delete.tsx b/web/app/[locale]/admin/posts/[id]/delete.tsx index 50193916..a35d54c4 100644 --- a/web/app/[locale]/admin/posts/[id]/delete.tsx +++ b/web/app/[locale]/admin/posts/[id]/delete.tsx @@ -8,9 +8,14 @@ import Link from 'next/link'; import RefreshAction from '@/app/[locale]/actions/refresh-action'; import type { IPost } from '@/app/[locale]/interfaces/posts'; import DeletePostAction from '@/app/[locale]/actions/posts/delete-post-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ post }: { post: IPost }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/posts', + 'Posts#Delete', + ); const deletePostActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -79,12 +84,13 @@ export default function Delete({ post }: { post: IPost }) {
+
diff --git a/web/app/[locale]/admin/posts/[id]/update-section.tsx b/web/app/[locale]/admin/posts/[id]/update-section.tsx index 4303f80e..b6904fe2 100644 --- a/web/app/[locale]/admin/posts/[id]/update-section.tsx +++ b/web/app/[locale]/admin/posts/[id]/update-section.tsx @@ -10,6 +10,7 @@ import UpdateSectionPostAction, { type IUpdateSectionPostActionVariables, } from '@/app/[locale]/actions/posts/update-section-post-action'; import { isNum } from '@/app/[locale]/common/tool'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateSection({ post, @@ -22,6 +23,10 @@ export default function UpdateSection({ const [sectionId, setSectionId] = useState( (post.section?.id ?? 'none') + '', ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/posts', + 'Posts#Update Section', + ); const updateSectionPostActionMutation = useMutation({ mutationFn: async (variables: { @@ -91,7 +96,9 @@ export default function UpdateSection({
+
diff --git a/web/app/[locale]/admin/posts/[id]/update-states.tsx b/web/app/[locale]/admin/posts/[id]/update-states.tsx index fce81485..4d693a9c 100644 --- a/web/app/[locale]/admin/posts/[id]/update-states.tsx +++ b/web/app/[locale]/admin/posts/[id]/update-states.tsx @@ -20,6 +20,7 @@ import type { import UpdateStatesPostAction, { type IUpdateStatesPostActionVariables, } from '@/app/[locale]/actions/posts/update-states-post-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; interface IState { id: number | string; @@ -61,6 +62,10 @@ export default function UpdateStates({ post }: { post: IPost }) { const [blocks, setBlocks] = useState( post.blocks.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/posts', + 'Posts#Update States', + ); const updateStatesPostActionMutation = useMutation({ mutationFn: async (variables: { @@ -381,7 +386,9 @@ export default function UpdateStates({ post }: { post: IPost }) {
+
diff --git a/web/app/[locale]/admin/posts/[id]/update-tags.tsx b/web/app/[locale]/admin/posts/[id]/update-tags.tsx index 833a5ebb..07b3083a 100644 --- a/web/app/[locale]/admin/posts/[id]/update-tags.tsx +++ b/web/app/[locale]/admin/posts/[id]/update-tags.tsx @@ -10,12 +10,17 @@ import type { IPost } from '@/app/[locale]/interfaces/posts'; import UpdateTagsPostAction, { type IUpdateTagsPostActionVariables, } from '@/app/[locale]/actions/posts/update-tags-post-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateTags({ post }: { post: IPost }) { const { toast } = useContext(GlobalContext); const [tags, setTags] = useState( post.tags.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/posts', + 'Posts#Update Tags', + ); const updateTagsPostActionMutation = useMutation({ mutationFn: async (variables: { @@ -81,7 +86,9 @@ export default function UpdateTags({ post }: { post: IPost }) {
+
diff --git a/web/app/[locale]/admin/posts/review-queues/approved/approved.tsx b/web/app/[locale]/admin/posts/review-queues/approved/approved.tsx index a0360325..2a720982 100644 --- a/web/app/[locale]/admin/posts/review-queues/approved/approved.tsx +++ b/web/app/[locale]/admin/posts/review-queues/approved/approved.tsx @@ -8,6 +8,7 @@ import { trimObjectStrings } from '@/app/[locale]/common/client'; import ApprovedPostReviewQueuesAction, { type IApprovedPostReviewQueuesActionVariables, } from '@/app/[locale]/actions/posts/review-queues/approved-post-review-queues-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Approved({ id }: { id: number }) { const { toast } = useContext(GlobalContext); @@ -16,6 +17,10 @@ export default function Approved({ id }: { id: number }) { }>({ reason: '', }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/posts/review-queues', + 'Post Review Queues#Approved', + ); const approvedPostReviewQueuesActionMutation = useMutation({ mutationFn: async (variables: { @@ -88,6 +93,7 @@ export default function Approved({ id }: { id: number }) { + diff --git a/web/app/[locale]/admin/roles/[id]/update-permissions.tsx b/web/app/[locale]/admin/roles/[id]/update-permissions.tsx index e8a30ffb..cb92f5ca 100644 --- a/web/app/[locale]/admin/roles/[id]/update-permissions.tsx +++ b/web/app/[locale]/admin/roles/[id]/update-permissions.tsx @@ -10,12 +10,17 @@ import type { IRole } from '@/app/[locale]/interfaces/roles'; import UpdatePermissionsRoleAction, { type IUpdatePermissionsRoleActionVariables, } from '@/app/[locale]/actions/roles/update-permissions-role-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdatePermissions({ role }: { role: IRole }) { const { toast } = useContext(GlobalContext); const [permissions, setPermissions] = useState( role.permissions.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/roles', + 'Roles#Update Permissions', + ); const updatePermissionsRoleActionMutation = useMutation({ mutationFn: async (variables: { @@ -80,7 +85,9 @@ export default function UpdatePermissions({ role }: { role: IRole }) {
+
diff --git a/web/app/[locale]/admin/roles/[id]/update.tsx b/web/app/[locale]/admin/roles/[id]/update.tsx index e39afa3a..fa9638b6 100644 --- a/web/app/[locale]/admin/roles/[id]/update.tsx +++ b/web/app/[locale]/admin/roles/[id]/update.tsx @@ -9,6 +9,7 @@ import type { IRole } from '@/app/[locale]/interfaces/roles'; import UpdateRoleAction, { type IUpdateRoleActionVariables, } from '@/app/[locale]/actions/roles/update-role-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Update({ role }: { role: IRole }) { const { toast } = useContext(GlobalContext); @@ -23,6 +24,10 @@ export default function Update({ role }: { role: IRole }) { sort: role.sort ?? 0, display: role.display ?? true, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/roles', + 'Roles#Update', + ); const updateRoleActionMutation = useMutation({ mutationFn: async (variables: { @@ -159,12 +164,13 @@ export default function Update({ role }: { role: IRole }) {
+
diff --git a/web/app/[locale]/admin/roles/create.tsx b/web/app/[locale]/admin/roles/create.tsx index 7474742b..f8b7ef17 100644 --- a/web/app/[locale]/admin/roles/create.tsx +++ b/web/app/[locale]/admin/roles/create.tsx @@ -8,6 +8,7 @@ import CreateRoleAction, { type ICreateRoleActionVariables, } from '@/app/[locale]/actions/roles/create-role-action'; import { trimObjectStrings } from '@/app/[locale]/common/client'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Create() { const { toast } = useContext(GlobalContext); @@ -22,6 +23,10 @@ export default function Create() { sort: 0, display: true, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/roles', + 'Roles#Create', + ); const createRoleActionMutation = useMutation({ mutationFn: async (variables: ICreateRoleActionVariables) => { @@ -155,12 +160,13 @@ export default function Create() {
+
diff --git a/web/app/[locale]/admin/section-groups/[id]/delete.tsx b/web/app/[locale]/admin/section-groups/[id]/delete.tsx index be42361f..54451fb5 100644 --- a/web/app/[locale]/admin/section-groups/[id]/delete.tsx +++ b/web/app/[locale]/admin/section-groups/[id]/delete.tsx @@ -7,6 +7,7 @@ import { GlobalContext } from '@/app/[locale]/contexts'; import RefreshAction from '@/app/[locale]/actions/refresh-action'; import type { ISectionGroup } from '@/app/[locale]/interfaces/section-groups'; import DeleteSectionGroupAction from '@/app/[locale]/actions/section-groups/delete-section-group-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ sectionGroup, @@ -14,6 +15,10 @@ export default function Delete({ sectionGroup: ISectionGroup; }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/section-groups', + 'Section Groups#Delete', + ); const deleteSectionGroupActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -79,12 +84,15 @@ export default function Delete({
+
diff --git a/web/app/[locale]/admin/section-groups/[id]/update-sections.tsx b/web/app/[locale]/admin/section-groups/[id]/update-sections.tsx index 23813e77..26e70275 100644 --- a/web/app/[locale]/admin/section-groups/[id]/update-sections.tsx +++ b/web/app/[locale]/admin/section-groups/[id]/update-sections.tsx @@ -10,6 +10,7 @@ import type { ISectionGroup } from '@/app/[locale]/interfaces/section-groups'; import UpdateSectionsSectionGroupAction, { type IUpdateSectionsSectionGroupActionVariables, } from '@/app/[locale]/actions/sections/update-sections-section-group-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateSections({ sectionGroup, @@ -20,6 +21,10 @@ export default function UpdateSections({ const [sections, setSections] = useState( sectionGroup.sections.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/section-groups', + 'Section Groups#Update Sections', + ); const updateSectionsSectionGroupActionMutation = useMutation({ mutationFn: async (variables: { @@ -85,7 +90,10 @@ export default function UpdateSections({
+
diff --git a/web/app/[locale]/admin/section-groups/[id]/update.tsx b/web/app/[locale]/admin/section-groups/[id]/update.tsx index 1f4261fa..f8f1361c 100644 --- a/web/app/[locale]/admin/section-groups/[id]/update.tsx +++ b/web/app/[locale]/admin/section-groups/[id]/update.tsx @@ -9,6 +9,7 @@ import type { ISectionGroup } from '@/app/[locale]/interfaces/section-groups'; import UpdateSectionGroupAction, { type IUpdateSectionGroupActionVariables, } from '@/app/[locale]/actions/section-groups/update-section-group-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Update({ sectionGroup, @@ -23,6 +24,10 @@ export default function Update({ name: sectionGroup.name ?? '', sort: sectionGroup.sort ?? 0, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/section-groups', + 'Section Groups#Update', + ); const updateSectionGroupActionMutation = useMutation({ mutationFn: async (variables: { @@ -122,7 +127,9 @@ export default function Update({
+
diff --git a/web/app/[locale]/admin/section-groups/create.tsx b/web/app/[locale]/admin/section-groups/create.tsx index 43abfbca..dfb59852 100644 --- a/web/app/[locale]/admin/section-groups/create.tsx +++ b/web/app/[locale]/admin/section-groups/create.tsx @@ -5,6 +5,7 @@ import { type ChangeEvent, type FormEvent, useContext, useState } from 'react'; import { GlobalContext } from '@/app/[locale]/contexts'; import { useMutation } from '@tanstack/react-query'; import CreateSectionGroupAction from '@/app/[locale]/actions/section-groups/create-section-group-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Create() { const { toast } = useContext(GlobalContext); @@ -13,6 +14,10 @@ export default function Create() { }>({ name: '', }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/section-groups', + 'Section Groups#Create', + ); const createSectionGroupActionMutation = useMutation({ mutationFn: async (variables: { name: string }) => { @@ -90,7 +95,7 @@ export default function Create() {
diff --git a/web/app/[locale]/admin/sections/[id]/delete.tsx b/web/app/[locale]/admin/sections/[id]/delete.tsx index 48f8cfdb..6d7e208f 100644 --- a/web/app/[locale]/admin/sections/[id]/delete.tsx +++ b/web/app/[locale]/admin/sections/[id]/delete.tsx @@ -8,9 +8,14 @@ import { GlobalContext } from '@/app/[locale]/contexts'; import Link from 'next/link'; import DeleteSectionAction from '@/app/[locale]/actions/sections/delete-section-action'; import RefreshAction from '@/app/[locale]/actions/refresh-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ section }: { section: ISection }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/sections', + 'Sections#Delete', + ); const deleteSectionActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -80,12 +85,13 @@ export default function Delete({ section }: { section: ISection }) {
+
diff --git a/web/app/[locale]/admin/sections/[id]/update-admins.tsx b/web/app/[locale]/admin/sections/[id]/update-admins.tsx index c26b7a95..c9424303 100644 --- a/web/app/[locale]/admin/sections/[id]/update-admins.tsx +++ b/web/app/[locale]/admin/sections/[id]/update-admins.tsx @@ -10,12 +10,17 @@ import UpdateAdminsSectionAction, { type IUpdateAdminsSectionActionVariables, } from '@/app/[locale]/actions/sections/update-admins-section-action'; import { nonNum } from '@/app/[locale]/common/client'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateAdmins({ section }: { section: ISection }) { const { toast } = useContext(GlobalContext); const [admins, setAdmins] = useState( section.admins.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/sections', + 'Sections#Update Admins', + ); const updateAdminsSectionActionMutation = useMutation({ mutationFn: async (variables: { @@ -76,7 +81,9 @@ export default function UpdateAdmins({ section }: { section: ISection }) {
+
diff --git a/web/app/[locale]/admin/sections/[id]/update-states.tsx b/web/app/[locale]/admin/sections/[id]/update-states.tsx index b7e1f766..a9e2ac97 100644 --- a/web/app/[locale]/admin/sections/[id]/update-states.tsx +++ b/web/app/[locale]/admin/sections/[id]/update-states.tsx @@ -17,6 +17,7 @@ import SimpleDynamicInput from '@/app/[locale]/common/simple-dynamic-input'; import UpdateStatesSectionAction, { type IUpdateStatesSectionActionVariables, } from '@/app/[locale]/actions/sections/update-states-section-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; interface IState { id: number | string; @@ -52,6 +53,10 @@ export default function UpdateStates({ section }: { section: ISection }) { const [blocks, setBlocks] = useState( section.blocks.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/sections', + 'Sections#Update States', + ); const updateStatesSectionActionMutation = useMutation({ mutationFn: async (variables: { @@ -235,7 +240,9 @@ export default function UpdateStates({ section }: { section: ISection }) {
+
diff --git a/web/app/[locale]/admin/sections/[id]/update-tag-groups.tsx b/web/app/[locale]/admin/sections/[id]/update-tag-groups.tsx index 8f608a61..5ac5c8ae 100644 --- a/web/app/[locale]/admin/sections/[id]/update-tag-groups.tsx +++ b/web/app/[locale]/admin/sections/[id]/update-tag-groups.tsx @@ -10,12 +10,17 @@ import UpdateTagGroupsSectionAction, { type IUpdateTagGroupsSectionActionVariables, } from '@/app/[locale]/actions/sections/update-tag-groups-section-action'; import { nonNum } from '@/app/[locale]/common/client'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateTagGroups({ section }: { section: ISection }) { const { toast } = useContext(GlobalContext); const [tagGroups, setTagGroups] = useState( section.tagGroups.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/sections', + 'Sections#Update Tag Groups', + ); const updateTagGroupsSectionActionMutation = useMutation({ mutationFn: async (variables: { @@ -77,7 +82,9 @@ export default function UpdateTagGroups({ section }: { section: ISection }) {
+
diff --git a/web/app/[locale]/admin/sections/[id]/update-tags.tsx b/web/app/[locale]/admin/sections/[id]/update-tags.tsx index 6c8b7020..4e26c421 100644 --- a/web/app/[locale]/admin/sections/[id]/update-tags.tsx +++ b/web/app/[locale]/admin/sections/[id]/update-tags.tsx @@ -10,12 +10,17 @@ import { nonNum } from '@/app/[locale]/common/client'; import UpdateTagsSectionAction, { type IUpdateTagsSectionActionVariables, } from '@/app/[locale]/actions/sections/update-tags-section-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateTags({ section }: { section: ISection }) { const { toast } = useContext(GlobalContext); const [tags, setTags] = useState( section.tags.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/sections', + 'Sections#Update Tags', + ); const updateTagsSectionActionMutation = useMutation({ mutationFn: async (variables: { @@ -81,7 +86,9 @@ export default function UpdateTags({ section }: { section: ISection }) {
+
diff --git a/web/app/[locale]/admin/sections/[id]/update.tsx b/web/app/[locale]/admin/sections/[id]/update.tsx index 39e22157..a263895e 100644 --- a/web/app/[locale]/admin/sections/[id]/update.tsx +++ b/web/app/[locale]/admin/sections/[id]/update.tsx @@ -23,6 +23,7 @@ import { setContent, } from '@/app/[locale]/common/editor'; import UploadCover from '@/app/[locale]/admin/sections/[id]/upload-cover'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Update({ section }: { section: ISection }) { const { toast } = useContext(GlobalContext); @@ -42,6 +43,10 @@ export default function Update({ section }: { section: ISection }) { const editorElementRef = useRef(null); const editorRef = useRef(null); const [editorInitializing, setEditorInitializing] = useState(true); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/sections', + 'Sections#Update', + ); const updateSectionActionMutation = useMutation({ mutationFn: async (variables: { @@ -216,7 +221,7 @@ export default function Update({ section }: { section: ISection }) {
+
diff --git a/web/app/[locale]/admin/sections/create.tsx b/web/app/[locale]/admin/sections/create.tsx index 6924e5b4..20be312f 100644 --- a/web/app/[locale]/admin/sections/create.tsx +++ b/web/app/[locale]/admin/sections/create.tsx @@ -5,6 +5,7 @@ import { type ChangeEvent, type FormEvent, useContext, useState } from 'react'; import { GlobalContext } from '@/app/[locale]/contexts'; import { useMutation } from '@tanstack/react-query'; import CreateSectionAction from '@/app/[locale]/actions/sections/create-section-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Create() { const { toast } = useContext(GlobalContext); @@ -13,6 +14,10 @@ export default function Create() { }>({ name: '', }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/sections', + 'Sections#Create', + ); const createSectionActionMutation = useMutation({ mutationFn: async (variables: { name: string }) => { @@ -85,9 +90,7 @@ export default function Create() {
+
diff --git a/web/app/[locale]/admin/submenus/[id]/delete.tsx b/web/app/[locale]/admin/submenus/[id]/delete.tsx index fe983ac5..e582afaf 100644 --- a/web/app/[locale]/admin/submenus/[id]/delete.tsx +++ b/web/app/[locale]/admin/submenus/[id]/delete.tsx @@ -7,9 +7,14 @@ import { GlobalContext } from '@/app/[locale]/contexts'; import RefreshAction from '@/app/[locale]/actions/refresh-action'; import type { ISubmenu } from '@/app/[locale]/interfaces/menus'; import DeleteSubmenuAction from '@/app/[locale]/actions/submenus/delete-submenu-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ submenu }: { submenu: ISubmenu }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/submenus', + 'Submenus#Delete', + ); const deleteSubmenuActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -76,12 +81,13 @@ export default function Delete({ submenu }: { submenu: ISubmenu }) {
+
diff --git a/web/app/[locale]/admin/submenus/[id]/update-roles.tsx b/web/app/[locale]/admin/submenus/[id]/update-roles.tsx index 918bc162..27e635b7 100644 --- a/web/app/[locale]/admin/submenus/[id]/update-roles.tsx +++ b/web/app/[locale]/admin/submenus/[id]/update-roles.tsx @@ -10,12 +10,17 @@ import type { ISubmenu } from '@/app/[locale]/interfaces/menus'; import UpdateRolesSubmenuAction, { type IUpdateRolesSubmenuActionVariables, } from '@/app/[locale]/actions/submenus/update-roles-submenu-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateRoles({ submenu }: { submenu: ISubmenu }) { const { toast } = useContext(GlobalContext); const [roles, setRoles] = useState( submenu.roles.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/submenus', + 'Submenus#Update Roles', + ); const updateRolesSubmenuActionMutation = useMutation({ mutationFn: async (variables: { @@ -81,7 +86,9 @@ export default function UpdateRoles({ submenu }: { submenu: ISubmenu }) {
+
diff --git a/web/app/[locale]/admin/submenus/[id]/update.tsx b/web/app/[locale]/admin/submenus/[id]/update.tsx index be20dea3..c106d1f3 100644 --- a/web/app/[locale]/admin/submenus/[id]/update.tsx +++ b/web/app/[locale]/admin/submenus/[id]/update.tsx @@ -10,6 +10,7 @@ import UpdateSubmenuAction, { type IUpdateSubmenuActionVariables, } from '@/app/[locale]/actions/submenus/update-submenu-action'; import SimpleDynamicInput from '@/app/[locale]/common/simple-dynamic-input'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Update({ submenu }: { submenu: ISubmenu }) { const { toast } = useContext(GlobalContext); @@ -27,6 +28,10 @@ export default function Update({ submenu }: { submenu: ISubmenu }) { const [actions, setActions] = useState( submenu.actions.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/submenus', + 'Submenus#Update', + ); const updateSubmenuActionMutation = useMutation({ mutationFn: async (variables: { @@ -200,7 +205,7 @@ export default function Update({ submenu }: { submenu: ISubmenu }) {
+
diff --git a/web/app/[locale]/admin/submenus/create.tsx b/web/app/[locale]/admin/submenus/create.tsx index 8d64f2dc..dfac823e 100644 --- a/web/app/[locale]/admin/submenus/create.tsx +++ b/web/app/[locale]/admin/submenus/create.tsx @@ -8,6 +8,7 @@ import { trimObjectStrings } from '@/app/[locale]/common/client'; import CreateSubmenuAction, { type ICreateSubmenuActionVariables, } from '@/app/[locale]/actions/submenus/create-submenu-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Create() { const { toast } = useContext(GlobalContext); @@ -20,6 +21,10 @@ export default function Create() { link: '', sort: 0, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/submenus', + 'Submenus#Create', + ); const createSubmenuActionMutation = useMutation({ mutationFn: async (variables: ICreateSubmenuActionVariables) => { @@ -141,7 +146,7 @@ export default function Create() {
+
diff --git a/web/app/[locale]/admin/tag-groups/[id]/delete.tsx b/web/app/[locale]/admin/tag-groups/[id]/delete.tsx index 6ced5e4f..9ab7b1d6 100644 --- a/web/app/[locale]/admin/tag-groups/[id]/delete.tsx +++ b/web/app/[locale]/admin/tag-groups/[id]/delete.tsx @@ -7,9 +7,14 @@ import { GlobalContext } from '@/app/[locale]/contexts'; import RefreshAction from '@/app/[locale]/actions/refresh-action'; import type { ITagGroup } from '@/app/[locale]/interfaces/tag-groups'; import DeleteTagGroupAction from '@/app/[locale]/actions/tag-groups/delete-tag-group-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ tagGroup }: { tagGroup: ITagGroup }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/tag-groups', + 'Tag Groups#Delete', + ); const deleteTagGroupActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -75,12 +80,15 @@ export default function Delete({ tagGroup }: { tagGroup: ITagGroup }) {
+
diff --git a/web/app/[locale]/admin/tag-groups/[id]/update-tags.tsx b/web/app/[locale]/admin/tag-groups/[id]/update-tags.tsx index 2a99da42..bc969ca5 100644 --- a/web/app/[locale]/admin/tag-groups/[id]/update-tags.tsx +++ b/web/app/[locale]/admin/tag-groups/[id]/update-tags.tsx @@ -10,12 +10,17 @@ import type { ITagGroup } from '@/app/[locale]/interfaces/tag-groups'; import UpdateTagsTagGroupAction, { type IUpdateTagsTagGroupActionVariables, } from '@/app/[locale]/actions/tag-groups/update-tags-tag-group-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateTags({ tagGroup }: { tagGroup: ITagGroup }) { const { toast } = useContext(GlobalContext); const [tags, setTags] = useState( tagGroup.tags.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/tag-groups', + 'Tag Groups#Update Tags', + ); const updateTagsTagGroupActionMutation = useMutation({ mutationFn: async (variables: { @@ -81,7 +86,9 @@ export default function UpdateTags({ tagGroup }: { tagGroup: ITagGroup }) {
+
diff --git a/web/app/[locale]/admin/tag-groups/[id]/update.tsx b/web/app/[locale]/admin/tag-groups/[id]/update.tsx index 1dcd4cde..87d83f86 100644 --- a/web/app/[locale]/admin/tag-groups/[id]/update.tsx +++ b/web/app/[locale]/admin/tag-groups/[id]/update.tsx @@ -9,6 +9,7 @@ import type { ITagGroup } from '@/app/[locale]/interfaces/tag-groups'; import UpdateTagGroupAction, { type IUpdateTagGroupActionVariables, } from '@/app/[locale]/actions/tag-groups/update-tag-group-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Update({ tagGroup }: { tagGroup: ITagGroup }) { const { toast } = useContext(GlobalContext); @@ -19,6 +20,10 @@ export default function Update({ tagGroup }: { tagGroup: ITagGroup }) { name: tagGroup.name ?? '', sort: tagGroup.sort ?? 0, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/tag-groups', + 'Tag Groups#Update', + ); const updateTagGroupActionMutation = useMutation({ mutationFn: async (variables: { @@ -118,7 +123,9 @@ export default function Update({ tagGroup }: { tagGroup: ITagGroup }) {
+
diff --git a/web/app/[locale]/admin/tag-groups/create.tsx b/web/app/[locale]/admin/tag-groups/create.tsx index 727b03b9..61748e9d 100644 --- a/web/app/[locale]/admin/tag-groups/create.tsx +++ b/web/app/[locale]/admin/tag-groups/create.tsx @@ -5,6 +5,7 @@ import { type ChangeEvent, type FormEvent, useContext, useState } from 'react'; import { GlobalContext } from '@/app/[locale]/contexts'; import { useMutation } from '@tanstack/react-query'; import CreateTagGroupAction from '@/app/[locale]/actions/tag-groups/create-tag-group-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Create() { const { toast } = useContext(GlobalContext); @@ -13,6 +14,10 @@ export default function Create() { }>({ name: '', }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/tag-groups', + 'Tag Groups#Create', + ); const createTagGroupActionMutation = useMutation({ mutationFn: async (variables: { name: string }) => { @@ -90,7 +95,7 @@ export default function Create() {
diff --git a/web/app/[locale]/admin/tags/[id]/delete.tsx b/web/app/[locale]/admin/tags/[id]/delete.tsx index 99724fcd..c0b4ddeb 100644 --- a/web/app/[locale]/admin/tags/[id]/delete.tsx +++ b/web/app/[locale]/admin/tags/[id]/delete.tsx @@ -7,9 +7,14 @@ import { GlobalContext } from '@/app/[locale]/contexts'; import RefreshAction from '@/app/[locale]/actions/refresh-action'; import type { ITag } from '@/app/[locale]/interfaces/tags'; import DeleteTagAction from '@/app/[locale]/actions/tags/delete-tag-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ tag }: { tag: ITag }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/tags', + 'Tags#Delete', + ); const deleteTagActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -74,12 +79,13 @@ export default function Delete({ tag }: { tag: ITag }) {
+
diff --git a/web/app/[locale]/admin/tags/[id]/update.tsx b/web/app/[locale]/admin/tags/[id]/update.tsx index 9d40d804..ee731808 100644 --- a/web/app/[locale]/admin/tags/[id]/update.tsx +++ b/web/app/[locale]/admin/tags/[id]/update.tsx @@ -9,6 +9,7 @@ import type { ITag } from '@/app/[locale]/interfaces/tags'; import UpdateTagAction, { type IUpdateTagActionVariables, } from '@/app/[locale]/actions/tags/update-tag-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Update({ tag }: { tag: ITag }) { const { toast } = useContext(GlobalContext); @@ -19,6 +20,10 @@ export default function Update({ tag }: { tag: ITag }) { name: tag.name ?? '', sort: tag.sort ?? 0, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/tags', + 'Tags#Update', + ); const updateTagActionMutation = useMutation({ mutationFn: async (variables: { @@ -117,12 +122,13 @@ export default function Update({ tag }: { tag: ITag }) {
+
diff --git a/web/app/[locale]/admin/tags/create.tsx b/web/app/[locale]/admin/tags/create.tsx index 3c2a97cd..1df3faac 100644 --- a/web/app/[locale]/admin/tags/create.tsx +++ b/web/app/[locale]/admin/tags/create.tsx @@ -5,6 +5,7 @@ import { type ChangeEvent, type FormEvent, useContext, useState } from 'react'; import { GlobalContext } from '@/app/[locale]/contexts'; import { useMutation } from '@tanstack/react-query'; import CreateTagAction from '@/app/[locale]/actions/tags/create-tag-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Create() { const { toast } = useContext(GlobalContext); @@ -13,6 +14,10 @@ export default function Create() { }>({ name: '', }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/tags', + 'Tags#Create', + ); const createTagActionMutation = useMutation({ mutationFn: async (variables: { name: string }) => { @@ -88,12 +93,13 @@ export default function Create() {
+
diff --git a/web/app/[locale]/admin/users/[id]/delete.tsx b/web/app/[locale]/admin/users/[id]/delete.tsx index 9bef75cc..991999cd 100644 --- a/web/app/[locale]/admin/users/[id]/delete.tsx +++ b/web/app/[locale]/admin/users/[id]/delete.tsx @@ -8,9 +8,14 @@ import RefreshAction from '@/app/[locale]/actions/refresh-action'; import type { IUser } from '@/app/[locale]/interfaces/users'; import DeleteUserAction from '@/app/[locale]/actions/users/delete-user-action'; import { getUserAlias } from '@/app/[locale]/common/client'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function Delete({ user }: { user: IUser }) { const { toast } = useContext(GlobalContext); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/users', + 'Users#Delete', + ); const deleteUserActionMutation = useMutation({ mutationFn: async (variables: { id: number }) => { @@ -75,12 +80,13 @@ export default function Delete({ user }: { user: IUser }) {
+
diff --git a/web/app/[locale]/admin/users/[id]/update-roles.tsx b/web/app/[locale]/admin/users/[id]/update-roles.tsx index 58d7dca4..98ee3c91 100644 --- a/web/app/[locale]/admin/users/[id]/update-roles.tsx +++ b/web/app/[locale]/admin/users/[id]/update-roles.tsx @@ -10,12 +10,17 @@ import type { IUser } from '@/app/[locale]/interfaces/users'; import UpdateRolesUserAction, { type IUpdateRolesUserActionVariables, } from '@/app/[locale]/actions/users/update-roles-user-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateRoles({ user }: { user: IUser }) { const { toast } = useContext(GlobalContext); const [roles, setRoles] = useState( user.roles.map((item) => item.id + ''), ); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/users', + 'Users#Update Roles', + ); const updateRolesUserGroupActionMutation = useMutation({ mutationFn: async (variables: { @@ -81,7 +86,9 @@ export default function UpdateRoles({ user }: { user: IUser }) {
+
diff --git a/web/app/[locale]/admin/users/[id]/update-states.tsx b/web/app/[locale]/admin/users/[id]/update-states.tsx index c56f6e14..975a7e24 100644 --- a/web/app/[locale]/admin/users/[id]/update-states.tsx +++ b/web/app/[locale]/admin/users/[id]/update-states.tsx @@ -9,6 +9,7 @@ import type { IUser } from '@/app/[locale]/interfaces/users'; import UpdateStatesUserAction, { type IUpdateStatesUserActionVariables, } from '@/app/[locale]/actions/users/update-states-user-action'; +import useMenuActionPermission from '@/app/[locale]/hooks/useMenuActionPermission'; export default function UpdateStates({ user }: { user: IUser }) { const { toast } = useContext(GlobalContext); @@ -23,6 +24,10 @@ export default function UpdateStates({ user }: { user: IUser }) { accountNonLocked: user.accountNonLocked ?? true, enabled: user.enabled ?? true, }); + const { isActionDisabled, AccessDeniedAlert } = useMenuActionPermission( + '/admin/users', + 'Users#Update States', + ); const updateStatesUserActionMutation = useMutation({ mutationFn: async (variables: { @@ -149,7 +154,9 @@ export default function UpdateStates({ user }: { user: IUser }) {
+
diff --git a/web/app/[locale]/constants/index.ts b/web/app/[locale]/constants/index.ts index fb0f6553..1d50bba2 100644 --- a/web/app/[locale]/constants/index.ts +++ b/web/app/[locale]/constants/index.ts @@ -32,9 +32,9 @@ export const ACTION_PAGES_DATA = { 'Section Groups': ['Create', 'Update', 'Update Sections', 'Delete'], Tags: ['Create', 'Update', 'Delete'], 'Tag Groups': ['Create', 'Update', 'Update Tags', 'Delete'], - Posts: ['Update States', 'Update Tags', 'Update Section'], + Posts: ['Update States', 'Update Tags', 'Update Section', 'Delete'], 'Post Review Queues': ['Receive', 'Return', 'Approved', 'NotApproved'], - Comments: [], + Comments: ['Update State'], Messages: ['Create'], 'Point Rules': ['Update'], 'Point Permissions': ['Update'], diff --git a/web/app/[locale]/hooks/useMenuActionPermission.tsx b/web/app/[locale]/hooks/useMenuActionPermission.tsx new file mode 100644 index 00000000..3b33a5e7 --- /dev/null +++ b/web/app/[locale]/hooks/useMenuActionPermission.tsx @@ -0,0 +1,69 @@ +import { useEffect, useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import MenusUserAction from '@/app/[locale]/actions/users/menus-user-action'; +import { useTranslations } from 'next-intl'; + +function useMenuActionPermission(link: string, name: string) { + const [isActionDisabled, setIsActionDisabled] = useState(false); + + const menuQuery = useQuery({ + queryKey: ['/users', '/menus'], + queryFn: async () => { + const response = await MenusUserAction(); + if (response.isError) { + throw response; + } + + return response.data; + }, + }); + + useEffect(() => { + if (menuQuery.data) { + const menus = menuQuery.data; + let find = menus.find((item) => item.link === link); + if (!find) { + const findSubmenu = menus + .filter((item) => item.submenus.length > 0) + .find((item) => + item.submenus.find((submenuItem) => submenuItem.link === link), + ); + + if (!findSubmenu) { + setIsActionDisabled(true); + return; + } + + find = findSubmenu; + } + + const findAction = find.actions.find((item) => item.name === name); + setIsActionDisabled(!findAction); + } else { + setIsActionDisabled(true); + } + }, [menuQuery.data, link, name]); + + return { + isActionDisabled, + AccessDeniedAlert: isActionDisabled + ? AccessDeniedAlert + : AccessGrantedAlert, + }; +} + +function AccessDeniedAlert() { + const t = useTranslations(); + + return ( +
+ {t('common.sorryYouDontHaveAccessToThisButtonYet')} +
+ ); +} + +function AccessGrantedAlert() { + return <>; +} + +export default useMenuActionPermission; diff --git a/web/app/[locale]/posts/[id]/navbar.tsx b/web/app/[locale]/posts/[id]/navbar.tsx index 324b7484..40d03b4a 100644 --- a/web/app/[locale]/posts/[id]/navbar.tsx +++ b/web/app/[locale]/posts/[id]/navbar.tsx @@ -46,7 +46,14 @@ export default function Navbar({ details }: { details: IPostDetails }) {
-
{details.name}
+
+ + {details.name} + +
{details.reviewState !== 'APPROVED' && (
diff --git a/web/messages/en.json b/web/messages/en.json index ccedddcf..34ad5bf2 100644 --- a/web/messages/en.json +++ b/web/messages/en.json @@ -74,6 +74,8 @@ "upload": "Upload", "postCoverImageFormText": "Only JPG Or PNG format cover image files are supported, with a size of up to 1MB.", "readMore": "Read More", - "footerFormText": "Built by Youdeyiwu. The source code is available on Github." + "footerFormText": "Built by Youdeyiwu. The source code is available on Github.", + "userRegistrationStatisticsForTheLast15Days": "User registration statistics for the last 15 days", + "sorryYouDontHaveAccessToThisButtonYet": "Sorry, you don't have access to this button yet" } } diff --git a/web/messages/zh.json b/web/messages/zh.json index 39ddf1ea..e2687876 100644 --- a/web/messages/zh.json +++ b/web/messages/zh.json @@ -74,6 +74,8 @@ "upload": "上传", "postCoverImageFormText": "仅支持 JPG 或 PNG 格式的封面文件,大小不能超过 1MB", "readMore": "阅读更多", - "footerFormText": "由 Youdeyiwu 构建。源代码可在 Github 上获取" + "footerFormText": "由 Youdeyiwu 构建。源代码可在 Github 上获取", + "userRegistrationStatisticsForTheLast15Days": "过去 15 天用户注册统计", + "sorryYouDontHaveAccessToThisButtonYet": "抱歉,您暂无权限执行该按钮操作" } }