Skip to content

Commit

Permalink
feat: add subscription manager to handle subscription sharing (#1517)
Browse files Browse the repository at this point in the history
* feat: add subscription manager to handle subscription sharing

* fix(services): add missing methods to the interface

* fix(services): add subscription manager specs

* feat(snjs): add subscriptions e2e tests

* fix(snjs): add wait in subscription cancelling test

* fix(snjs): checking for canceled invitations in tests

* fix(snjs): add e2e test for restored limit of subscription invitations

* chore(lint): fix linter issues
  • Loading branch information
Karol Sójko committed Sep 13, 2022
1 parent 2b830c0 commit 55b1409
Show file tree
Hide file tree
Showing 55 changed files with 512 additions and 91 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"build:mobile": "yarn workspaces foreach -pt --verbose -R --from @standardnotes/mobile --exclude @standardnotes/components-meta run build",
"build:snjs": "yarn workspaces foreach -pt --verbose -R --from @standardnotes/snjs --exclude @standardnotes/components-meta run build",
"build:services": "yarn workspaces foreach -pt --verbose -R --from @standardnotes/services --exclude @standardnotes/components-meta run build",
"build:api": "yarn workspaces foreach -pt --verbose -R --from @standardnotes/api --exclude @standardnotes/components-meta run build",
"start:server:web": "lerna run start --scope=@standardnotes/web",
"start:server:e2e": "lerna run start:test-server --scope=@standardnotes/snjs",
"prepare": "husky install",
Expand Down
3 changes: 1 addition & 2 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,11 @@
"ts-jest": "^28.0.5"
},
"dependencies": {
"@standardnotes/common": "^1.23.1",
"@standardnotes/common": "^1.32.0",
"@standardnotes/encryption": "workspace:*",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/security": "^1.1.0",
"@standardnotes/services": "workspace:*",
"@standardnotes/utils": "workspace:*",
"reflect-metadata": "^0.1.13"
}
Expand Down
13 changes: 12 additions & 1 deletion packages/api/src/Domain/Http/HttpService.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Environment } from '@standardnotes/services'
import { Environment } from '@standardnotes/models'

import { HttpResponseMeta } from './HttpResponseMeta'
import { HttpService } from './HttpService'

Expand All @@ -24,4 +25,14 @@ describe('HttpService', () => {

expect(service['host']).toEqual('http://foo')
})

it('should set and use the authorization token', () => {
const service = createService()

expect(service['authorizationToken']).toBeUndefined()

service.setAuthorizationToken('foo-bar')

expect(service['authorizationToken']).toEqual('foo-bar')
})
})
43 changes: 37 additions & 6 deletions packages/api/src/Domain/Http/HttpService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isString, joinPaths } from '@standardnotes/utils'
import { Environment } from '@standardnotes/services'
import { Environment } from '@standardnotes/models'
import { HttpRequestParams } from './HttpRequestParams'
import { HttpVerb } from './HttpVerb'
import { HttpRequest } from './HttpRequest'
Expand All @@ -12,6 +12,8 @@ import { HttpResponseMeta } from './HttpResponseMeta'
import { HttpErrorResponseBody } from './HttpErrorResponseBody'

export class HttpService implements HttpServiceInterface {
private authorizationToken?: string

constructor(
private environment: Environment,
private appVersion: string,
Expand All @@ -20,28 +22,57 @@ export class HttpService implements HttpServiceInterface {
private updateMetaCallback: (meta: HttpResponseMeta) => void,
) {}

setAuthorizationToken(authorizationToken: string): void {
this.authorizationToken = authorizationToken
}

setHost(host: string): void {
this.host = host
}

async get(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Get, authentication })
return this.runHttp({
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Get,
authentication: authentication ?? this.authorizationToken,
})
}

async post(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Post, authentication })
return this.runHttp({
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Post,
authentication: authentication ?? this.authorizationToken,
})
}

async put(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Put, authentication })
return this.runHttp({
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Put,
authentication: authentication ?? this.authorizationToken,
})
}

async patch(path: string, params: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Patch, authentication })
return this.runHttp({
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Patch,
authentication: authentication ?? this.authorizationToken,
})
}

async delete(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Delete, authentication })
return this.runHttp({
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Delete,
authentication: authentication ?? this.authorizationToken,
})
}

