This commit is contained in:
TheCactusBlue 2025-03-25 12:02:36 -07:00
parent 1ffd1e3e5b
commit 952aa78981
6 changed files with 45 additions and 26 deletions

View File

@ -0,0 +1,19 @@
/*
Warnings:
- The values [USER] on the enum `PermissionScope` will be removed. If these variants are still used in the database, this will fail.
- You are about to drop the column `isDefaultUserPermission` on the `Permission` table. All the data in the column will be lost.
*/
-- AlterEnum
BEGIN;
CREATE TYPE "PermissionScope_new" AS ENUM ('PROJECT', 'TEAM');
ALTER TABLE "Permission" ALTER COLUMN "scope" TYPE "PermissionScope_new" USING ("scope"::text::"PermissionScope_new");
ALTER TYPE "PermissionScope" RENAME TO "PermissionScope_old";
ALTER TYPE "PermissionScope_new" RENAME TO "PermissionScope";
DROP TYPE "PermissionScope_old";
COMMIT;
-- AlterTable
ALTER TABLE "Permission" DROP COLUMN "isDefaultUserPermission",
ADD COLUMN "isDefaultProjectPermission" BOOLEAN NOT NULL DEFAULT false;

View File

@ -224,14 +224,14 @@ model Permission {
isDefaultTeamCreatorPermission Boolean @default(false)
isDefaultTeamMemberPermission Boolean @default(false)
isDefaultUserPermission Boolean @default(false)
isDefaultProjectPermission Boolean @default(false)
@@unique([projectConfigId, queryableId])
@@unique([tenancyId, teamId, queryableId])
}
enum PermissionScope {
USER
PROJECT
TEAM
}

View File

