From fb41f651eca45dd62314609c2f389d5dc683c36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Tue, 11 Oct 2022 12:20:58 +0200 Subject: [PATCH] feat(api): add listing workspace users --- ...mmon-npm-1.39.0-1e36e2ef74-92cfad04a6.zip} | Bin 39729 -> 41393 bytes packages/api/package.json | 2 +- .../Workspace/WorkspaceApiOperations.ts | 1 + .../Workspace/WorkspaceApiService.spec.ts | 56 ++++++++++++++++-- .../Client/Workspace/WorkspaceApiService.ts | 19 +++++- .../Workspace/WorkspaceApiServiceInterface.ts | 6 +- .../WorkspaceInvitationRequestParams.ts | 4 +- .../WorkspaceUserListRequestParams.ts | 6 ++ packages/api/src/Domain/Request/index.ts | 1 + .../Workspace/WorkspaceUserListResponse.ts | 9 +++ .../WorkspaceUserListResponseBody.ts | 5 ++ .../api/src/Domain/Server/Workspace/Paths.ts | 1 + .../Server/Workspace/WorkspaceServer.spec.ts | 19 +++++- .../Server/Workspace/WorkspaceServer.ts | 8 +++ .../Workspace/WorkspaceServerInterface.ts | 3 + packages/encryption/package.json | 2 +- packages/features/package.json | 2 +- packages/filepicker/package.json | 2 +- packages/files/package.json | 2 +- packages/models/package.json | 2 +- .../src/Domain/Api/Workspace/WorkspaceUser.ts | 16 +++++ packages/models/src/Domain/index.ts | 1 + packages/responses/package.json | 2 +- packages/services/package.json | 2 +- .../Workspace/WorkspaceClientInterface.ts | 7 ++- .../src/Domain/Workspace/WorkspaceManager.ts | 20 ++++++- packages/snjs/package.json | 2 +- packages/ui-services/package.json | 2 +- packages/utils/package.json | 2 +- yarn.lock | 30 +++++----- 30 files changed, 190 insertions(+), 44 deletions(-) rename .yarn/cache/{@standardnotes-common-npm-1.36.1-8fadd25f7f-4f2367d461.zip => @standardnotes-common-npm-1.39.0-1e36e2ef74-92cfad04a6.zip} (73%) create mode 100644 packages/api/src/Domain/Request/Workspace/WorkspaceUserListRequestParams.ts create mode 100644 packages/api/src/Domain/Response/Workspace/WorkspaceUserListResponse.ts create mode 100644 packages/api/src/Domain/Response/Workspace/WorkspaceUserListResponseBody.ts create mode 100644 packages/models/src/Domain/Api/Workspace/WorkspaceUser.ts diff --git a/.yarn/cache/@standardnotes-common-npm-1.36.1-8fadd25f7f-4f2367d461.zip b/.yarn/cache/@standardnotes-common-npm-1.39.0-1e36e2ef74-92cfad04a6.zip similarity index 73% rename from .yarn/cache/@standardnotes-common-npm-1.36.1-8fadd25f7f-4f2367d461.zip rename to .yarn/cache/@standardnotes-common-npm-1.39.0-1e36e2ef74-92cfad04a6.zip index b806c765e5a1d82dbe1cb911fd246301b0d5fb32..85ed6ebe6439d2865c76d4c3517480fb97c3b0b7 100644 GIT binary patch delta 4540 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 delta 3462 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 diff --git a/packages/api/package.json b/packages/api/package.json index c97b82550..48609e15f 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -36,7 +36,7 @@ "typescript": "*" }, "dependencies": { - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/encryption": "workspace:*", "@standardnotes/models": "workspace:*", "@standardnotes/responses": "workspace:*", diff --git a/packages/api/src/Domain/Client/Workspace/WorkspaceApiOperations.ts b/packages/api/src/Domain/Client/Workspace/WorkspaceApiOperations.ts index 8f1ff5681..889c0dcab 100644 --- a/packages/api/src/Domain/Client/Workspace/WorkspaceApiOperations.ts +++ b/packages/api/src/Domain/Client/Workspace/WorkspaceApiOperations.ts @@ -3,4 +3,5 @@ export enum WorkspaceApiOperations { Inviting, Accepting, ListingWorkspaces, + ListingWorkspaceUsers, } diff --git a/packages/api/src/Domain/Client/Workspace/WorkspaceApiService.spec.ts b/packages/api/src/Domain/Client/Workspace/WorkspaceApiService.spec.ts index 61edf8f72..d252aa3f8 100644 --- a/packages/api/src/Domain/Client/Workspace/WorkspaceApiService.spec.ts +++ b/packages/api/src/Domain/Client/Workspace/WorkspaceApiService.spec.ts @@ -1,9 +1,10 @@ -import { WorkspaceType } from '@standardnotes/common' +import { WorkspaceAccessLevel, WorkspaceType } from '@standardnotes/common' import { HttpStatusCode } from '../../Http' import { WorkspaceCreationResponse } from '../../Response/Workspace/WorkspaceCreationResponse' import { WorkspaceInvitationAcceptingResponse } from '../../Response/Workspace/WorkspaceInvitationAcceptingResponse' import { WorkspaceInvitationResponse } from '../../Response/Workspace/WorkspaceInvitationResponse' import { WorkspaceListResponse } from '../../Response/Workspace/WorkspaceListResponse' +import { WorkspaceUserListResponse } from '../../Response/Workspace/WorkspaceUserListResponse' import { WorkspaceServerInterface } from '../../Server/Workspace/WorkspaceServerInterface' import { WorkspaceApiOperations } from './WorkspaceApiOperations' @@ -29,6 +30,10 @@ describe('WorkspaceApiService', () => { status: HttpStatusCode.Success, data: { ownedWorkspaces: [], joinedWorkspaces: [] }, } as jest.Mocked) + workspaceServer.listWorkspaceUsers = jest.fn().mockReturnValue({ + status: HttpStatusCode.Success, + data: { users: [] }, + } as jest.Mocked) }) it('should create a workspace', async () => { @@ -97,7 +102,7 @@ describe('WorkspaceApiService', () => { const response = await createService().inviteToWorkspace({ workspaceUuid: 'w-1-2-3', inviteeEmail: 'test@test.te', - accessLevel: 'write-and-read', + accessLevel: WorkspaceAccessLevel.WriteAndRead, }) expect(response).toEqual({ @@ -123,7 +128,7 @@ describe('WorkspaceApiService', () => { await service.inviteToWorkspace({ workspaceUuid: 'w-1-2-3', inviteeEmail: 'test@test.te', - accessLevel: 'write-and-read', + accessLevel: WorkspaceAccessLevel.WriteAndRead, }) } catch (caughtError) { error = caughtError @@ -142,7 +147,7 @@ describe('WorkspaceApiService', () => { await createService().inviteToWorkspace({ workspaceUuid: 'w-1-2-3', inviteeEmail: 'test@test.te', - accessLevel: 'write-and-read', + accessLevel: WorkspaceAccessLevel.WriteAndRead, }) } catch (caughtError) { error = caughtError @@ -256,4 +261,47 @@ describe('WorkspaceApiService', () => { expect(error).not.toBeNull() }) + + it('should list workspace users', async () => { + const response = await createService().listWorkspaceUsers({ workspaceUuid: 'w-1-2-3' }) + + expect(response).toEqual({ + status: 200, + data: { + users: [], + }, + }) + expect(workspaceServer.listWorkspaceUsers).toHaveBeenCalledWith({ workspaceUuid: 'w-1-2-3' }) + }) + + it('should not list workspace users if it is already listing them', async () => { + const service = createService() + Object.defineProperty(service, 'operationsInProgress', { + get: () => new Map([[WorkspaceApiOperations.ListingWorkspaceUsers, true]]), + }) + + let error = null + try { + await service.listWorkspaceUsers({ workspaceUuid: 'w-1-2-3' }) + } catch (caughtError) { + error = caughtError + } + + expect(error).not.toBeNull() + }) + + it('should not list workspace users if the server fails', async () => { + workspaceServer.listWorkspaceUsers = jest.fn().mockImplementation(() => { + throw new Error('Oops') + }) + + let error = null + try { + await createService().listWorkspaceUsers({ workspaceUuid: 'w-1-2-3' }) + } catch (caughtError) { + error = caughtError + } + + expect(error).not.toBeNull() + }) }) diff --git a/packages/api/src/Domain/Client/Workspace/WorkspaceApiService.ts b/packages/api/src/Domain/Client/Workspace/WorkspaceApiService.ts index 741cfdf0e..41099857b 100644 --- a/packages/api/src/Domain/Client/Workspace/WorkspaceApiService.ts +++ b/packages/api/src/Domain/Client/Workspace/WorkspaceApiService.ts @@ -1,4 +1,4 @@ -import { Uuid, WorkspaceType } from '@standardnotes/common' +import { Uuid, WorkspaceAccessLevel, WorkspaceType } from '@standardnotes/common' import { ErrorMessage } from '../../Error/ErrorMessage' import { ApiCallError } from '../../Error/ApiCallError' @@ -7,6 +7,7 @@ import { WorkspaceInvitationAcceptingResponse } from '../../Response/Workspace/W import { WorkspaceInvitationResponse } from '../../Response/Workspace/WorkspaceInvitationResponse' import { WorkspaceServerInterface } from '../../Server/Workspace/WorkspaceServerInterface' import { WorkspaceListResponse } from '../../Response/Workspace/WorkspaceListResponse' +import { WorkspaceUserListResponse } from '../../Response/Workspace/WorkspaceUserListResponse' import { WorkspaceApiServiceInterface } from './WorkspaceApiServiceInterface' import { WorkspaceApiOperations } from './WorkspaceApiOperations' @@ -18,6 +19,20 @@ export class WorkspaceApiService implements WorkspaceApiServiceInterface { this.operationsInProgress = new Map() } + async listWorkspaceUsers(dto: { workspaceUuid: string }): Promise { + this.lockOperation(WorkspaceApiOperations.ListingWorkspaceUsers) + + try { + const response = await this.workspaceServer.listWorkspaceUsers({ workspaceUuid: dto.workspaceUuid }) + + this.unlockOperation(WorkspaceApiOperations.ListingWorkspaceUsers) + + return response + } catch (error) { + throw new ApiCallError(ErrorMessage.GenericFail) + } + } + async listWorkspaces(): Promise { this.lockOperation(WorkspaceApiOperations.ListingWorkspaces) @@ -59,7 +74,7 @@ export class WorkspaceApiService implements WorkspaceApiServiceInterface { async inviteToWorkspace(dto: { inviteeEmail: string workspaceUuid: Uuid - accessLevel: string + accessLevel: WorkspaceAccessLevel }): Promise { this.lockOperation(WorkspaceApiOperations.Inviting) diff --git a/packages/api/src/Domain/Client/Workspace/WorkspaceApiServiceInterface.ts b/packages/api/src/Domain/Client/Workspace/WorkspaceApiServiceInterface.ts index 1b6fe08b7..c949ca6a1 100644 --- a/packages/api/src/Domain/Client/Workspace/WorkspaceApiServiceInterface.ts +++ b/packages/api/src/Domain/Client/Workspace/WorkspaceApiServiceInterface.ts @@ -1,9 +1,10 @@ -import { Uuid, WorkspaceType } from '@standardnotes/common' +import { Uuid, WorkspaceAccessLevel, WorkspaceType } from '@standardnotes/common' import { WorkspaceCreationResponse } from '../../Response/Workspace/WorkspaceCreationResponse' import { WorkspaceInvitationAcceptingResponse } from '../../Response/Workspace/WorkspaceInvitationAcceptingResponse' import { WorkspaceInvitationResponse } from '../../Response/Workspace/WorkspaceInvitationResponse' import { WorkspaceListResponse } from '../../Response/Workspace/WorkspaceListResponse' +import { WorkspaceUserListResponse } from '../../Response/Workspace/WorkspaceUserListResponse' export interface WorkspaceApiServiceInterface { createWorkspace(dto: { @@ -16,7 +17,7 @@ export interface WorkspaceApiServiceInterface { inviteToWorkspace(dto: { inviteeEmail: string workspaceUuid: Uuid - accessLevel: string + accessLevel: WorkspaceAccessLevel }): Promise acceptInvite(dto: { inviteUuid: Uuid @@ -25,4 +26,5 @@ export interface WorkspaceApiServiceInterface { encryptedPrivateKey: string }): Promise listWorkspaces(): Promise + listWorkspaceUsers(dto: { workspaceUuid: Uuid }): Promise } diff --git a/packages/api/src/Domain/Request/Workspace/WorkspaceInvitationRequestParams.ts b/packages/api/src/Domain/Request/Workspace/WorkspaceInvitationRequestParams.ts index 2c198faa6..3f9cdced3 100644 --- a/packages/api/src/Domain/Request/Workspace/WorkspaceInvitationRequestParams.ts +++ b/packages/api/src/Domain/Request/Workspace/WorkspaceInvitationRequestParams.ts @@ -1,8 +1,8 @@ -import { Uuid } from '@standardnotes/common' +import { Uuid, WorkspaceAccessLevel } from '@standardnotes/common' export type WorkspaceInvitationRequestParams = { workspaceUuid: Uuid inviteeEmail: string - accessLevel: string + accessLevel: WorkspaceAccessLevel [additionalParam: string]: unknown } diff --git a/packages/api/src/Domain/Request/Workspace/WorkspaceUserListRequestParams.ts b/packages/api/src/Domain/Request/Workspace/WorkspaceUserListRequestParams.ts new file mode 100644 index 000000000..cef93740d --- /dev/null +++ b/packages/api/src/Domain/Request/Workspace/WorkspaceUserListRequestParams.ts @@ -0,0 +1,6 @@ +import { Uuid } from '@standardnotes/common' + +export type WorkspaceUserListRequestParams = { + workspaceUuid: Uuid + [additionalParam: string]: unknown +} diff --git a/packages/api/src/Domain/Request/index.ts b/packages/api/src/Domain/Request/index.ts index 6819f74c2..b0e53a01a 100644 --- a/packages/api/src/Domain/Request/index.ts +++ b/packages/api/src/Domain/Request/index.ts @@ -10,3 +10,4 @@ export * from './Workspace/WorkspaceCreationRequestParams' export * from './Workspace/WorkspaceInvitationAcceptingRequestParams' export * from './Workspace/WorkspaceInvitationRequestParams' export * from './Workspace/WorkspaceListRequestParams' +export * from './Workspace/WorkspaceUserListRequestParams' diff --git a/packages/api/src/Domain/Response/Workspace/WorkspaceUserListResponse.ts b/packages/api/src/Domain/Response/Workspace/WorkspaceUserListResponse.ts new file mode 100644 index 000000000..e339a29e0 --- /dev/null +++ b/packages/api/src/Domain/Response/Workspace/WorkspaceUserListResponse.ts @@ -0,0 +1,9 @@ +import { Either } from '@standardnotes/common' + +import { HttpErrorResponseBody } from '../../Http/HttpErrorResponseBody' +import { HttpResponse } from '../../Http/HttpResponse' +import { WorkspaceUserListResponseBody } from './WorkspaceUserListResponseBody' + +export interface WorkspaceUserListResponse extends HttpResponse { + data: Either +} diff --git a/packages/api/src/Domain/Response/Workspace/WorkspaceUserListResponseBody.ts b/packages/api/src/Domain/Response/Workspace/WorkspaceUserListResponseBody.ts new file mode 100644 index 000000000..c2c810204 --- /dev/null +++ b/packages/api/src/Domain/Response/Workspace/WorkspaceUserListResponseBody.ts @@ -0,0 +1,5 @@ +import { WorkspaceUser } from '@standardnotes/models' + +export type WorkspaceUserListResponseBody = { + users: Array +} diff --git a/packages/api/src/Domain/Server/Workspace/Paths.ts b/packages/api/src/Domain/Server/Workspace/Paths.ts index 1da981566..59abb55f6 100644 --- a/packages/api/src/Domain/Server/Workspace/Paths.ts +++ b/packages/api/src/Domain/Server/Workspace/Paths.ts @@ -3,6 +3,7 @@ import { Uuid } from '@standardnotes/common' const WorkspacePaths = { createWorkspace: '/v1/workspaces', listWorkspaces: '/v1/workspaces', + listWorkspaceUsers: (uuid: Uuid) => `/v1/workspaces/${uuid}/users`, inviteToWorkspace: (uuid: Uuid) => `/v1/workspaces/${uuid}/invites`, acceptInvite: (uuid: Uuid) => `/v1/invites/${uuid}/accept`, } diff --git a/packages/api/src/Domain/Server/Workspace/WorkspaceServer.spec.ts b/packages/api/src/Domain/Server/Workspace/WorkspaceServer.spec.ts index b46abc49d..0340a5891 100644 --- a/packages/api/src/Domain/Server/Workspace/WorkspaceServer.spec.ts +++ b/packages/api/src/Domain/Server/Workspace/WorkspaceServer.spec.ts @@ -1,9 +1,10 @@ -import { WorkspaceType } from '@standardnotes/common' +import { WorkspaceAccessLevel, WorkspaceType } from '@standardnotes/common' import { HttpServiceInterface, HttpStatusCode } from '../../Http' import { WorkspaceCreationResponse } from '../../Response/Workspace/WorkspaceCreationResponse' import { WorkspaceInvitationAcceptingResponse } from '../../Response/Workspace/WorkspaceInvitationAcceptingResponse' import { WorkspaceInvitationResponse } from '../../Response/Workspace/WorkspaceInvitationResponse' import { WorkspaceListResponse } from '../../Response/Workspace/WorkspaceListResponse' +import { WorkspaceUserListResponse } from '../../Response/Workspace/WorkspaceUserListResponse' import { WorkspaceServer } from './WorkspaceServer' @@ -42,7 +43,7 @@ describe('WorkspaceServer', () => { const response = await createServer().inviteToWorkspace({ inviteeEmail: 'test@test.te', workspaceUuid: 'w-1-2-3', - accessLevel: 'write-and-read', + accessLevel: WorkspaceAccessLevel.WriteAndRead, }) expect(response).toEqual({ @@ -84,4 +85,18 @@ describe('WorkspaceServer', () => { data: { ownedWorkspaces: [], joinedWorkspaces: [] }, }) }) + + it('should list workspace users', async () => { + httpService.get = jest.fn().mockReturnValue({ + status: HttpStatusCode.Success, + data: { users: [] }, + } as jest.Mocked) + + const response = await createServer().listWorkspaceUsers({ workspaceUuid: 'w-1-2-3' }) + + expect(response).toEqual({ + status: 200, + data: { users: [] }, + }) + }) }) diff --git a/packages/api/src/Domain/Server/Workspace/WorkspaceServer.ts b/packages/api/src/Domain/Server/Workspace/WorkspaceServer.ts index a50ae1add..f82efcc06 100644 --- a/packages/api/src/Domain/Server/Workspace/WorkspaceServer.ts +++ b/packages/api/src/Domain/Server/Workspace/WorkspaceServer.ts @@ -7,6 +7,8 @@ import { WorkspaceInvitationAcceptingRequestParams } from '../../Request/Workspa import { WorkspaceInvitationAcceptingResponse } from '../../Response/Workspace/WorkspaceInvitationAcceptingResponse' import { WorkspaceListRequestParams } from '../../Request/Workspace/WorkspaceListRequestParams' import { WorkspaceListResponse } from '../../Response/Workspace/WorkspaceListResponse' +import { WorkspaceUserListRequestParams } from '../../Request/Workspace/WorkspaceUserListRequestParams' +import { WorkspaceUserListResponse } from '../../Response/Workspace/WorkspaceUserListResponse' import { Paths } from './Paths' import { WorkspaceServerInterface } from './WorkspaceServerInterface' @@ -14,6 +16,12 @@ import { WorkspaceServerInterface } from './WorkspaceServerInterface' export class WorkspaceServer implements WorkspaceServerInterface { constructor(private httpService: HttpServiceInterface) {} + async listWorkspaceUsers(params: WorkspaceUserListRequestParams): Promise { + const response = await this.httpService.get(Paths.v1.listWorkspaceUsers(params.workspaceUuid), params) + + return response as WorkspaceUserListResponse + } + async listWorkspaces(params: WorkspaceListRequestParams): Promise { const response = await this.httpService.get(Paths.v1.listWorkspaces, params) diff --git a/packages/api/src/Domain/Server/Workspace/WorkspaceServerInterface.ts b/packages/api/src/Domain/Server/Workspace/WorkspaceServerInterface.ts index 1cf263b90..342879205 100644 --- a/packages/api/src/Domain/Server/Workspace/WorkspaceServerInterface.ts +++ b/packages/api/src/Domain/Server/Workspace/WorkspaceServerInterface.ts @@ -6,10 +6,13 @@ import { WorkspaceInvitationAcceptingRequestParams } from '../../Request/Workspa import { WorkspaceInvitationAcceptingResponse } from '../../Response/Workspace/WorkspaceInvitationAcceptingResponse' import { WorkspaceListRequestParams } from '../../Request/Workspace/WorkspaceListRequestParams' import { WorkspaceListResponse } from '../../Response/Workspace/WorkspaceListResponse' +import { WorkspaceUserListRequestParams } from '../../Request/Workspace/WorkspaceUserListRequestParams' +import { WorkspaceUserListResponse } from '../../Response/Workspace/WorkspaceUserListResponse' export interface WorkspaceServerInterface { createWorkspace(params: WorkspaceCreationRequestParams): Promise listWorkspaces(params: WorkspaceListRequestParams): Promise + listWorkspaceUsers(params: WorkspaceUserListRequestParams): Promise inviteToWorkspace(params: WorkspaceInvitationRequestParams): Promise acceptInvite(params: WorkspaceInvitationAcceptingRequestParams): Promise } diff --git a/packages/encryption/package.json b/packages/encryption/package.json index 899abb7ce..44a3a33dd 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -35,7 +35,7 @@ "typescript": "*" }, "dependencies": { - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/models": "workspace:*", "@standardnotes/responses": "workspace:*", "@standardnotes/sncrypto-common": "workspace:*", diff --git a/packages/features/package.json b/packages/features/package.json index f1fbc9f15..9003d8d25 100644 --- a/packages/features/package.json +++ b/packages/features/package.json @@ -26,7 +26,7 @@ }, "dependencies": { "@standardnotes/auth": "^3.19.4", - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/security": "^1.2.0", "reflect-metadata": "^0.1.13" }, diff --git a/packages/filepicker/package.json b/packages/filepicker/package.json index a18e11d50..7dd28b709 100644 --- a/packages/filepicker/package.json +++ b/packages/filepicker/package.json @@ -31,7 +31,7 @@ "ts-node": "^10.5.0" }, "dependencies": { - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/files": "workspace:*", "@standardnotes/utils": "workspace:*", "@types/wicg-file-system-access": "^2020.9.5", diff --git a/packages/files/package.json b/packages/files/package.json index ec45cf7c5..19bde9adc 100644 --- a/packages/files/package.json +++ b/packages/files/package.json @@ -30,7 +30,7 @@ "ts-jest": "^28.0.5" }, "dependencies": { - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/encryption": "workspace:*", "@standardnotes/models": "workspace:*", "@standardnotes/responses": "workspace:*", diff --git a/packages/models/package.json b/packages/models/package.json index 75f457b36..c78fc1576 100644 --- a/packages/models/package.json +++ b/packages/models/package.json @@ -31,7 +31,7 @@ "typescript": "*" }, "dependencies": { - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/features": "workspace:*", "@standardnotes/responses": "workspace:*", "@standardnotes/utils": "workspace:*", diff --git a/packages/models/src/Domain/Api/Workspace/WorkspaceUser.ts b/packages/models/src/Domain/Api/Workspace/WorkspaceUser.ts new file mode 100644 index 000000000..16fcb8e5d --- /dev/null +++ b/packages/models/src/Domain/Api/Workspace/WorkspaceUser.ts @@ -0,0 +1,16 @@ +import { Uuid, WorkspaceAccessLevel, WorkspaceUserStatus } from '@standardnotes/common' + +export type WorkspaceUser = { + uuid: Uuid + accessLevel: WorkspaceAccessLevel + userUuid: Uuid + userDisplayName: string | null + workspaceUuid: Uuid + encryptedWorkspaceKey: string | null + publicKey: string | null + encryptedPrivateKey: string | null + status: WorkspaceUserStatus + keyRotationIndex: number + createdAt: number + updatedAt: number +} diff --git a/packages/models/src/Domain/index.ts b/packages/models/src/Domain/index.ts index de83ff3d9..a93856bb6 100644 --- a/packages/models/src/Domain/index.ts +++ b/packages/models/src/Domain/index.ts @@ -29,6 +29,7 @@ export * from './Api/Subscription/InvitationStatus' export * from './Api/Subscription/InviteeIdentifierType' export * from './Api/Subscription/InviterIdentifierType' export * from './Api/Workspace/Workspace' +export * from './Api/Workspace/WorkspaceUser' export * from './Device/Environment' export * from './Device/Platform' export * from './Local/KeyParams/RootKeyParamsInterface' diff --git a/packages/responses/package.json b/packages/responses/package.json index 6432faf7f..04a1bf28d 100644 --- a/packages/responses/package.json +++ b/packages/responses/package.json @@ -31,7 +31,7 @@ "ts-jest": "^28.0.5" }, "dependencies": { - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/features": "workspace:*", "@standardnotes/security": "^1.1.0", "reflect-metadata": "^0.1.13" diff --git a/packages/services/package.json b/packages/services/package.json index 3b89b058c..75071dbe1 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -26,7 +26,7 @@ "dependencies": { "@standardnotes/api": "workspace:^", "@standardnotes/auth": "^3.19.4", - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/encryption": "workspace:^", "@standardnotes/files": "workspace:^", "@standardnotes/models": "workspace:^", diff --git a/packages/services/src/Domain/Workspace/WorkspaceClientInterface.ts b/packages/services/src/Domain/Workspace/WorkspaceClientInterface.ts index 5000d9aa3..f6f86014d 100644 --- a/packages/services/src/Domain/Workspace/WorkspaceClientInterface.ts +++ b/packages/services/src/Domain/Workspace/WorkspaceClientInterface.ts @@ -1,5 +1,5 @@ -import { Uuid, WorkspaceType } from '@standardnotes/common' -import { Workspace } from '@standardnotes/models' +import { Uuid, WorkspaceAccessLevel, WorkspaceType } from '@standardnotes/common' +import { Workspace, WorkspaceUser } from '@standardnotes/models' export interface WorkspaceClientInterface { createWorkspace(dto: { @@ -12,7 +12,7 @@ export interface WorkspaceClientInterface { inviteToWorkspace(dto: { inviteeEmail: string workspaceUuid: Uuid - accessLevel: string + accessLevel: WorkspaceAccessLevel }): Promise<{ uuid: string } | null> acceptInvite(dto: { inviteUuid: Uuid @@ -21,4 +21,5 @@ export interface WorkspaceClientInterface { encryptedPrivateKey: string }): Promise<{ success: boolean }> listWorkspaces(): Promise<{ ownedWorkspaces: Array; joinedWorkspaces: Array }> + listWorkspaceUsers(dto: { workspaceUuid: Uuid }): Promise<{ users: Array }> } diff --git a/packages/services/src/Domain/Workspace/WorkspaceManager.ts b/packages/services/src/Domain/Workspace/WorkspaceManager.ts index baae68710..a62b9dae6 100644 --- a/packages/services/src/Domain/Workspace/WorkspaceManager.ts +++ b/packages/services/src/Domain/Workspace/WorkspaceManager.ts @@ -1,6 +1,6 @@ import { WorkspaceApiServiceInterface } from '@standardnotes/api' -import { Uuid, WorkspaceType } from '@standardnotes/common' -import { Workspace } from '@standardnotes/models' +import { Uuid, WorkspaceAccessLevel, WorkspaceType } from '@standardnotes/common' +import { Workspace, WorkspaceUser } from '@standardnotes/models' import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface' import { AbstractService } from '../Service/AbstractService' @@ -14,6 +14,20 @@ export class WorkspaceManager extends AbstractService implements WorkspaceClient super(internalEventBus) } + async listWorkspaceUsers(dto: { workspaceUuid: string }): Promise<{ users: WorkspaceUser[] }> { + try { + const result = await this.workspaceApiService.listWorkspaceUsers(dto) + + if (result.data.error !== undefined) { + return { users: [] } + } + + return result.data + } catch (error) { + return { users: [] } + } + } + async listWorkspaces(): Promise<{ ownedWorkspaces: Workspace[]; joinedWorkspaces: Workspace[] }> { try { const result = await this.workspaceApiService.listWorkspaces() @@ -50,7 +64,7 @@ export class WorkspaceManager extends AbstractService implements WorkspaceClient async inviteToWorkspace(dto: { inviteeEmail: string workspaceUuid: Uuid - accessLevel: string + accessLevel: WorkspaceAccessLevel }): Promise<{ uuid: string } | null> { try { const result = await this.workspaceApiService.inviteToWorkspace(dto) diff --git a/packages/snjs/package.json b/packages/snjs/package.json index 6eeeef9b7..4211b0922 100644 --- a/packages/snjs/package.json +++ b/packages/snjs/package.json @@ -68,7 +68,7 @@ }, "dependencies": { "@standardnotes/api": "workspace:*", - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/domain-events": "^2.39.0", "@standardnotes/encryption": "workspace:*", "@standardnotes/features": "workspace:*", diff --git a/packages/ui-services/package.json b/packages/ui-services/package.json index a44d1aa57..1ef7267d2 100644 --- a/packages/ui-services/package.json +++ b/packages/ui-services/package.json @@ -23,7 +23,7 @@ "test": "jest spec --coverage --passWithNoTests" }, "dependencies": { - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "@standardnotes/filepicker": "workspace:^", "@standardnotes/services": "workspace:^", "@standardnotes/styles": "workspace:^", diff --git a/packages/utils/package.json b/packages/utils/package.json index 3103d9fe8..cbaae390f 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -25,7 +25,7 @@ "test": "jest spec" }, "dependencies": { - "@standardnotes/common": "^1.36.1", + "@standardnotes/common": "^1.39.0", "dompurify": "^2.3.8", "lodash": "^4.17.21", "reflect-metadata": "^0.1.13" diff --git a/yarn.lock b/yarn.lock index 30c134afe..20953aaf3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6068,7 +6068,7 @@ __metadata: version: 0.0.0-use.local resolution: "@standardnotes/api@workspace:packages/api" dependencies: - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/encryption": "workspace:*" "@standardnotes/models": "workspace:*" "@standardnotes/responses": "workspace:*" @@ -6251,12 +6251,12 @@ __metadata: languageName: node linkType: hard -"@standardnotes/common@npm:^1.36.1": - version: 1.36.1 - resolution: "@standardnotes/common@npm:1.36.1" +"@standardnotes/common@npm:^1.39.0": + version: 1.39.0 + resolution: "@standardnotes/common@npm:1.39.0" dependencies: reflect-metadata: ^0.1.13 - checksum: 4f2367d461aa1cd4e3ec132520310773183c3c9f8e423565aec315f5e5dffdce79f9704307a32fbfec17157f99d37d49982ad4272eee5aac0dbe37da34be054c + checksum: 92cfad04a631cdcf971516be4bf0e066e9cb6e894017102ac406cd8964282e088653ebed282d7624f371d617418edce124d12a62964723697ed7fa33b6d6e4d0 languageName: node linkType: hard @@ -6443,7 +6443,7 @@ __metadata: version: 0.0.0-use.local resolution: "@standardnotes/encryption@workspace:packages/encryption" dependencies: - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/config": 2.4.3 "@standardnotes/models": "workspace:*" "@standardnotes/responses": "workspace:*" @@ -6485,7 +6485,7 @@ __metadata: resolution: "@standardnotes/features@workspace:packages/features" dependencies: "@standardnotes/auth": ^3.19.4 - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/security": ^1.2.0 "@types/jest": ^28.1.5 "@typescript-eslint/eslint-plugin": ^5.30.0 @@ -6501,7 +6501,7 @@ __metadata: version: 0.0.0-use.local resolution: "@standardnotes/filepicker@workspace:packages/filepicker" dependencies: - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/files": "workspace:*" "@standardnotes/utils": "workspace:*" "@types/jest": ^28.1.5 @@ -6519,7 +6519,7 @@ __metadata: version: 0.0.0-use.local resolution: "@standardnotes/files@workspace:packages/files" dependencies: - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/encryption": "workspace:*" "@standardnotes/models": "workspace:*" "@standardnotes/responses": "workspace:*" @@ -6905,7 +6905,7 @@ __metadata: version: 0.0.0-use.local resolution: "@standardnotes/models@workspace:packages/models" dependencies: - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/features": "workspace:*" "@standardnotes/responses": "workspace:*" "@standardnotes/utils": "workspace:*" @@ -6972,7 +6972,7 @@ __metadata: version: 0.0.0-use.local resolution: "@standardnotes/responses@workspace:packages/responses" dependencies: - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/features": "workspace:*" "@standardnotes/security": ^1.1.0 "@types/jest": ^28.1.5 @@ -7041,7 +7041,7 @@ __metadata: dependencies: "@standardnotes/api": "workspace:^" "@standardnotes/auth": ^3.19.4 - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/encryption": "workspace:^" "@standardnotes/files": "workspace:^" "@standardnotes/models": "workspace:^" @@ -7156,7 +7156,7 @@ __metadata: "@babel/core": "*" "@babel/preset-env": "*" "@standardnotes/api": "workspace:*" - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/domain-events": ^2.39.0 "@standardnotes/encryption": "workspace:*" "@standardnotes/features": "workspace:*" @@ -7309,7 +7309,7 @@ __metadata: version: 0.0.0-use.local resolution: "@standardnotes/ui-services@workspace:packages/ui-services" dependencies: - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@standardnotes/filepicker": "workspace:^" "@standardnotes/services": "workspace:^" "@standardnotes/styles": "workspace:^" @@ -7329,7 +7329,7 @@ __metadata: version: 0.0.0-use.local resolution: "@standardnotes/utils@workspace:packages/utils" dependencies: - "@standardnotes/common": ^1.36.1 + "@standardnotes/common": ^1.39.0 "@types/dompurify": ^2.3.3 "@types/jest": ^28.1.5 "@types/jsdom": ^16.2.14