diff --git a/apps/backend/src/app/api/latest/internal/projects/current/crud.tsx b/apps/backend/src/app/api/latest/internal/projects/current/crud.tsx index e7c2dda13..3f63a8e80 100644 --- a/apps/backend/src/app/api/latest/internal/projects/current/crud.tsx +++ b/apps/backend/src/app/api/latest/internal/projects/current/crud.tsx @@ -1,4 +1,4 @@ -import { isTeamSystemPermission, listPermissionDefinitions, teamSystemPermissionStringToDBType } from "@/lib/permissions"; +import { isTeamSystemPermission, listPermissionDefinitions, systemPermissionStringToDBType } from "@/lib/permissions"; import { fullProjectInclude, projectPrismaToCrud } from "@/lib/projects"; import { ensureSharedProvider } from "@/lib/request-checks"; import { retryTransaction } from "@/prisma-client"; @@ -81,7 +81,7 @@ export const projectsCrudHandlers = createLazyProxy(() => createCrudHandlers(pro const systemPerms = defaultPerms .filter(p => isTeamSystemPermission(p)) - .map(p => teamSystemPermissionStringToDBType(p as any)); + .map(p => systemPermissionStringToDBType(p as any)); await tx.projectConfig.update({ where: { id: oldProject.config.id }, diff --git a/apps/backend/src/app/api/latest/team-memberships/crud.tsx b/apps/backend/src/app/api/latest/team-memberships/crud.tsx index 113d4368f..c7bf15a4f 100644 --- a/apps/backend/src/app/api/latest/team-memberships/crud.tsx +++ b/apps/backend/src/app/api/latest/team-memberships/crud.tsx @@ -1,4 +1,4 @@ -import { isTeamSystemPermission, teamSystemPermissionStringToDBType } from "@/lib/permissions"; +import { isTeamSystemPermission, systemPermissionStringToDBType } from "@/lib/permissions"; import { ensureTeamExists, ensureTeamMembershipDoesNotExist, ensureTeamMembershipExists, ensureUserExists, ensureUserTeamPermissionExists } from "@/lib/request-checks"; import { Tenancy } from "@/lib/tenancies"; import { PrismaTransaction } from "@/lib/types"; @@ -30,7 +30,7 @@ export async function addUserToTeam(tx: PrismaTransaction, options: { create: options.tenancy.config[permissionAttributeName].map((p) => { if (isTeamSystemPermission(p.id)) { return { - systemPermission: teamSystemPermissionStringToDBType(p.id), + systemPermission: systemPermissionStringToDBType(p.id), }; } else { return { diff --git a/apps/backend/src/lib/config.tsx b/apps/backend/src/lib/config.tsx index aea1cf728..7768859d3 100644 --- a/apps/backend/src/lib/config.tsx +++ b/apps/backend/src/lib/config.tsx @@ -11,6 +11,7 @@ import { stringCompare, typedToLowercase } from "@stackframe/stack-shared/dist/u import { generateUuid } from "@stackframe/stack-shared/dist/utils/uuids"; import * as yup from "yup"; import { RawQuery, prismaClient } from "../prisma-client"; +import { systemPermissionDBTypeToString } from "./permissions"; import { DBProject, fullProjectInclude } from "./projects"; // These are placeholder types that should be replaced after the config json db migration @@ -201,7 +202,9 @@ export async function getEnvironmentConfigOverride(options: EnvironmentOptions): configOverride['auth.otp.allowSignIn'] = true; } } else if (authMethodConfig.passkeyConfig) { - configOverride['auth.passkey.allowSignIn'] = true; + if (authMethodConfig.enabled) { + configOverride['auth.passkey.allowSignIn'] = true; + } } else { throw new StackAssertionError('Unknown auth method config', { authMethodConfig }); } @@ -293,11 +296,11 @@ export async function getEnvironmentConfigOverride(options: EnvironmentOptions): configOverride['rbac.defaultPermissions'] = { teamCreator: typedFromEntries([ ...oldConfig.permissions.filter(perm => perm.isDefaultTeamCreatorPermission).map(perm => perm.queryableId), - ...oldConfig.teamCreateDefaultSystemPermissions, + ...oldConfig.teamCreateDefaultSystemPermissions.map(perm => systemPermissionDBTypeToString(perm)), ].map((id) => [id, true])), teamMember: typedFromEntries([ ...oldConfig.permissions.filter(perm => perm.isDefaultTeamMemberPermission).map(perm => perm.queryableId), - ...oldConfig.teamMemberDefaultSystemPermissions, + ...oldConfig.teamMemberDefaultSystemPermissions.map(perm => systemPermissionDBTypeToString(perm)), ].map((id) => [id, true])), signUp: typedFromEntries([ ...oldConfig.permissions.filter(perm => perm.isDefaultProjectPermission).map(perm => perm.queryableId), @@ -316,7 +319,12 @@ export async function getEnvironmentConfigOverride(options: EnvironmentOptions): environmentConfigOverride: configOverride, }); if (validationResult.status === 'error') { - throw new StackAssertionError('getEnvironmentConfigOverride returned an invalid config override: ' + validationResult.error, { validationResult }); + throw new StackAssertionError('getEnvironmentConfigOverride returned an invalid config override: ' + validationResult.error, { + validationResult, + project: options.project, + branch: options.branch, + environmentConfigOverride: configOverride, + }); } return configOverride; diff --git a/apps/backend/src/lib/permissions.tsx b/apps/backend/src/lib/permissions.tsx index 83dd0eda5..367f251c9 100644 --- a/apps/backend/src/lib/permissions.tsx +++ b/apps/backend/src/lib/permissions.tsx @@ -21,15 +21,15 @@ export function isTeamSystemPermission(permission: string): permission is `$${Lo return permission.startsWith('$') && permission.slice(1).toUpperCase() in DBTeamSystemPermission; } -export function teamSystemPermissionStringToDBType(permission: `$${Lowercase}`): DBTeamSystemPermission { +export function systemPermissionStringToDBType(permission: `$${Lowercase}`): DBTeamSystemPermission { return typedToUppercase(permission.slice(1)) as DBTeamSystemPermission; } -export function teamDBTypeToSystemPermissionString(permission: DBTeamSystemPermission): `$${Lowercase}` { +export function systemPermissionDBTypeToString(permission: DBTeamSystemPermission): `$${Lowercase}` { return '$' + typedToLowercase(permission) as `$${Lowercase}`; } -export type TeamSystemPermission = ReturnType; +export type TeamSystemPermission = ReturnType; const descriptionMap: Record = { "UPDATE_TEAM": "Update the team information", @@ -147,7 +147,7 @@ export async function listUserTeamPermissions( const [userId, teamId] = JSON.parse(compositeKey) as [string, string]; const idsToProcess = [...userTeamResults.map(p => p.permission?.queryableId || - (p.systemPermission ? teamDBTypeToSystemPermissionString(p.systemPermission) : null) || + (p.systemPermission ? systemPermissionDBTypeToString(p.systemPermission) : null) || throwErr(new StackAssertionError(`Permission should have either queryableId or systemPermission`, { p })) )]; @@ -191,11 +191,11 @@ export async function grantTeamPermission( tenancyId: options.tenancy.id, projectUserId: options.userId, teamId: options.teamId, - systemPermission: teamSystemPermissionStringToDBType(options.permissionId), + systemPermission: systemPermissionStringToDBType(options.permissionId), }, }, create: { - systemPermission: teamSystemPermissionStringToDBType(options.permissionId), + systemPermission: systemPermissionStringToDBType(options.permissionId), teamMember: { connect: { tenancyId_projectUserId_teamId: { @@ -282,7 +282,7 @@ export async function revokeTeamPermission( tenancyId: options.tenancy.id, projectUserId: options.userId, teamId: options.teamId, - systemPermission: teamSystemPermissionStringToDBType(options.permissionId), + systemPermission: systemPermissionStringToDBType(options.permissionId), }, }, }); @@ -390,7 +390,7 @@ export async function createPermissionDefinition( create: parentDbIds.map(parentDbId => { if (isTeamSystemPermission(parentDbId)) { return { - parentTeamSystemPermission: teamSystemPermissionStringToDBType(parentDbId), + parentTeamSystemPermission: systemPermissionStringToDBType(parentDbId), }; } else { return { @@ -436,7 +436,7 @@ export async function updatePermissionDefinitions( create: parentDbIds.map(parentDbId => { if (isTeamSystemPermission(parentDbId)) { return { - parentTeamSystemPermission: teamSystemPermissionStringToDBType(parentDbId), + parentTeamSystemPermission: systemPermissionStringToDBType(parentDbId), }; } else { return { diff --git a/apps/backend/src/lib/projects.tsx b/apps/backend/src/lib/projects.tsx index 5cd72909e..460071d8d 100644 --- a/apps/backend/src/lib/projects.tsx +++ b/apps/backend/src/lib/projects.tsx @@ -416,7 +416,7 @@ export function getProjectQuery(projectId: string): RawQuery new Date(a.createdAt + "Z").getTime() - new Date(b.createdAt + "Z").getTime()) + .sort((a: any, b: any) => stringCompare(a.domain, b.domain)) .map((domain: any) => ({ domain: domain.domain, handler_path: domain.handlerPath,