( input: GrantWorkspaceAccessDirectlyInput )
| 92 | * or upgrade an existing member's permission. |
| 93 | */ |
| 94 | export async function grantWorkspaceAccessDirectly( |
| 95 | input: GrantWorkspaceAccessDirectlyInput |
| 96 | ): Promise<DirectGrantOutcome> { |
| 97 | const normalizedEmail = normalizeEmail(input.email) |
| 98 | |
| 99 | const result = await db.transaction(async (tx): Promise<DirectGrantOutcome> => { |
| 100 | const [existing] = await tx |
| 101 | .select({ id: permissions.id, permissionType: permissions.permissionType }) |
| 102 | .from(permissions) |
| 103 | .where( |
| 104 | and( |
| 105 | eq(permissions.entityId, input.workspaceId), |
| 106 | eq(permissions.entityType, 'workspace'), |
| 107 | eq(permissions.userId, input.userId) |
| 108 | ) |
| 109 | ) |
| 110 | .limit(1) |
| 111 | |
| 112 | if (existing) { |
| 113 | return { outcome: 'unchanged', permission: existing.permissionType as PermissionType } |
| 114 | } |
| 115 | |
| 116 | const inserted = await tx |
| 117 | .insert(permissions) |
| 118 | .values({ |
| 119 | id: generateId(), |
| 120 | entityType: 'workspace', |
| 121 | entityId: input.workspaceId, |
| 122 | userId: input.userId, |
| 123 | permissionType: input.permission, |
| 124 | createdAt: new Date(), |
| 125 | updatedAt: new Date(), |
| 126 | }) |
| 127 | .onConflictDoNothing() |
| 128 | .returning({ id: permissions.id }) |
| 129 | |
| 130 | if (inserted.length === 0) { |
| 131 | return { outcome: 'unchanged', permission: input.permission } |
| 132 | } |
| 133 | |
| 134 | return { outcome: 'added', permission: input.permission } |
| 135 | }) |
| 136 | |
| 137 | if (result.outcome === 'unchanged') { |
| 138 | return result |
| 139 | } |
| 140 | |
| 141 | try { |
| 142 | await supersedePendingWorkspaceInvites(input.workspaceId, normalizedEmail) |
| 143 | } catch (error) { |
| 144 | logger.error('Failed to supersede pending workspace invitations after direct grant', { |
| 145 | workspaceId: input.workspaceId, |
| 146 | error, |
| 147 | }) |
| 148 | } |
| 149 | |
| 150 | try { |
| 151 | const [wsEnvRow] = await db |
no test coverage detected