@ -34,27 +34,27 @@ export const projectsCrudHandlers = createLazyProxy(() => createCrudHandlers(pro
] as const;
const teamPermissions = await listPermissionDefinitions(tx, "TEAM", auth.tenancy);
const userPermissions = await listPermissionDefinitions(tx, "USER", auth.tenancy);
const projectPermissions = await listPermissionDefinitions(tx, "PROJECT", auth.tenancy);
// Handle user default permissions
const userDefaultPerms = data.config?.user_default_permissions?.map((p) => p.id);
if (userDefaultPerms) {
if (!userDefaultPerms.every((id) => userPermissions.some((perm) => perm.id === id))) {
if (!userDefaultPerms.every((id) => projectPermissions.some((perm) => perm.id === id))) {
throw new StatusError(StatusError.BadRequest,
`Invalid user default permission ids: ${userDefaultPerms.filter(id => !userPermissions.some(perm => perm.id === id)).join(', ')}`);
`Invalid user default permission ids: ${userDefaultPerms.filter(id => !projectPermissions.some(perm => perm.id === id)).join(', ')}`);
}
// Remove existing default user permissions
// Remove existing default project permissions
await tx.permission.updateMany({
where: {
projectConfigId: oldProject.config.id,
},
data: {
isDefaultUserPermission: false,
isDefaultProjectPermission: false,
},
});
// Add new default user permissions
// Add new default project permissions
await tx.permission.updateMany({
where: {
projectConfigId: oldProject.config.id,
@ -63,7 +63,7 @@ export const projectsCrudHandlers = createLazyProxy(() => createCrudHandlers(pro
},
},
data: {
isDefaultUserPermission: true,
isDefaultProjectPermission: true,
},
});
}

View File

@ -12,7 +12,7 @@ export const userPermissionDefinitionsCrudHandlers = createLazyProxy(() => creat
async onCreate({ auth, data }) {
return await retryTransaction(async (tx) => {
return await createPermissionDefinition(tx, {
scope: "USER",
scope: "PROJECT",
tenancy: auth.tenancy,
data,
});
@ -21,7 +21,7 @@ export const userPermissionDefinitionsCrudHandlers = createLazyProxy(() => creat
async onUpdate({ auth, data, params }) {
return await retryTransaction(async (tx) => {
return await updatePermissionDefinitions(tx, {
scope: "USER",
scope: "PROJECT",
tenancy: auth.tenancy,
permissionId: params.permission_id,
data,
@ -39,7 +39,7 @@ export const userPermissionDefinitionsCrudHandlers = createLazyProxy(() => creat
async onList({ auth }) {
return await retryTransaction(async (tx) => {
return {
items: await listPermissionDefinitions(tx, "USER", auth.tenancy),
items: await listPermissionDefinitions(tx, "PROJECT", auth.tenancy),
is_paginated: false,
};
});

View File

@ -42,7 +42,7 @@ type ExtendedTeamPermissionDefinition = TeamPermissionDefinitionsCrud["Admin"]["
__database_id: string,
__is_default_team_member_permission?: boolean,
__is_default_team_creator_permission?: boolean,
__is_default_user_permission?: boolean,
__is_default_project_permission?: boolean,
};
export function teamPermissionDefinitionJsonFromDbType(db: Prisma.PermissionGetPayload<{ include: typeof fullPermissionInclude }>): ExtendedTeamPermissionDefinition {
@ -54,13 +54,13 @@ export function teamPermissionDefinitionJsonFromDbType(db: Prisma.PermissionGetP
export function teamPermissionDefinitionJsonFromRawDbType(db: any | Prisma.PermissionGetPayload<{ include: typeof fullPermissionInclude }>): ExtendedTeamPermissionDefinition {
if (!db.projectConfigId && !db.teamId) throw new StackAssertionError(`Permission DB object should have either projectConfigId or teamId`, { db });
if (db.projectConfigId && db.teamId) throw new StackAssertionError(`Permission DB object should have either projectConfigId or teamId, not both`, { db });
if (db.scope === "USER" && db.teamId) throw new StackAssertionError(`Permission DB object should not have teamId when scope is USER`, { db });
if (db.scope === "PROJECT" && db.teamId) throw new StackAssertionError(`Permission DB object should not have teamId when scope is PROJECT`, { db });
return {
__database_id: db.dbId,
__is_default_team_member_permission: db.isDefaultTeamMemberPermission,
__is_default_team_creator_permission: db.isDefaultTeamCreatorPermission,
__is_default_user_permission: db.isDefaultUserPermission,
__is_default_project_permission: db.isDefaultProjectPermission,
id: db.queryableId,
description: db.description || undefined,
contained_permission_ids: db.parentEdges?.map((edge: any) => {
@ -78,7 +78,7 @@ export function teamPermissionDefinitionJsonFromRawDbType(db: any | Prisma.Permi
export function teamPermissionDefinitionJsonFromTeamSystemDbType(db: DBTeamSystemPermission, projectConfig: {
teamCreateDefaultSystemPermissions: string[] | null,
teamMemberDefaultSystemPermissions: string[] | null,
userDefaultPermissions?: string[] | null,
projectDefaultPermissions?: string[] | null,
}): ExtendedTeamPermissionDefinition {
if ((["teamMemberDefaultSystemPermissions", "teamCreateDefaultSystemPermissions"] as const).some(key => projectConfig[key] !== null && !Array.isArray(projectConfig[key]))) {
throw new StackAssertionError(`Project config should have (nullable) array values for teamMemberDefaultSystemPermissions and teamCreateDefaultSystemPermissions`, { projectConfig });
@ -88,7 +88,7 @@ export function teamPermissionDefinitionJsonFromTeamSystemDbType(db: DBTeamSyste
__database_id: '$' + typedToLowercase(db),
__is_default_team_member_permission: projectConfig.teamMemberDefaultSystemPermissions?.includes(db) ?? false,
__is_default_team_creator_permission: projectConfig.teamCreateDefaultSystemPermissions?.includes(db) ?? false,
__is_default_user_permission: projectConfig.userDefaultPermissions?.includes(db) ?? false,
__is_default_project_permission: projectConfig.projectDefaultPermissions?.includes(db) ?? false,
id: '$' + typedToLowercase(db),
description: descriptionMap[db],
contained_permission_ids: [] as string[],
@ -99,7 +99,7 @@ async function getParentDbIds(
tx: PrismaTransaction,
options: {
tenancy: Tenancy,
scope: "TEAM" | "USER",
scope: "TEAM" | "PROJECT",
containedPermissionIds?: string[],
}
) {
@ -324,7 +324,7 @@ export async function revokeTeamPermission(
export async function listPermissionDefinitions(
tx: PrismaTransaction,
scope: "TEAM" | "USER",
scope: "TEAM" | "PROJECT",
tenancy: Tenancy
): Promise<(TeamPermissionDefinitionsCrud["Admin"]["Read"] & { __database_id: string })[]> {
const projectConfig = await tx.projectConfig.findUnique({
@ -356,7 +356,7 @@ export async function listPermissionDefinitions(
export async function createPermissionDefinition(
tx: PrismaTransaction,
options: {
scope: "TEAM" | "USER",
scope: "TEAM" | "PROJECT",
tenancy: Tenancy,
data: {
id: string,
@ -402,7 +402,7 @@ export async function createPermissionDefinition(
export async function updatePermissionDefinitions(
tx: PrismaTransaction,
options: {
scope: "TEAM" | "USER",
scope: "TEAM" | "PROJECT",
tenancy: Tenancy,
permissionId: string,
data: {
@ -486,7 +486,7 @@ export async function listUserPermissions(
recursive: boolean,
}
): Promise<UserPermissionsCrud["Admin"]["Read"][]> {
const permissionDefs = await listPermissionDefinitions(tx, "USER", options.tenancy);
const permissionDefs = await listPermissionDefinitions(tx, "PROJECT", options.tenancy);
const permissionsMap = new Map(permissionDefs.map(p => [p.id, p]));
const results = await tx.projectUserDirectPermission.findMany({
where: {
@ -610,7 +610,7 @@ export async function revokeUserPermission(
}
/**
* Grants default user permissions to a user
* Grants default project permissions to a user
* This function should be called when a new user is created
*/
export async function grantDefaultUserPermissions(
@ -623,7 +623,7 @@ export async function grantDefaultUserPermissions(
const defaultPermissions = await tx.permission.findMany({
where: {
projectConfigId: options.tenancy.config.id,
isDefaultUserPermission: true,
isDefaultProjectPermission: true,
}
});

View File

@ -173,7 +173,7 @@ export function projectPrismaToCrud(
.concat(prisma.config.teamMemberDefaultSystemPermissions.map(db => teamPermissionDefinitionJsonFromTeamSystemDbType(db, prisma.config)))
.sort((a, b) => stringCompare(a.id, b.id))
.map(perm => ({ id: perm.id })),
user_default_permissions: prisma.config.permissions.filter(perm => perm.isDefaultUserPermission)
user_default_permissions: prisma.config.permissions.filter(perm => perm.isDefaultProjectPermission)
.map(teamPermissionDefinitionJsonFromDbType)
.sort((a, b) => stringCompare(a.id, b.id))
.map(perm => ({ id: perm.id })),
@ -464,7 +464,7 @@ export function getProjectQuery(projectId: string): RawQuery<ProjectsCrud["Admin
.filter(perm => perm.__is_default_team_member_permission)
.map(perm => ({ id: perm.id })),
user_default_permissions: teamPermissions
.filter(perm => perm.__is_default_user_permission)
.filter(perm => perm.__is_default_project_permission)
.map(perm => ({ id: perm.id })),
},
};