-
Notifications
You must be signed in to change notification settings - Fork 181
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WEB-1140 manage user workspace membership services (#2460)
* 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 <[email protected]>
- Loading branch information
1 parent
a72ef61
commit e703bb7
Showing
10 changed files
with
590 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { BaseError } from '@/modules/shared/errors/base' | ||
|
||
export class WorkspaceAdminRequiredError extends BaseError { | ||
static defaultMessage = 'Cannot remove last admin from a workspace' | ||
static code = 'WORKSPACE_ADMIN_REQUIRED_ERROR' | ||
static statusCode = 400 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
packages/server/modules/workspaces/services/workspaceRoleCreation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { | ||
DeleteWorkspaceRole, | ||
EmitWorkspaceEvent, | ||
GetWorkspaceRoleForUser, | ||
GetWorkspaceRoles, | ||
UpsertWorkspaceRole | ||
} from '@/modules/workspaces/domain/operations' | ||
import { WorkspaceAcl } from '@/modules/workspaces/domain/types' | ||
import { WorkspaceAdminRequiredError } from '@/modules/workspaces/errors/workspace' | ||
import { isUserLastWorkspaceAdmin } from '@/modules/workspaces/utils/isUserLastWorkspaceAdmin' | ||
import { WorkspaceEvents } from '@/modules/workspacesCore/domain/events' | ||
|
||
type WorkspaceRoleDeleteArgs = { | ||
userId: string | ||
workspaceId: string | ||
} | ||
|
||
export const deleteWorkspaceRoleFactory = | ||
({ | ||
getWorkspaceRoles, | ||
deleteWorkspaceRole, | ||
emitWorkspaceEvent | ||
}: { | ||
getWorkspaceRoles: GetWorkspaceRoles | ||
deleteWorkspaceRole: DeleteWorkspaceRole | ||
emitWorkspaceEvent: EmitWorkspaceEvent | ||
}) => | ||
async ({ | ||
userId, | ||
workspaceId | ||
}: WorkspaceRoleDeleteArgs): Promise<WorkspaceAcl | null> => { | ||
const workspaceRoles = await getWorkspaceRoles({ workspaceId }) | ||
|
||
if (isUserLastWorkspaceAdmin(workspaceRoles, userId)) { | ||
throw new WorkspaceAdminRequiredError() | ||
} | ||
|
||
const deletedRole = await deleteWorkspaceRole({ userId, workspaceId }) | ||
|
||
if (!deletedRole) { | ||
return null | ||
} | ||
|
||
emitWorkspaceEvent({ event: WorkspaceEvents.RoleDeleted, payload: deletedRole }) | ||
|
||
return deletedRole | ||
} | ||
|
||
type WorkspaceRoleGetArgs = { | ||
userId: string | ||
workspaceId: string | ||
} | ||
|
||
export const getWorkspaceRoleFactory = | ||
({ getWorkspaceRoleForUser }: { getWorkspaceRoleForUser: GetWorkspaceRoleForUser }) => | ||
async ({ | ||
userId, | ||
workspaceId | ||
}: WorkspaceRoleGetArgs): Promise<WorkspaceAcl | null> => { | ||
return await getWorkspaceRoleForUser({ userId, workspaceId }) | ||
} | ||
|
||
export const setWorkspaceRoleFactory = | ||
({ | ||
getWorkspaceRoles, | ||
upsertWorkspaceRole, | ||
emitWorkspaceEvent | ||
}: { | ||
getWorkspaceRoles: GetWorkspaceRoles | ||
upsertWorkspaceRole: UpsertWorkspaceRole | ||
emitWorkspaceEvent: EmitWorkspaceEvent | ||
}) => | ||
async ({ userId, workspaceId, role }: WorkspaceAcl): Promise<void> => { | ||
const workspaceRoles = await getWorkspaceRoles({ workspaceId }) | ||
|
||
if ( | ||
isUserLastWorkspaceAdmin(workspaceRoles, userId) && | ||
role !== 'workspace:admin' | ||
) { | ||
throw new WorkspaceAdminRequiredError() | ||
} | ||
|
||
await upsertWorkspaceRole({ userId, workspaceId, role }) | ||
|
||
await emitWorkspaceEvent({ | ||
event: WorkspaceEvents.RoleUpdated, | ||
payload: { userId, workspaceId, role } | ||
}) | ||
} |
Oops, something went wrong.