From bbd76fea1867a456fbf54f57259ae8e76d2db0ed Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Wed, 16 Oct 2024 19:12:53 +0200 Subject: [PATCH] fix(frontend): Revalidate date when edit admin permissions in AdminCP --- apps/backend/schema.gql | 2 +- .../create-edit/create-edit.dto.ts | 3 + .../create-edit/create-edit.service.ts | 76 ++++- .../src/utils/guards/admin-auth.guard.ts | 2 + .../frontend/src/components/ui/carousel.tsx | 2 +- ...f_administrators__create_edit.generated.ts | 4 +- ...core_staff_administrators__create_edit.gql | 2 + packages/frontend/src/graphql/types.ts | 1 + .../create-edit-form/hooks/mutation-api.ts | 4 +- .../create-edit-form/hooks/use-form.ts | 15 +- .../views/members/staff/permissions-field.tsx | 273 ++++++++---------- 11 files changed, 220 insertions(+), 164 deletions(-) diff --git a/apps/backend/schema.gql b/apps/backend/schema.gql index 8d24e229c..9b3afb431 100644 --- a/apps/backend/schema.gql +++ b/apps/backend/schema.gql @@ -248,7 +248,7 @@ type Mutation { admin__core_plugins__permissions_admin__delete(id: String!, parent_id: String, plugin_code: String!): String! admin__core_plugins__upload(code: String, file: Upload!): String! admin__core_security__captcha__edit(secret_key: String!, site_key: String!, type: CaptchaTypeEnum!): ShowAdminCaptchaSecurityObj! - admin__core_staff_administrators__create_edit(group_id: Int, permissions: [PermissionsStaffArgs!], user_id: Int): ShowAdminStaffAdministrators! + admin__core_staff_administrators__create_edit(group_id: Int, id: Int, permissions: [PermissionsStaffArgs!], user_id: Int): ShowAdminStaffAdministrators! admin__core_staff_administrators__delete(id: Int!): String! admin__core_staff_moderators__create(group_id: Int, user_id: Int): ShowAdminStaffModerators! admin__core_staff_moderators__delete(id: Int!): String! diff --git a/packages/backend/src/core/admin/staff/administrators/create-edit/create-edit.dto.ts b/packages/backend/src/core/admin/staff/administrators/create-edit/create-edit.dto.ts index 3c74714bb..4f61b84b1 100644 --- a/packages/backend/src/core/admin/staff/administrators/create-edit/create-edit.dto.ts +++ b/packages/backend/src/core/admin/staff/administrators/create-edit/create-edit.dto.ts @@ -7,6 +7,9 @@ export class CreateEditAdminStaffAdministratorsArgs { @Field(() => Int, { nullable: true }) group_id: null | number; + @Field(() => Int, { nullable: true }) + id: null | number; + @Field(() => [PermissionsStaffArgs], { nullable: true }) permissions: PermissionsStaffArgs[]; diff --git a/packages/backend/src/core/admin/staff/administrators/create-edit/create-edit.service.ts b/packages/backend/src/core/admin/staff/administrators/create-edit/create-edit.service.ts index 92ff383db..d7be81f93 100644 --- a/packages/backend/src/core/admin/staff/administrators/create-edit/create-edit.service.ts +++ b/packages/backend/src/core/admin/staff/administrators/create-edit/create-edit.service.ts @@ -1,8 +1,9 @@ import { core_admin_permissions } from '@/database/schema/admins'; -import { CustomError, NotFoundError } from '@/errors'; +import { CustomError, InternalServerError, NotFoundError } from '@/errors'; import { getUser } from '@/utils/database/helpers/get-user'; import { InternalDatabaseService } from '@/utils/database/internal_database.service'; import { Injectable } from '@nestjs/common'; +import { eq } from 'drizzle-orm'; import { ShowAdminStaffAdministrators } from '../show/show.dto'; import { CreateEditAdminStaffAdministratorsArgs } from './create-edit.dto'; @@ -15,7 +16,75 @@ export class CreateEditAdminStaffAdministratorsService { group_id, user_id, permissions, + id, }: CreateEditAdminStaffAdministratorsArgs): Promise { + // Edit + if (id) { + const permission = + await this.databaseService.db.query.core_admin_permissions.findFirst({ + where: (table, { eq }) => eq(table.id, id), + }); + + if (!permission) { + throw new NotFoundError('Permission'); + } + + await this.databaseService.db + .update(core_admin_permissions) + .set({ + permissions, + }) + .where(eq(core_admin_permissions.id, id)); + + const data = + await this.databaseService.db.query.core_admin_permissions.findFirst({ + where: (table, { eq }) => eq(table.id, id), + with: { + group: { + columns: { + id: true, + color: true, + }, + }, + }, + }); + + if (!data) { + throw new InternalServerError(); + } + + if (data.user_id) { + const user = await getUser({ + id: data.user_id, + db: this.databaseService.db, + }); + + return { + ...data, + user_or_group: { + ...user, + }, + permissions: + data.permissions as ShowAdminStaffAdministrators['permissions'], + }; + } + + if (!data.group) { + throw new InternalServerError(); + } + + return { + ...data, + user_or_group: { + ...data.group, + group_name: [], + }, + permissions: + data.permissions as ShowAdminStaffAdministrators['permissions'], + }; + } + + // Create if (!group_id && !user_id) { throw new CustomError({ code: 'BAD_REQUEST', @@ -38,8 +107,7 @@ export class CreateEditAdminStaffAdministratorsService { message: 'This user or group already has moderator permissions.', }); } - - const permission = await this.databaseService.db + const [permission] = await this.databaseService.db .insert(core_admin_permissions) .values({ user_id, @@ -50,7 +118,7 @@ export class CreateEditAdminStaffAdministratorsService { const data = await this.databaseService.db.query.core_admin_permissions.findFirst({ - where: (table, { eq }) => eq(table.id, permission[0].id), + where: (table, { eq }) => eq(table.id, permission.id), with: { group: { columns: { diff --git a/packages/backend/src/utils/guards/admin-auth.guard.ts b/packages/backend/src/utils/guards/admin-auth.guard.ts index e6684e13b..e4267c63d 100644 --- a/packages/backend/src/utils/guards/admin-auth.guard.ts +++ b/packages/backend/src/utils/guards/admin-auth.guard.ts @@ -60,6 +60,8 @@ export class AdminAuthGuards implements CanActivate { if (!plugin) throw new AccessDeniedError(); const group = plugin.groups.find(group => group.id === permission.group); if (!group) throw new AccessDeniedError(); + if (group.permissions.length === 0) return !!authorization; + const permissionObj = group.permissions.find( item => item === permission.permission, ); diff --git a/packages/frontend/src/components/ui/carousel.tsx b/packages/frontend/src/components/ui/carousel.tsx index 5e20cc720..dcaf20b81 100644 --- a/packages/frontend/src/components/ui/carousel.tsx +++ b/packages/frontend/src/components/ui/carousel.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { cn } from '../../helpers/classnames'; import { Button } from './button'; -type CarouselApi = UseEmblaCarouselType[1]; +export type CarouselApi = UseEmblaCarouselType[1]; type UseCarouselParameters = Parameters; type CarouselOptions = UseCarouselParameters[0]; type CarouselPlugin = UseCarouselParameters[1]; diff --git a/packages/frontend/src/graphql/mutations/admin/members/staff/administrators/admin__core_staff_administrators__create_edit.generated.ts b/packages/frontend/src/graphql/mutations/admin/members/staff/administrators/admin__core_staff_administrators__create_edit.generated.ts index 1fac3e508..f6fc10d12 100644 --- a/packages/frontend/src/graphql/mutations/admin/members/staff/administrators/admin__core_staff_administrators__create_edit.generated.ts +++ b/packages/frontend/src/graphql/mutations/admin/members/staff/administrators/admin__core_staff_administrators__create_edit.generated.ts @@ -5,6 +5,7 @@ export type Admin__Core_Staff_Administrators__Create_EditMutationVariables = Typ groupId?: Types.InputMaybe; userId?: Types.InputMaybe; permissions?: Types.InputMaybe | Types.PermissionsStaffArgs>; + id?: Types.InputMaybe; }>; @@ -12,11 +13,12 @@ export type Admin__Core_Staff_Administrators__Create_EditMutation = { __typename export const Admin__Core_Staff_Administrators__Create_Edit = gql` - mutation Admin__core_staff_administrators__create_edit($groupId: Int, $userId: Int, $permissions: [PermissionsStaffArgs!]) { + mutation Admin__core_staff_administrators__create_edit($groupId: Int, $userId: Int, $permissions: [PermissionsStaffArgs!], $id: Int) { admin__core_staff_administrators__create_edit( group_id: $groupId user_id: $userId permissions: $permissions + id: $id ) { id } diff --git a/packages/frontend/src/graphql/mutations/admin/members/staff/administrators/admin__core_staff_administrators__create_edit.gql b/packages/frontend/src/graphql/mutations/admin/members/staff/administrators/admin__core_staff_administrators__create_edit.gql index 632352363..39d2b5b4d 100644 --- a/packages/frontend/src/graphql/mutations/admin/members/staff/administrators/admin__core_staff_administrators__create_edit.gql +++ b/packages/frontend/src/graphql/mutations/admin/members/staff/administrators/admin__core_staff_administrators__create_edit.gql @@ -2,11 +2,13 @@ mutation Admin__core_staff_administrators__create_edit( $groupId: Int $userId: Int $permissions: [PermissionsStaffArgs!] + $id: Int ) { admin__core_staff_administrators__create_edit( group_id: $groupId user_id: $userId permissions: $permissions + id: $id ) { id } diff --git a/packages/frontend/src/graphql/types.ts b/packages/frontend/src/graphql/types.ts index 043cb713d..d6e46b007 100644 --- a/packages/frontend/src/graphql/types.ts +++ b/packages/frontend/src/graphql/types.ts @@ -533,6 +533,7 @@ export type MutationAdmin__Core_Security__Captcha__EditArgs = { export type MutationAdmin__Core_Staff_Administrators__Create_EditArgs = { group_id?: InputMaybe; + id?: InputMaybe; permissions?: InputMaybe>; user_id?: InputMaybe; }; diff --git a/packages/frontend/src/views/admin/views/members/staff/administrators/create-edit-form/hooks/mutation-api.ts b/packages/frontend/src/views/admin/views/members/staff/administrators/create-edit-form/hooks/mutation-api.ts index bca091a29..37a393a08 100644 --- a/packages/frontend/src/views/admin/views/members/staff/administrators/create-edit-form/hooks/mutation-api.ts +++ b/packages/frontend/src/views/admin/views/members/staff/administrators/create-edit-form/hooks/mutation-api.ts @@ -19,11 +19,11 @@ export const mutationApi = async ( query: Admin__Core_Staff_Administrators__Create_Edit, variables, }); + + revalidatePath('/', 'layout'); } catch (error) { const e = error as Error; return { error: e.message }; } - - revalidatePath('/admin', 'layout'); }; diff --git a/packages/frontend/src/views/admin/views/members/staff/administrators/create-edit-form/hooks/use-form.ts b/packages/frontend/src/views/admin/views/members/staff/administrators/create-edit-form/hooks/use-form.ts index a337d2d02..4b58584a0 100644 --- a/packages/frontend/src/views/admin/views/members/staff/administrators/create-edit-form/hooks/use-form.ts +++ b/packages/frontend/src/views/admin/views/members/staff/administrators/create-edit-form/hooks/use-form.ts @@ -14,7 +14,7 @@ export const useFormCreateEditFormGroupsMembersAdmin = ({ }: { data?: Admin__Core_Staff_Administrators__ShowQuery['admin__core_staff_administrators__show']['edges'][0]; }) => { - const t = useTranslations('admin.members.staff.administrators.add'); + const t = useTranslations('admin.members.staff.administrators'); const tShared = useTranslations('admin.members.staff.shared'); const tCore = useTranslations('core.global'); const { convertText } = useTextLang(); @@ -75,15 +75,18 @@ export const useFormCreateEditFormGroupsMembersAdmin = ({ form: UseFormReturn>, ) => { const mutation = await mutationApi({ - groupId: - values.type === 'group' && values.group?.[0].key + groupId: data + ? undefined + : values.type === 'group' && values.group?.[0].key ? +values.group[0].key : undefined, - userId: - values.type === 'user' && values.user?.[0].key + userId: data + ? undefined + : values.type === 'user' && values.user?.[0].key ? +values.user[0].key : undefined, permissions: values.unrestricted ? [] : values.permissions, + id: data?.id, }); if (mutation?.error) { @@ -104,7 +107,7 @@ export const useFormCreateEditFormGroupsMembersAdmin = ({ } setOpen?.(false); - toast.success(t('success'), { + toast.success(t(data ? 'edit.success' : 'add.success'), { description: values.type === 'group' && Array.isArray(values.group?.[0].value) ? convertText(values.group[0].value) diff --git a/packages/frontend/src/views/admin/views/members/staff/permissions-field.tsx b/packages/frontend/src/views/admin/views/members/staff/permissions-field.tsx index 3f2fbcc17..dace00e05 100644 --- a/packages/frontend/src/views/admin/views/members/staff/permissions-field.tsx +++ b/packages/frontend/src/views/admin/views/members/staff/permissions-field.tsx @@ -1,16 +1,9 @@ import { AutoFormItemProps } from '@/components/form/auto-form'; -import { - Accordion, - AccordionContent, - AccordionItem, -} from '@/components/ui/accordion'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Tabs, TabsTrigger } from '@/components/ui/tabs'; import { Admin__Core_Staff_Administrators__ShowQuery } from '@/graphql/queries/admin/members/staff/admin__core_staff_administrators__show.generated'; import { cn } from '@/helpers/classnames'; -import { AccordionTrigger } from '@radix-ui/react-accordion'; -import { ChevronDown } from 'lucide-react'; import { useTranslations } from 'next-intl'; import React from 'react'; import { FieldValues } from 'react-hook-form'; @@ -38,7 +31,7 @@ export function PermissionsField({ const t = useTranslations(); return ( - + <> {permissions.map(permission => ( ({ const langKey = `admin_${plugin.plugin_code}.admin_permissions.${permission.id}`; return ( - +
({ }} /> - -
- - {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */} - {/* @ts-expect-error */} - {t.has(langKey) ? t(langKey) : langKey} - - -
-
+
- - {permission.permissions.length > 0 && ( -
    - {permission.permissions.map(child => { - const childValue = groupValue?.permissions.find( - c => c === child, - ); - const childLangKey = `${langKey}_${child}`; - - return ( -
  • - { - if (checked) { - const valueToChange: PermissionState[] = [ - ...values.filter( - value => - value.plugin_code !== - plugin.plugin_code, - ), - { - plugin_code: plugin.plugin_code, - groups: valuePlugin - ? [ - ...valuePlugin.groups.filter( - p => p.id !== permission.id, - ), - { - id: permission.id, - permissions: groupValue - ? [ - ...groupValue.permissions, - child, - ] - : [child], - }, - ] - : [ - { - id: permission.id, - permissions: [child], - }, - ], - }, - ]; - field.onChange(valueToChange); - - return; - } - - if (!valuePlugin) return; + {permission.permissions.length > 0 && ( +
      + {permission.permissions.map(child => { + const childValue = groupValue?.permissions.find( + c => c === child, + ); + const childLangKey = `${langKey}_${child}`; + return ( +
    • + { + if (checked) { const valueToChange: PermissionState[] = [ ...values.filter( value => @@ -206,84 +154,111 @@ export function PermissionsField({ plugin.plugin_code, ), { - ...valuePlugin, - groups: valuePlugin.groups.map(p => { - if (p.id !== permission.id) return p; - - return { - ...p, - permissions: childValue - ? p.permissions.filter( - c => c !== child, - ) - : permission.permissions.filter( - c => c !== child, - ), - }; - }), + plugin_code: plugin.plugin_code, + groups: valuePlugin + ? [ + ...valuePlugin.groups.filter( + p => p.id !== permission.id, + ), + { + id: permission.id, + permissions: groupValue + ? [ + ...groupValue.permissions, + child, + ] + : [child], + }, + ] + : [ + { + id: permission.id, + permissions: [child], + }, + ], }, ]; + field.onChange(valueToChange); - const checkIfEmpty = valueToChange.find( + return; + } + + if (!valuePlugin) return; + + const valueToChange: PermissionState[] = [ + ...values.filter( value => - value.plugin_code === - plugin.plugin_code && - value.groups.find( - p => p.id === permission.id, - )?.permissions.length === 0, - ); + value.plugin_code !== plugin.plugin_code, + ), + { + ...valuePlugin, + groups: valuePlugin.groups.map(p => { + if (p.id !== permission.id) return p; + + return { + ...p, + permissions: childValue + ? p.permissions.filter( + c => c !== child, + ) + : permission.permissions.filter( + c => c !== child, + ), + }; + }), + }, + ]; - const returnValue: PermissionState[] = - checkIfEmpty?.plugin_code === - plugin.plugin_code - ? valueToChange - .map(item => { - if ( - item.plugin_code === - plugin.plugin_code - ) { - return { - ...item, - permissions: item.groups.filter( - p => p.id !== permission.id, - ), - }; - } + const returnValue: PermissionState[] = + valueToChange + .map(item => { + if ( + item.plugin_code === plugin.plugin_code + ) { + const groups = item.groups.filter( + p => p.permissions.length > 0, + ); - return item; - }) - .filter( - plugin => plugin.groups.length > 0, - ) - : valueToChange; + if (groups.length === 0) { + return null; + } - field.onChange(returnValue); - }} - /> - -
    • - ); - })} -
    - )} - - + return { + ...item, + groups, + }; + } + + return item; + }) + .filter(Boolean) as PermissionState[]; + + field.onChange(returnValue); + }} + /> + +
  • + ); + })} +
+ )} +
); })} ); })} -
+ ); }