103 lines
4.4 KiB
TypeScript
103 lines
4.4 KiB
TypeScript
'use server'
|
|
|
|
import { revalidateTag } from 'next/cache'
|
|
import { z } from 'zod'
|
|
import { PERMS } from '@/lib/permission-slugs'
|
|
import { prisma } from '@/lib/prisma'
|
|
import { adminAction } from '@/lib/safe-action'
|
|
import { ActionError, actionOk } from '@/lib/safe-action-shared'
|
|
import { createEmulatorRank, deleteEmulatorRank, updateEmulatorRank } from '@/lib/services/permission-ranks'
|
|
import { rcon } from '@/lib/services/rcon'
|
|
import { logStaffActivity } from '@/lib/services/staff-activity'
|
|
|
|
const createRankSchema = z.object({
|
|
rank_name: z.string().trim().min(1).max(25),
|
|
level: z.coerce.number().int().min(1),
|
|
})
|
|
|
|
export const createRank = adminAction(
|
|
{ schema: createRankSchema, permission: PERMS.PERMISSIONS_MANAGE },
|
|
async (ctx) => {
|
|
const id = await createEmulatorRank(prisma, ctx.data)
|
|
await prisma.aclRole.upsert({
|
|
where: { slug: `rank_${id}` },
|
|
create: { slug: `rank_${id}`, title: ctx.data.rank_name, description: 'CMS role synchronized from permission_ranks' },
|
|
update: { title: ctx.data.rank_name },
|
|
})
|
|
await logStaffActivity({ staffId: ctx.session.user.id, action: 'rank_create', description: `Created rank #${id}`, targetType: 'rank', targetId: id })
|
|
await rcon.send('updatepermissions')
|
|
revalidateTag('permissions', { expire: 0 })
|
|
return actionOk({ id })
|
|
},
|
|
)
|
|
|
|
const deleteRankSchema = z.object({ id: z.coerce.number().int().positive() })
|
|
|
|
export const deleteRank = adminAction(
|
|
{ schema: deleteRankSchema, permission: PERMS.PERMISSIONS_MANAGE },
|
|
async (ctx) => {
|
|
const users = await prisma.user.count({ where: { rank: ctx.data.id } })
|
|
if (users > 0) throw new ActionError(`Cannot delete: ${users} users have this rank`)
|
|
const role = await prisma.aclRole.findFirst({ where: { slug: `rank_${ctx.data.id}` } })
|
|
await deleteEmulatorRank(prisma, ctx.data.id)
|
|
if (role) {
|
|
await prisma.$transaction([
|
|
prisma.aclModelPermission.deleteMany({ where: { modelId: role.id, modelType: 'Role' } }),
|
|
prisma.aclModelRole.deleteMany({ where: { roleId: role.id } }),
|
|
prisma.aclRole.delete({ where: { id: role.id } }),
|
|
])
|
|
}
|
|
await logStaffActivity({ staffId: ctx.session.user.id, action: 'rank_delete', description: `Deleted rank #${ctx.data.id}`, targetType: 'rank', targetId: ctx.data.id })
|
|
await rcon.send('updatepermissions')
|
|
revalidateTag('permissions', { expire: 0 })
|
|
return actionOk()
|
|
},
|
|
)
|
|
|
|
const saveRankSchema = z.object({
|
|
id: z.coerce.number().int().positive(),
|
|
fields: z.record(z.string(), z.union([z.string(), z.number()])),
|
|
})
|
|
|
|
export const saveRank = adminAction(
|
|
{ schema: saveRankSchema, permission: PERMS.PERMISSIONS_MANAGE },
|
|
async (ctx) => {
|
|
await updateEmulatorRank(prisma, ctx.data.id, ctx.data.fields)
|
|
if (typeof ctx.data.fields.rank_name === 'string') {
|
|
await prisma.aclRole.updateMany({ where: { slug: `rank_${ctx.data.id}` }, data: { title: ctx.data.fields.rank_name } })
|
|
}
|
|
await logStaffActivity({ staffId: ctx.session.user.id, action: 'rank_update', description: `Updated rank #${ctx.data.id}`, targetType: 'rank', targetId: ctx.data.id })
|
|
await rcon.send('updatepermissions')
|
|
revalidateTag('permissions', { expire: 0 })
|
|
return actionOk()
|
|
},
|
|
)
|
|
|
|
const setCmsPermsSchema = z.object({
|
|
roleId: z.coerce.number().int().positive(),
|
|
permissionSlugs: z.array(z.string().trim().min(1)).max(500),
|
|
})
|
|
|
|
export const setCmsPermissions = adminAction(
|
|
{ schema: setCmsPermsSchema, permission: PERMS.PERMISSIONS_MANAGE },
|
|
async (ctx) => {
|
|
const role = await prisma.aclRole.findUnique({ where: { id: ctx.data.roleId }, select: { id: true, slug: true } })
|
|
if (!role) throw new ActionError('Role not found')
|
|
const permissions = await prisma.aclPermission.findMany({
|
|
where: { slug: { in: ctx.data.permissionSlugs } },
|
|
select: { id: true },
|
|
})
|
|
await prisma.$transaction(async (tx) => {
|
|
await tx.aclModelPermission.deleteMany({ where: { modelId: role.id, modelType: 'Role' } })
|
|
if (permissions.length) {
|
|
await tx.aclModelPermission.createMany({
|
|
data: permissions.map((permission) => ({ modelId: role.id, modelType: 'Role', permissionId: permission.id })),
|
|
})
|
|
}
|
|
})
|
|
await logStaffActivity({ staffId: ctx.session.user.id, action: 'acl_role_permissions_update', description: `Updated ${permissions.length} permissions for ${role.slug}`, targetType: 'acl_role', targetId: role.id })
|
|
revalidateTag('permissions', { expire: 0 })
|
|
return actionOk()
|
|
},
|
|
)
|