e703bb7415
* feat(workspaces): drop createdByUserId from the dataschema * feat(workspaces): repositories WIP * merge * protect against removing last admin in workspace * quick impl and stub tests * add tests * services * unit tests for role services * fix(workspaces): maybe tests work like this * fix(workspaces): dry * fix(workspaces): initialize tests better * fix(workspaces): so true * fix(workspaces): right * fix(workspaces): self nit * fix(workspaces): better repository structure * fix(workspaces): repair tests, use `example.org` * fix(workspaces): add tests for new repo functions, repair other tests * fix(workspaces): better distinction between service-level guarantees and repo-level guarantees * fix(workspaces): review comments and stencil tests * fix(workspaces): add tests * fix(workspaces): tests work --------- Co-authored-by: Gergő Jedlicska <gergo@jedlicska.com>
105 lines
2.9 KiB
TypeScript
105 lines
2.9 KiB
TypeScript
import { Workspace, WorkspaceAcl } from '@/modules/workspaces/domain/types'
|
|
import {
|
|
DeleteWorkspaceRole,
|
|
GetWorkspace,
|
|
GetWorkspaceRoleForUser,
|
|
GetWorkspaceRoles,
|
|
GetWorkspaceRolesForUser,
|
|
UpsertWorkspace,
|
|
UpsertWorkspaceRole
|
|
} from '@/modules/workspaces/domain/operations'
|
|
import { Knex } from 'knex'
|
|
import { Roles } from '@speckle/shared'
|
|
|
|
const tables = {
|
|
workspaces: (db: Knex) => db<Workspace>('workspaces'),
|
|
workspacesAcl: (db: Knex) => db<WorkspaceAcl>('workspace_acl')
|
|
}
|
|
|
|
export const getWorkspaceFactory =
|
|
({ db }: { db: Knex }): GetWorkspace =>
|
|
async ({ workspaceId }) => {
|
|
const workspace = await tables
|
|
.workspaces(db)
|
|
.select('*')
|
|
.where('id', '=', workspaceId)
|
|
.first()
|
|
|
|
return workspace || null
|
|
}
|
|
|
|
export const upsertWorkspaceFactory =
|
|
({ db }: { db: Knex }): UpsertWorkspace =>
|
|
async ({ workspace }) => {
|
|
await tables
|
|
.workspaces(db)
|
|
.insert(workspace)
|
|
.onConflict('id')
|
|
.merge(['description', 'logoUrl', 'name', 'updatedAt'])
|
|
}
|
|
|
|
export const getWorkspaceRolesFactory =
|
|
({ db }: { db: Knex }): GetWorkspaceRoles =>
|
|
async ({ workspaceId }) => {
|
|
return await tables.workspacesAcl(db).select('*').where({ workspaceId })
|
|
}
|
|
|
|
export const getWorkspaceRoleForUserFactory =
|
|
({ db }: { db: Knex }): GetWorkspaceRoleForUser =>
|
|
async ({ userId, workspaceId }) => {
|
|
return (
|
|
(await tables
|
|
.workspacesAcl(db)
|
|
.select('*')
|
|
.where({ userId, workspaceId })
|
|
.first()) ?? null
|
|
)
|
|
}
|
|
|
|
export const getWorkspaceRolesForUserFactory =
|
|
({ db }: { db: Knex }): GetWorkspaceRolesForUser =>
|
|
async ({ userId }, options) => {
|
|
const workspaceIdFilter = options?.workspaceIdFilter ?? []
|
|
|
|
const query = tables.workspacesAcl(db).select('*').where({ userId })
|
|
|
|
if (workspaceIdFilter.length > 0) {
|
|
query.whereIn('workspaceId', workspaceIdFilter)
|
|
}
|
|
|
|
return await query
|
|
}
|
|
|
|
export const deleteWorkspaceRoleFactory =
|
|
({ db }: { db: Knex }): DeleteWorkspaceRole =>
|
|
async ({ userId, workspaceId }) => {
|
|
const deletedRoles = await tables
|
|
.workspacesAcl(db)
|
|
.where({ workspaceId, userId })
|
|
.delete('*')
|
|
|
|
if (deletedRoles.length === 0) {
|
|
return null
|
|
}
|
|
|
|
// Given `workspaceId` and `userId` define a primary key for `workspace_acl` table,
|
|
// query returns either 0 or 1 row in all cases
|
|
return deletedRoles[0]
|
|
}
|
|
|
|
export const upsertWorkspaceRoleFactory =
|
|
({ db }: { db: Knex }): UpsertWorkspaceRole =>
|
|
async ({ userId, workspaceId, role }) => {
|
|
// Verify requested role is valid workspace role
|
|
const validRoles = Object.values(Roles.Workspace)
|
|
if (!validRoles.includes(role)) {
|
|
throw new Error(`Unexpected workspace role provided: ${role}`)
|
|
}
|
|
|
|
await tables
|
|
.workspacesAcl(db)
|
|
.insert({ userId, workspaceId, role })
|
|
.onConflict(['userId', 'workspaceId'])
|
|
.merge(['role'])
|
|
}
|