diff --git a/packages/api/src/Domain/Client/Subscription/SubscriptionApiOperations.ts b/packages/api/src/Domain/Client/Subscription/SubscriptionApiOperations.ts index 81c3c5cb6..5ec3c1ffe 100644 --- a/packages/api/src/Domain/Client/Subscription/SubscriptionApiOperations.ts +++ b/packages/api/src/Domain/Client/Subscription/SubscriptionApiOperations.ts @@ -2,4 +2,5 @@ export enum SubscriptionApiOperations { Inviting, CancelingInvite, ListingInvites, + AcceptingInvite, } diff --git a/packages/api/src/Domain/Client/Subscription/SubscriptionApiService.spec.ts b/packages/api/src/Domain/Client/Subscription/SubscriptionApiService.spec.ts index 82a718bef..08127ec27 100644 --- a/packages/api/src/Domain/Client/Subscription/SubscriptionApiService.spec.ts +++ b/packages/api/src/Domain/Client/Subscription/SubscriptionApiService.spec.ts @@ -1,5 +1,6 @@ import { Invitation } from '@standardnotes/models' +import { SubscriptionInviteAcceptResponse } from '../../Response/Subscription/SubscriptionInviteAcceptResponse' import { SubscriptionInviteCancelResponse } from '../../Response/Subscription/SubscriptionInviteCancelResponse' import { SubscriptionInviteListResponse } from '../../Response/Subscription/SubscriptionInviteListResponse' import { SubscriptionInviteResponse } from '../../Response/Subscription/SubscriptionInviteResponse' @@ -24,6 +25,9 @@ describe('SubscriptionApiService', () => { subscriptionServer.listInvites = jest.fn().mockReturnValue({ data: { invitations: [{} as jest.Mocked] }, } as jest.Mocked) + subscriptionServer.acceptInvite = jest.fn().mockReturnValue({ + data: { success: true }, + } as jest.Mocked) }) it('should invite a user', async () => { @@ -160,4 +164,48 @@ describe('SubscriptionApiService', () => { expect(error).not.toBeNull() }) + + it('should accept an invite', async () => { + const response = await createService().acceptInvite('1-2-3') + + expect(response).toEqual({ + data: { + success: true, + }, + }) + expect(subscriptionServer.acceptInvite).toHaveBeenCalledWith({ + inviteUuid: '1-2-3', + }) + }) + + it('should not accept an invite if it is already accepting', async () => { + const service = createService() + Object.defineProperty(service, 'operationsInProgress', { + get: () => new Map([[SubscriptionApiOperations.AcceptingInvite, true]]), + }) + + let error = null + try { + await service.acceptInvite('1-2-3') + } catch (caughtError) { + error = caughtError + } + + expect(error).not.toBeNull() + }) + + it('should not accept an invite if the server fails', async () => { + subscriptionServer.acceptInvite = jest.fn().mockImplementation(() => { + throw new Error('Oops') + }) + + let error = null + try { + await createService().acceptInvite('1-2-3') + } catch (caughtError) { + error = caughtError + } + + expect(error).not.toBeNull() + }) }) diff --git a/packages/api/src/Domain/Client/Subscription/SubscriptionApiService.ts b/packages/api/src/Domain/Client/Subscription/SubscriptionApiService.ts index 8e48970f7..4a71cec1e 100644 --- a/packages/api/src/Domain/Client/Subscription/SubscriptionApiService.ts +++ b/packages/api/src/Domain/Client/Subscription/SubscriptionApiService.ts @@ -6,9 +6,11 @@ import { SubscriptionServerInterface } from '../../Server/Subscription/Subscript import { SubscriptionInviteResponse } from '../../Response/Subscription/SubscriptionInviteResponse' import { SubscriptionInviteListResponse } from '../../Response/Subscription/SubscriptionInviteListResponse' import { SubscriptionInviteCancelResponse } from '../../Response/Subscription/SubscriptionInviteCancelResponse' +import { SubscriptionInviteAcceptResponse } from '../../Response/Subscription/SubscriptionInviteAcceptResponse' import { SubscriptionApiServiceInterface } from './SubscriptionApiServiceInterface' import { SubscriptionApiOperations } from './SubscriptionApiOperations' +import { Uuid } from '@standardnotes/common' export class SubscriptionApiService implements SubscriptionApiServiceInterface { private operationsInProgress: Map @@ -78,4 +80,24 @@ export class SubscriptionApiService implements SubscriptionApiServiceInterface { throw new ApiCallError(ErrorMessage.GenericFail) } } + + async acceptInvite(inviteUuid: Uuid): Promise { + if (this.operationsInProgress.get(SubscriptionApiOperations.AcceptingInvite)) { + throw new ApiCallError(ErrorMessage.GenericInProgress) + } + + this.operationsInProgress.set(SubscriptionApiOperations.AcceptingInvite, true) + + try { + const response = await this.subscriptionServer.acceptInvite({ + inviteUuid, + }) + + this.operationsInProgress.set(SubscriptionApiOperations.AcceptingInvite, false) + + return response + } catch (error) { + throw new ApiCallError(ErrorMessage.GenericFail) + } + } } diff --git a/packages/api/src/Domain/Client/Subscription/SubscriptionApiServiceInterface.ts b/packages/api/src/Domain/Client/Subscription/SubscriptionApiServiceInterface.ts index e65c2a02f..e3e14875d 100644 --- a/packages/api/src/Domain/Client/Subscription/SubscriptionApiServiceInterface.ts +++ b/packages/api/src/Domain/Client/Subscription/SubscriptionApiServiceInterface.ts @@ -1,5 +1,6 @@ import { Uuid } from '@standardnotes/common' +import { SubscriptionInviteAcceptResponse } from '../../Response/Subscription/SubscriptionInviteAcceptResponse' import { SubscriptionInviteCancelResponse } from '../../Response/Subscription/SubscriptionInviteCancelResponse' import { SubscriptionInviteListResponse } from '../../Response/Subscription/SubscriptionInviteListResponse' import { SubscriptionInviteResponse } from '../../Response/Subscription/SubscriptionInviteResponse' @@ -8,4 +9,5 @@ export interface SubscriptionApiServiceInterface { invite(inviteeEmail: string): Promise listInvites(): Promise cancelInvite(inviteUuid: Uuid): Promise + acceptInvite(inviteUuid: Uuid): Promise } diff --git a/packages/api/src/Domain/Request/Subscription/SubscriptionInviteAcceptRequestParams.ts b/packages/api/src/Domain/Request/Subscription/SubscriptionInviteAcceptRequestParams.ts index 975efc490..c72da5b6b 100644 --- a/packages/api/src/Domain/Request/Subscription/SubscriptionInviteAcceptRequestParams.ts +++ b/packages/api/src/Domain/Request/Subscription/SubscriptionInviteAcceptRequestParams.ts @@ -1,10 +1,6 @@ import { Uuid } from '@standardnotes/common' -import { ApiEndpointParam } from '../ApiEndpointParam' -import { ApiVersion } from '../../Api/ApiVersion' - export type SubscriptionInviteAcceptRequestParams = { - [ApiEndpointParam.ApiVersion]: ApiVersion.v0 inviteUuid: Uuid [additionalParam: string]: unknown } diff --git a/packages/api/src/Domain/Response/Subscription/SubscriptionInviteAcceptResponseBody.ts b/packages/api/src/Domain/Response/Subscription/SubscriptionInviteAcceptResponseBody.ts index 9635a4aec..e5a976440 100644 --- a/packages/api/src/Domain/Response/Subscription/SubscriptionInviteAcceptResponseBody.ts +++ b/packages/api/src/Domain/Response/Subscription/SubscriptionInviteAcceptResponseBody.ts @@ -1,3 +1,3 @@ -export type SubscriptionInviteAcceptResponseBody = { - success: boolean -} +import { Either } from '@standardnotes/common' + +export type SubscriptionInviteAcceptResponseBody = Either<{ success: true }, { success: false; message: string }>