private async runHttp(httpRequest: HttpRequest): Promise<HttpResponse> {
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/Domain/Http/HttpServiceInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { HttpResponse } from './HttpResponse'

export interface HttpServiceInterface {
setHost(host: string): void
setAuthorizationToken(authorizationToken: string): void
get(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse>
post(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse>
put(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Either } from '@standardnotes/common'

import { HttpErrorResponseBody } from '../../Http/HttpErrorResponseBody'
import { HttpResponse } from '../../Http/HttpResponse'
import { SubscriptionInviteAcceptResponseBody } from './SubscriptionInviteAcceptResponseBody'

export interface SubscriptionInviteAcceptResponse extends HttpResponse {
data: SubscriptionInviteAcceptResponseBody | HttpErrorResponseBody
data: Either<SubscriptionInviteAcceptResponseBody, HttpErrorResponseBody>
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Either } from '@standardnotes/common'

import { HttpErrorResponseBody } from '../../Http/HttpErrorResponseBody'
import { HttpResponse } from '../../Http/HttpResponse'
import { SubscriptionInviteCancelResponseBody } from './SubscriptionInviteCancelResponseBody'

export interface SubscriptionInviteCancelResponse extends HttpResponse {
data: SubscriptionInviteCancelResponseBody | HttpErrorResponseBody
data: Either<SubscriptionInviteCancelResponseBody, HttpErrorResponseBody>
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Either } from '@standardnotes/common'

import { HttpErrorResponseBody } from '../../Http/HttpErrorResponseBody'
import { HttpResponse } from '../../Http/HttpResponse'
import { SubscriptionInviteDeclineResponseBody } from './SubscriptionInviteDeclineResponseBody'

export interface SubscriptionInviteDeclineResponse extends HttpResponse {
data: SubscriptionInviteDeclineResponseBody | HttpErrorResponseBody
data: Either<SubscriptionInviteDeclineResponseBody, HttpErrorResponseBody>
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Either } from '@standardnotes/common'

import { HttpErrorResponseBody } from '../../Http/HttpErrorResponseBody'
import { HttpResponse } from '../../Http/HttpResponse'
import { SubscriptionInviteListResponseBody } from './SubscriptionInviteListResponseBody'

export interface SubscriptionInviteListResponse extends HttpResponse {
data: SubscriptionInviteListResponseBody | HttpErrorResponseBody
data: Either<SubscriptionInviteListResponseBody, HttpErrorResponseBody>
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Either } from '@standardnotes/common'

import { HttpErrorResponseBody } from '../../Http/HttpErrorResponseBody'
import { HttpResponse } from '../../Http/HttpResponse'
import { SubscriptionInviteResponseBody } from './SubscriptionInviteResponseBody'

export interface SubscriptionInviteResponse extends HttpResponse {
data: SubscriptionInviteResponseBody | HttpErrorResponseBody
data: Either<SubscriptionInviteResponseBody, HttpErrorResponseBody>
}
3 changes: 2 additions & 1 deletion packages/api/src/Domain/Server/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './User/Paths'
export * from './Subscription/SubscriptionServer'
export * from './Subscription/SubscriptionServerInterface'
export * from './User/UserServer'
export * from './User/UserServerInterface'
2 changes: 1 addition & 1 deletion packages/encryption/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"typescript": "*"
},
"dependencies": {
"@standardnotes/common": "^1.23.1",
"@standardnotes/common": "^1.32.0",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/sncrypto-common": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/features/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"dependencies": {
"@standardnotes/auth": "^3.19.4",
"@standardnotes/common": "^1.23.1",
"@standardnotes/common": "^1.32.0",
"@standardnotes/security": "^1.2.0",
"reflect-metadata": "^0.1.13"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/filepicker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"ts-node": "^10.5.0"
},
"dependencies": {
"@standardnotes/common": "^1.23.1",
"@standardnotes/common": "^1.32.0",
"@standardnotes/files": "workspace:*",
"@standardnotes/utils": "workspace:*",
"@types/wicg-file-system-access": "^2020.9.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/files/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"ts-jest": "^28.0.5"
},
"dependencies": {
"@standardnotes/common": "^1.23.1",
"@standardnotes/common": "^1.32.0",
"@standardnotes/encryption": "workspace:*",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/models/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"typescript": "*"
},
"dependencies": {
"@standardnotes/common": "^1.23.1",
"@standardnotes/common": "^1.32.0",
"@standardnotes/features": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/utils": "workspace:*",
Expand Down
6 changes: 6 additions & 0 deletions packages/models/src/Domain/Device/Environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum Environment {
Web = 1,
Desktop = 2,
Mobile = 3,
NativeMobileWeb = 4,
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
export enum Environment {
Web = 1,
Desktop = 2,
Mobile = 3,
NativeMobileWeb = 4,
}

export enum Platform {
Ios = 1,
Android = 2,
Expand Down
2 changes: 2 additions & 0 deletions packages/models/src/Domain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export * from './Api/Subscription/Invitation'
export * from './Api/Subscription/InvitationStatus'
export * from './Api/Subscription/InviteeIdentifierType'
export * from './Api/Subscription/InviterIdentifierType'
export * from './Device/Environment'
export * from './Device/Platform'
export * from './Local/KeyParams/RootKeyParamsInterface'
export * from './Local/RootKey/KeychainTypes'
export * from './Local/RootKey/RootKeyContent'
Expand Down
2 changes: 1 addition & 1 deletion packages/responses/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"ts-jest": "^28.0.5"
},
"dependencies": {
"@standardnotes/common": "^1.23.1",
"@standardnotes/common": "^1.32.0",
"@standardnotes/features": "workspace:*",
"@standardnotes/security": "^1.1.0",
"reflect-metadata": "^0.1.13"
Expand Down
4 changes: 2 additions & 2 deletions packages/services/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ module.exports = {
coverageThreshold: {
global: {
branches: 9,
functions: 9,
lines: 16,
functions: 10,
lines: 17,
statements: 16
}
}
Expand Down
5 changes: 4 additions & 1 deletion packages/services/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
"prebuild": "yarn clean",
"build": "tsc -p tsconfig.json",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"test": "jest spec --coverage"
},
"dependencies": {
"@standardnotes/api": "workspace:^",
"@standardnotes/auth": "^3.19.4",
"@standardnotes/common": "^1.30.0",
"@standardnotes/common": "^1.32.0",
"@standardnotes/encryption": "workspace:^",
"@standardnotes/files": "workspace:^",
"@standardnotes/models": "workspace:^",
Expand All @@ -37,6 +39,7 @@
"@types/jest": "^28.1.5",
"@typescript-eslint/eslint-plugin": "^5.30.0",
"@typescript-eslint/parser": "^5.12.1",
"eslint": "^8.23.1",
"eslint-plugin-prettier": "*",
"jest": "^28.1.2",
"ts-jest": "^28.0.5"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ApplicationIdentifier, ContentType } from '@standardnotes/common'
import { BackupFile, DecryptedItemInterface, ItemStream, PrefKey, PrefValue } from '@standardnotes/models'
import { BackupFile, DecryptedItemInterface, ItemStream, Platform, PrefKey, PrefValue } from '@standardnotes/models'
import { FilesClientInterface } from '@standardnotes/files'
import { AlertService } from '../Alert/AlertService'

import { ComponentManagerInterface } from '../Component/ComponentManagerInterface'
import { Platform } from '../Device/Environments'
import { ApplicationEvent } from '../Event/ApplicationEvent'
import { ApplicationEventCallback } from '../Event/ApplicationEventCallback'
import { FeaturesClientInterface } from '../Feature/FeaturesClientInterface'
import { SubscriptionClientInterface } from '../Subscription/SubscriptionClientInterface'
import { ItemsClientInterface } from '../Item/ItemsClientInterface'
import { MutatorClientInterface } from '../Mutator/MutatorClientInterface'
import { StorageValueModes } from '../Storage/StorageTypes'
Expand Down Expand Up @@ -48,6 +48,7 @@ export interface ApplicationInterface {
get mutator(): MutatorClientInterface
get user(): UserClientInterface
get files(): FilesClientInterface
get subscriptions(): SubscriptionClientInterface
readonly identifier: ApplicationIdentifier
readonly platform: Platform
deviceInterface: DeviceInterface
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Environment } from '@standardnotes/models'

import { WebClientRequiresDesktopMethods } from './DesktopWebCommunication'
import { DeviceInterface } from './DeviceInterface'
import { Environment } from './Environments'
import { WebOrDesktopDeviceInterface } from './WebOrDesktopDeviceInterface'

/* istanbul ignore file */
Expand Down
2 changes: 1 addition & 1 deletion packages/services/src/Domain/Device/DeviceInterface.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Environment } from './Environments'
import { ApplicationIdentifier } from '@standardnotes/common'
import {
FullyFormedTransferPayload,
TransferPayload,
LegacyRawKeychainValue,
NamespacedRootKeyInKeychain,
Environment,
} from '@standardnotes/models'

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/services/src/Domain/Device/MobileDeviceInterface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { DeviceInterface } from './DeviceInterface'
import { Environment } from './Environments'
import { RawKeychainValue } from '@standardnotes/models'
import { Environment, RawKeychainValue } from '@standardnotes/models'

export interface MobileDeviceInterface extends DeviceInterface {
environment: Environment.Mobile
Expand Down
3 changes: 2 additions & 1 deletion packages/services/src/Domain/Device/TypeCheck.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Environment } from '@standardnotes/models'

import { DeviceInterface } from './DeviceInterface'
import { Environment } from './Environments'
import { MobileDeviceInterface } from './MobileDeviceInterface'
import { isMobileDevice } from './TypeCheck'

Expand Down
2 changes: 1 addition & 1 deletion packages/services/src/Domain/Device/TypeCheck.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Environment } from './Environments'
import { MobileDeviceInterface } from './MobileDeviceInterface'
import { DeviceInterface } from './DeviceInterface'
import { Environment } from '@standardnotes/models'

/* istanbul ignore file */

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Uuid } from '@standardnotes/common'
import { Invitation } from '@standardnotes/models'

export interface SubscriptionClientInterface {
listSubscriptionInvitations(): Promise<Invitation[]>
inviteToSubscription(inviteeEmail: string): Promise<boolean>
cancelInvitation(inviteUuid: Uuid): Promise<boolean>
}

0 comments on commit 55b1409

Please sign in to comment.