import { DeviceType } from '../enums/deviceType'; import { PolicyType } from '../enums/policyType'; import { ApiService as ApiServiceAbstraction } from '../abstractions/api.service'; import { PlatformUtilsService } from '../abstractions/platformUtils.service'; import { TokenService } from '../abstractions/token.service'; import { AttachmentRequest } from '../models/request/attachmentRequest'; import { BitPayInvoiceRequest } from '../models/request/bitPayInvoiceRequest'; import { CipherBulkDeleteRequest } from '../models/request/cipherBulkDeleteRequest'; import { CipherBulkMoveRequest } from '../models/request/cipherBulkMoveRequest'; import { CipherBulkShareRequest } from '../models/request/cipherBulkShareRequest'; import { CipherCollectionsRequest } from '../models/request/cipherCollectionsRequest'; import { CipherCreateRequest } from '../models/request/cipherCreateRequest'; import { CipherRequest } from '../models/request/cipherRequest'; import { CipherShareRequest } from '../models/request/cipherShareRequest'; import { CollectionRequest } from '../models/request/collectionRequest'; import { DeleteRecoverRequest } from '../models/request/deleteRecoverRequest'; import { EmailRequest } from '../models/request/emailRequest'; import { EmailTokenRequest } from '../models/request/emailTokenRequest'; import { EmergencyAccessAcceptRequest } from '../models/request/emergencyAccessAcceptRequest'; import { EmergencyAccessConfirmRequest } from '../models/request/emergencyAccessConfirmRequest'; import { EmergencyAccessInviteRequest } from '../models/request/emergencyAccessInviteRequest'; import { EmergencyAccessPasswordRequest } from '../models/request/emergencyAccessPasswordRequest'; import { EmergencyAccessUpdateRequest } from '../models/request/emergencyAccessUpdateRequest'; import { EventRequest } from '../models/request/eventRequest'; import { FolderRequest } from '../models/request/folderRequest'; import { GroupRequest } from '../models/request/groupRequest'; import { IapCheckRequest } from '../models/request/iapCheckRequest'; import { ImportCiphersRequest } from '../models/request/importCiphersRequest'; import { ImportDirectoryRequest } from '../models/request/importDirectoryRequest'; import { ImportOrganizationCiphersRequest } from '../models/request/importOrganizationCiphersRequest'; import { KdfRequest } from '../models/request/kdfRequest'; import { KeysRequest } from '../models/request/keysRequest'; import { OrganizationCreateRequest } from '../models/request/organizationCreateRequest'; import { OrganizationImportRequest } from '../models/request/organizationImportRequest'; import { OrganizationKeysRequest } from '../models/request/organizationKeysRequest'; import { OrganizationTaxInfoUpdateRequest } from '../models/request/organizationTaxInfoUpdateRequest'; import { OrganizationUpdateRequest } from '../models/request/organizationUpdateRequest'; import { OrganizationUpgradeRequest } from '../models/request/organizationUpgradeRequest'; import { OrganizationUserAcceptRequest } from '../models/request/organizationUserAcceptRequest'; import { OrganizationUserBulkConfirmRequest } from '../models/request/organizationUserBulkConfirmRequest'; import { OrganizationUserBulkRequest } from '../models/request/organizationUserBulkRequest'; import { OrganizationUserConfirmRequest } from '../models/request/organizationUserConfirmRequest'; import { OrganizationUserInviteRequest } from '../models/request/organizationUserInviteRequest'; import { OrganizationUserResetPasswordEnrollmentRequest } from '../models/request/organizationUserResetPasswordEnrollmentRequest'; import { OrganizationUserResetPasswordRequest } from '../models/request/organizationUserResetPasswordRequest'; import { OrganizationUserUpdateGroupsRequest } from '../models/request/organizationUserUpdateGroupsRequest'; import { OrganizationUserUpdateRequest } from '../models/request/organizationUserUpdateRequest'; import { PasswordHintRequest } from '../models/request/passwordHintRequest'; import { PasswordRequest } from '../models/request/passwordRequest'; import { PasswordVerificationRequest } from '../models/request/passwordVerificationRequest'; import { PaymentRequest } from '../models/request/paymentRequest'; import { PolicyRequest } from '../models/request/policyRequest'; import { PreloginRequest } from '../models/request/preloginRequest'; import { ProviderAddOrganizationRequest } from '../models/request/provider/providerAddOrganizationRequest'; import { ProviderSetupRequest } from '../models/request/provider/providerSetupRequest'; import { ProviderUpdateRequest } from '../models/request/provider/providerUpdateRequest'; import { ProviderUserAcceptRequest } from '../models/request/provider/providerUserAcceptRequest'; import { ProviderUserBulkConfirmRequest } from '../models/request/provider/providerUserBulkConfirmRequest'; import { ProviderUserBulkRequest } from '../models/request/provider/providerUserBulkRequest'; import { ProviderUserConfirmRequest } from '../models/request/provider/providerUserConfirmRequest'; import { ProviderUserInviteRequest } from '../models/request/provider/providerUserInviteRequest'; import { ProviderUserUpdateRequest } from '../models/request/provider/providerUserUpdateRequest'; import { RegisterRequest } from '../models/request/registerRequest'; import { SeatRequest } from '../models/request/seatRequest'; import { SelectionReadOnlyRequest } from '../models/request/selectionReadOnlyRequest'; import { SendAccessRequest } from '../models/request/sendAccessRequest'; import { SendRequest } from '../models/request/sendRequest'; import { SetPasswordRequest } from '../models/request/setPasswordRequest'; import { StorageRequest } from '../models/request/storageRequest'; import { TaxInfoUpdateRequest } from '../models/request/taxInfoUpdateRequest'; import { TokenRequest } from '../models/request/tokenRequest'; import { TwoFactorEmailRequest } from '../models/request/twoFactorEmailRequest'; import { TwoFactorProviderRequest } from '../models/request/twoFactorProviderRequest'; import { TwoFactorRecoveryRequest } from '../models/request/twoFactorRecoveryRequest'; import { UpdateDomainsRequest } from '../models/request/updateDomainsRequest'; import { UpdateKeyRequest } from '../models/request/updateKeyRequest'; import { UpdateProfileRequest } from '../models/request/updateProfileRequest'; import { UpdateTwoFactorAuthenticatorRequest } from '../models/request/updateTwoFactorAuthenticatorRequest'; import { UpdateTwoFactorDuoRequest } from '../models/request/updateTwoFactorDuoRequest'; import { UpdateTwoFactorEmailRequest } from '../models/request/updateTwoFactorEmailRequest'; import { UpdateTwoFactorWebAuthnDeleteRequest } from '../models/request/updateTwoFactorWebAuthnDeleteRequest'; import { UpdateTwoFactorWebAuthnRequest } from '../models/request/updateTwoFactorWebAuthnRequest'; import { UpdateTwoFactorYubioOtpRequest } from '../models/request/updateTwoFactorYubioOtpRequest'; import { VerifyBankRequest } from '../models/request/verifyBankRequest'; import { VerifyDeleteRecoverRequest } from '../models/request/verifyDeleteRecoverRequest'; import { VerifyEmailRequest } from '../models/request/verifyEmailRequest'; import { Utils } from '../misc/utils'; import { ApiKeyResponse } from '../models/response/apiKeyResponse'; import { AttachmentResponse } from '../models/response/attachmentResponse'; import { AttachmentUploadDataResponse } from '../models/response/attachmentUploadDataResponse'; import { BillingResponse } from '../models/response/billingResponse'; import { BreachAccountResponse } from '../models/response/breachAccountResponse'; import { CipherResponse } from '../models/response/cipherResponse'; import { CollectionGroupDetailsResponse, CollectionResponse, } from '../models/response/collectionResponse'; import { DomainsResponse } from '../models/response/domainsResponse'; import { EmergencyAccessGranteeDetailsResponse, EmergencyAccessGrantorDetailsResponse, EmergencyAccessTakeoverResponse, EmergencyAccessViewResponse } from '../models/response/emergencyAccessResponse'; import { ErrorResponse } from '../models/response/errorResponse'; import { EventResponse } from '../models/response/eventResponse'; import { FolderResponse } from '../models/response/folderResponse'; import { GroupDetailsResponse, GroupResponse, } from '../models/response/groupResponse'; import { IdentityTokenResponse } from '../models/response/identityTokenResponse'; import { IdentityTwoFactorResponse } from '../models/response/identityTwoFactorResponse'; import { ListResponse } from '../models/response/listResponse'; import { OrganizationKeysResponse } from '../models/response/organizationKeysResponse'; import { OrganizationResponse } from '../models/response/organizationResponse'; import { OrganizationSubscriptionResponse } from '../models/response/organizationSubscriptionResponse'; import { OrganizationUserBulkPublicKeyResponse } from '../models/response/organizationUserBulkPublicKeyResponse'; import { OrganizationUserBulkResponse } from '../models/response/organizationUserBulkResponse'; import { OrganizationUserDetailsResponse, OrganizationUserResetPasswordDetailsReponse, OrganizationUserUserDetailsResponse, } from '../models/response/organizationUserResponse'; import { PaymentResponse } from '../models/response/paymentResponse'; import { PlanResponse } from '../models/response/planResponse'; import { PolicyResponse } from '../models/response/policyResponse'; import { PreloginResponse } from '../models/response/preloginResponse'; import { ProfileResponse } from '../models/response/profileResponse'; import { ProviderOrganizationOrganizationDetailsResponse } from '../models/response/provider/providerOrganizationResponse'; import { ProviderResponse } from '../models/response/provider/providerResponse'; import { ProviderUserBulkPublicKeyResponse } from '../models/response/provider/providerUserBulkPublicKeyResponse'; import { ProviderUserBulkResponse } from '../models/response/provider/providerUserBulkResponse'; import { ProviderUserResponse, ProviderUserUserDetailsResponse } from '../models/response/provider/providerUserResponse'; import { SelectionReadOnlyResponse } from '../models/response/selectionReadOnlyResponse'; import { SendAccessResponse } from '../models/response/sendAccessResponse'; import { SendFileDownloadDataResponse } from '../models/response/sendFileDownloadDataResponse'; import { SendFileUploadDataResponse } from '../models/response/sendFileUploadDataResponse'; import { SendResponse } from '../models/response/sendResponse'; import { SubscriptionResponse } from '../models/response/subscriptionResponse'; import { SyncResponse } from '../models/response/syncResponse'; import { TaxInfoResponse } from '../models/response/taxInfoResponse'; import { TaxRateResponse } from '../models/response/taxRateResponse'; import { TwoFactorAuthenticatorResponse } from '../models/response/twoFactorAuthenticatorResponse'; import { TwoFactorDuoResponse } from '../models/response/twoFactorDuoResponse'; import { TwoFactorEmailResponse } from '../models/response/twoFactorEmailResponse'; import { TwoFactorProviderResponse } from '../models/response/twoFactorProviderResponse'; import { TwoFactorRecoverResponse } from '../models/response/twoFactorRescoverResponse'; import { TwoFactorWebAuthnResponse } from '../models/response/twoFactorWebAuthnResponse'; import { ChallengeResponse } from '../models/response/twoFactorWebAuthnResponse'; import { TwoFactorYubiKeyResponse } from '../models/response/twoFactorYubiKeyResponse'; import { UserKeyResponse } from '../models/response/userKeyResponse'; import { EnvironmentService } from '../abstractions'; import { IdentityCaptchaResponse } from '../models/response/identityCaptchaResponse'; import { SendAccessView } from '../models/view/sendAccessView'; export class ApiService implements ApiServiceAbstraction { private device: DeviceType; private deviceType: string; private isWebClient = false; private isDesktopClient = false; constructor(private tokenService: TokenService, private platformUtilsService: PlatformUtilsService, private environmentService: EnvironmentService, private logoutCallback: (expired: boolean) => Promise, private customUserAgent: string = null) { this.device = platformUtilsService.getDevice(); this.deviceType = this.device.toString(); this.isWebClient = this.device === DeviceType.IEBrowser || this.device === DeviceType.ChromeBrowser || this.device === DeviceType.EdgeBrowser || this.device === DeviceType.FirefoxBrowser || this.device === DeviceType.OperaBrowser || this.device === DeviceType.SafariBrowser || this.device === DeviceType.UnknownBrowser || this.device === DeviceType.VivaldiBrowser; this.isDesktopClient = this.device === DeviceType.WindowsDesktop || this.device === DeviceType.MacOsDesktop || this.device === DeviceType.LinuxDesktop; } // Auth APIs async postIdentityToken(request: TokenRequest): Promise { const headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'Accept': 'application/json', 'Device-Type': this.deviceType, }); if (this.customUserAgent != null) { headers.set('User-Agent', this.customUserAgent); } request.alterIdentityTokenHeaders(headers); const response = await this.fetch(new Request(this.environmentService.getIdentityUrl() + '/connect/token', { body: this.qsStringify(request.toIdentityToken(request.clientId ?? this.platformUtilsService.identityClientId)), credentials: this.getCredentials(), cache: 'no-store', headers: headers, method: 'POST', })); let responseJson: any = null; if (this.isJsonResponse(response)) { responseJson = await response.json(); } if (responseJson != null) { if (response.status === 200) { return new IdentityTokenResponse(responseJson); } else if (response.status === 400 && responseJson.TwoFactorProviders2 && Object.keys(responseJson.TwoFactorProviders2).length) { await this.tokenService.clearTwoFactorToken(request.email); return new IdentityTwoFactorResponse(responseJson); } else if (response.status === 400 && responseJson.HCaptcha_SiteKey && Object.keys(responseJson.HCaptcha_SiteKey).length) { return new IdentityCaptchaResponse(responseJson); } } return Promise.reject(new ErrorResponse(responseJson, response.status, true)); } async refreshIdentityToken(): Promise { try { await this.doRefreshToken(); } catch (e) { return Promise.reject(null); } } // Account APIs async getProfile(): Promise { const r = await this.send('GET', '/accounts/profile', null, true, true); return new ProfileResponse(r); } async getUserBilling(): Promise { const r = await this.send('GET', '/accounts/billing', null, true, true); return new BillingResponse(r); } async getUserSubscription(): Promise { const r = await this.send('GET', '/accounts/subscription', null, true, true); return new SubscriptionResponse(r); } async getTaxInfo(): Promise { const r = await this.send('GET', '/accounts/tax', null, true, true); return new TaxInfoResponse(r); } async putProfile(request: UpdateProfileRequest): Promise { const r = await this.send('PUT', '/accounts/profile', request, true, true); return new ProfileResponse(r); } putTaxInfo(request: TaxInfoUpdateRequest): Promise { return this.send('PUT', '/accounts/tax', request, true, false); } async postPrelogin(request: PreloginRequest): Promise { const r = await this.send('POST', '/accounts/prelogin', request, false, true); return new PreloginResponse(r); } postEmailToken(request: EmailTokenRequest): Promise { return this.send('POST', '/accounts/email-token', request, true, false); } postEmail(request: EmailRequest): Promise { return this.send('POST', '/accounts/email', request, true, false); } postPassword(request: PasswordRequest): Promise { return this.send('POST', '/accounts/password', request, true, false); } setPassword(request: SetPasswordRequest): Promise { return this.send('POST', '/accounts/set-password', request, true, false); } postSecurityStamp(request: PasswordVerificationRequest): Promise { return this.send('POST', '/accounts/security-stamp', request, true, false); } deleteAccount(request: PasswordVerificationRequest): Promise { return this.send('DELETE', '/accounts', request, true, false); } async getAccountRevisionDate(): Promise { const r = await this.send('GET', '/accounts/revision-date', null, true, true); return r as number; } postPasswordHint(request: PasswordHintRequest): Promise { return this.send('POST', '/accounts/password-hint', request, false, false); } postRegister(request: RegisterRequest): Promise { return this.send('POST', '/accounts/register', request, false, false); } async postPremium(data: FormData): Promise { const r = await this.send('POST', '/accounts/premium', data, true, true); return new PaymentResponse(r); } async postIapCheck(request: IapCheckRequest): Promise { return this.send('POST', '/accounts/iap-check', request, true, false); } postReinstatePremium(): Promise { return this.send('POST', '/accounts/reinstate-premium', null, true, false); } postCancelPremium(): Promise { return this.send('POST', '/accounts/cancel-premium', null, true, false); } async postAccountStorage(request: StorageRequest): Promise { const r = await this.send('POST', '/accounts/storage', request, true, true); return new PaymentResponse(r); } postAccountPayment(request: PaymentRequest): Promise { return this.send('POST', '/accounts/payment', request, true, false); } postAccountLicense(data: FormData): Promise { return this.send('POST', '/accounts/license', data, true, false); } postAccountKeys(request: KeysRequest): Promise { return this.send('POST', '/accounts/keys', request, true, false); } postAccountKey(request: UpdateKeyRequest): Promise { return this.send('POST', '/accounts/key', request, true, false); } postAccountVerifyEmail(): Promise { return this.send('POST', '/accounts/verify-email', null, true, false); } postAccountVerifyEmailToken(request: VerifyEmailRequest): Promise { return this.send('POST', '/accounts/verify-email-token', request, false, false); } postAccountVerifyPassword(request: PasswordVerificationRequest): Promise { return this.send('POST', '/accounts/verify-password', request, true, false); } postAccountRecoverDelete(request: DeleteRecoverRequest): Promise { return this.send('POST', '/accounts/delete-recover', request, false, false); } postAccountRecoverDeleteToken(request: VerifyDeleteRecoverRequest): Promise { return this.send('POST', '/accounts/delete-recover-token', request, false, false); } postAccountKdf(request: KdfRequest): Promise { return this.send('POST', '/accounts/kdf', request, true, false); } async getEnterprisePortalSignInToken(): Promise { const r = await this.send('GET', '/accounts/enterprise-portal-signin-token', null, true, true); return r as string; } async deleteSsoUser(organizationId: string): Promise { return this.send('DELETE', '/accounts/sso/' + organizationId, null, true, false); } async getSsoUserIdentifier(): Promise { return this.send('GET', '/accounts/sso/user-identifier', null, true, true); } async postUserApiKey(id: string, request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/accounts/api-key', request, true, true); return new ApiKeyResponse(r); } async postUserRotateApiKey(id: string, request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/accounts/rotate-api-key', request, true, true); return new ApiKeyResponse(r); } // Folder APIs async getFolder(id: string): Promise { const r = await this.send('GET', '/folders/' + id, null, true, true); return new FolderResponse(r); } async postFolder(request: FolderRequest): Promise { const r = await this.send('POST', '/folders', request, true, true); return new FolderResponse(r); } async putFolder(id: string, request: FolderRequest): Promise { const r = await this.send('PUT', '/folders/' + id, request, true, true); return new FolderResponse(r); } deleteFolder(id: string): Promise { return this.send('DELETE', '/folders/' + id, null, true, false); } // Send APIs async getSend(id: string): Promise { const r = await this.send('GET', '/sends/' + id, null, true, true); return new SendResponse(r); } async postSendAccess(id: string, request: SendAccessRequest, apiUrl?: string): Promise { const addSendIdHeader = (headers: Headers) => { headers.set('Send-Id', id); }; const r = await this.send('POST', '/sends/access/' + id, request, false, true, apiUrl, addSendIdHeader); return new SendAccessResponse(r); } async getSendFileDownloadData(send: SendAccessView, request: SendAccessRequest, apiUrl?: string): Promise { const addSendIdHeader = (headers: Headers) => { headers.set('Send-Id', send.id); }; const r = await this.send('POST', '/sends/' + send.id + '/access/file/' + send.file.id, request, false, true, apiUrl, addSendIdHeader); return new SendFileDownloadDataResponse(r); } async getSends(): Promise> { const r = await this.send('GET', '/sends', null, true, true); return new ListResponse(r, SendResponse); } async postSend(request: SendRequest): Promise { const r = await this.send('POST', '/sends', request, true, true); return new SendResponse(r); } async postFileTypeSend(request: SendRequest): Promise { const r = await this.send('POST', '/sends/file/v2', request, true, true); return new SendFileUploadDataResponse(r); } async renewSendFileUploadUrl(sendId: string, fileId: string): Promise { const r = await this.send('GET', '/sends/' + sendId + '/file/' + fileId, null, true, true); return new SendFileUploadDataResponse(r); } postSendFile(sendId: string, fileId: string, data: FormData): Promise { return this.send('POST', '/sends/' + sendId + '/file/' + fileId, data, true, false); } /** * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. * This method still exists for backward compatibility with old server versions. */ async postSendFileLegacy(data: FormData): Promise { const r = await this.send('POST', '/sends/file', data, true, true); return new SendResponse(r); } async putSend(id: string, request: SendRequest): Promise { const r = await this.send('PUT', '/sends/' + id, request, true, true); return new SendResponse(r); } async putSendRemovePassword(id: string): Promise { const r = await this.send('PUT', '/sends/' + id + '/remove-password', null, true, true); return new SendResponse(r); } deleteSend(id: string): Promise { return this.send('DELETE', '/sends/' + id, null, true, false); } // Cipher APIs async getCipher(id: string): Promise { const r = await this.send('GET', '/ciphers/' + id, null, true, true); return new CipherResponse(r); } async getCipherAdmin(id: string): Promise { const r = await this.send('GET', '/ciphers/' + id + '/admin', null, true, true); return new CipherResponse(r); } async getCiphersOrganization(organizationId: string): Promise> { const r = await this.send('GET', '/ciphers/organization-details?organizationId=' + organizationId, null, true, true); return new ListResponse(r, CipherResponse); } async postCipher(request: CipherRequest): Promise { const r = await this.send('POST', '/ciphers', request, true, true); return new CipherResponse(r); } async postCipherCreate(request: CipherCreateRequest): Promise { const r = await this.send('POST', '/ciphers/create', request, true, true); return new CipherResponse(r); } async postCipherAdmin(request: CipherCreateRequest): Promise { const r = await this.send('POST', '/ciphers/admin', request, true, true); return new CipherResponse(r); } async putCipher(id: string, request: CipherRequest): Promise { const r = await this.send('PUT', '/ciphers/' + id, request, true, true); return new CipherResponse(r); } async putCipherAdmin(id: string, request: CipherRequest): Promise { const r = await this.send('PUT', '/ciphers/' + id + '/admin', request, true, true); return new CipherResponse(r); } deleteCipher(id: string): Promise { return this.send('DELETE', '/ciphers/' + id, null, true, false); } deleteCipherAdmin(id: string): Promise { return this.send('DELETE', '/ciphers/' + id + '/admin', null, true, false); } deleteManyCiphers(request: CipherBulkDeleteRequest): Promise { return this.send('DELETE', '/ciphers', request, true, false); } deleteManyCiphersAdmin(request: CipherBulkDeleteRequest): Promise { return this.send('DELETE', '/ciphers/admin', request, true, false); } putMoveCiphers(request: CipherBulkMoveRequest): Promise { return this.send('PUT', '/ciphers/move', request, true, false); } async putShareCipher(id: string, request: CipherShareRequest): Promise { const r = await this.send('PUT', '/ciphers/' + id + '/share', request, true, true); return new CipherResponse(r); } putShareCiphers(request: CipherBulkShareRequest): Promise { return this.send('PUT', '/ciphers/share', request, true, false); } putCipherCollections(id: string, request: CipherCollectionsRequest): Promise { return this.send('PUT', '/ciphers/' + id + '/collections', request, true, false); } putCipherCollectionsAdmin(id: string, request: CipherCollectionsRequest): Promise { return this.send('PUT', '/ciphers/' + id + '/collections-admin', request, true, false); } postPurgeCiphers(request: PasswordVerificationRequest, organizationId: string = null): Promise { let path = '/ciphers/purge'; if (organizationId != null) { path += '?organizationId=' + organizationId; } return this.send('POST', path, request, true, false); } postImportCiphers(request: ImportCiphersRequest): Promise { return this.send('POST', '/ciphers/import', request, true, false); } postImportOrganizationCiphers(organizationId: string, request: ImportOrganizationCiphersRequest): Promise { return this.send('POST', '/ciphers/import-organization?organizationId=' + organizationId, request, true, false); } putDeleteCipher(id: string): Promise { return this.send('PUT', '/ciphers/' + id + '/delete', null, true, false); } putDeleteCipherAdmin(id: string): Promise { return this.send('PUT', '/ciphers/' + id + '/delete-admin', null, true, false); } putDeleteManyCiphers(request: CipherBulkDeleteRequest): Promise { return this.send('PUT', '/ciphers/delete', request, true, false); } putDeleteManyCiphersAdmin(request: CipherBulkDeleteRequest): Promise { return this.send('PUT', '/ciphers/delete-admin', request, true, false); } async putRestoreCipher(id: string): Promise { const r = await this.send('PUT', '/ciphers/' + id + '/restore', null, true, true); return new CipherResponse(r); } async putRestoreCipherAdmin(id: string): Promise { const r = await this.send('PUT', '/ciphers/' + id + '/restore-admin', null, true, true); return new CipherResponse(r); } async putRestoreManyCiphers(request: CipherBulkDeleteRequest): Promise> { const r = await this.send('PUT', '/ciphers/restore', request, true, true); return new ListResponse(r, CipherResponse); } // Attachments APIs async getAttachmentData(cipherId: string, attachmentId: string, emergencyAccessId?: string): Promise { const path = (emergencyAccessId != null ? '/emergency-access/' + emergencyAccessId + '/' : '/ciphers/') + cipherId + '/attachment/' + attachmentId; const r = await this.send('GET', path, null, true, true); return new AttachmentResponse(r); } async postCipherAttachment(id: string, request: AttachmentRequest): Promise { const r = await this.send('POST', '/ciphers/' + id + '/attachment/v2', request, true, true); return new AttachmentUploadDataResponse(r); } /** * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. * This method still exists for backward compatibility with old server versions. */ async postCipherAttachmentLegacy(id: string, data: FormData): Promise { const r = await this.send('POST', '/ciphers/' + id + '/attachment', data, true, true); return new CipherResponse(r); } /** * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. * This method still exists for backward compatibility with old server versions. */ async postCipherAttachmentAdminLegacy(id: string, data: FormData): Promise { const r = await this.send('POST', '/ciphers/' + id + '/attachment-admin', data, true, true); return new CipherResponse(r); } deleteCipherAttachment(id: string, attachmentId: string): Promise { return this.send('DELETE', '/ciphers/' + id + '/attachment/' + attachmentId, null, true, false); } deleteCipherAttachmentAdmin(id: string, attachmentId: string): Promise { return this.send('DELETE', '/ciphers/' + id + '/attachment/' + attachmentId + '/admin', null, true, false); } postShareCipherAttachment(id: string, attachmentId: string, data: FormData, organizationId: string): Promise { return this.send('POST', '/ciphers/' + id + '/attachment/' + attachmentId + '/share?organizationId=' + organizationId, data, true, false); } async renewAttachmentUploadUrl(id: string, attachmentId: string): Promise { const r = await this.send('GET', '/ciphers/' + id + '/attachment/' + attachmentId + '/renew', null, true, true); return new AttachmentUploadDataResponse(r); } postAttachmentFile(id: string, attachmentId: string, data: FormData): Promise { return this.send('POST', '/ciphers/' + id + '/attachment/' + attachmentId, data, true, false); } // Collections APIs async getCollectionDetails(organizationId: string, id: string): Promise { const r = await this.send('GET', '/organizations/' + organizationId + '/collections/' + id + '/details', null, true, true); return new CollectionGroupDetailsResponse(r); } async getUserCollections(): Promise> { const r = await this.send('GET', '/collections', null, true, true); return new ListResponse(r, CollectionResponse); } async getCollections(organizationId: string): Promise> { const r = await this.send('GET', '/organizations/' + organizationId + '/collections', null, true, true); return new ListResponse(r, CollectionResponse); } async getCollectionUsers(organizationId: string, id: string): Promise { const r = await this.send('GET', '/organizations/' + organizationId + '/collections/' + id + '/users', null, true, true); return r.map((dr: any) => new SelectionReadOnlyResponse(dr)); } async postCollection(organizationId: string, request: CollectionRequest): Promise { const r = await this.send('POST', '/organizations/' + organizationId + '/collections', request, true, true); return new CollectionResponse(r); } async putCollection(organizationId: string, id: string, request: CollectionRequest): Promise { const r = await this.send('PUT', '/organizations/' + organizationId + '/collections/' + id, request, true, true); return new CollectionResponse(r); } async putCollectionUsers(organizationId: string, id: string, request: SelectionReadOnlyRequest[]): Promise { await this.send('PUT', '/organizations/' + organizationId + '/collections/' + id + '/users', request, true, false); } deleteCollection(organizationId: string, id: string): Promise { return this.send('DELETE', '/organizations/' + organizationId + '/collections/' + id, null, true, false); } deleteCollectionUser(organizationId: string, id: string, organizationUserId: string): Promise { return this.send('DELETE', '/organizations/' + organizationId + '/collections/' + id + '/user/' + organizationUserId, null, true, false); } // Groups APIs async getGroupDetails(organizationId: string, id: string): Promise { const r = await this.send('GET', '/organizations/' + organizationId + '/groups/' + id + '/details', null, true, true); return new GroupDetailsResponse(r); } async getGroups(organizationId: string): Promise> { const r = await this.send('GET', '/organizations/' + organizationId + '/groups', null, true, true); return new ListResponse(r, GroupResponse); } async getGroupUsers(organizationId: string, id: string): Promise { const r = await this.send('GET', '/organizations/' + organizationId + '/groups/' + id + '/users', null, true, true); return r; } async postGroup(organizationId: string, request: GroupRequest): Promise { const r = await this.send('POST', '/organizations/' + organizationId + '/groups', request, true, true); return new GroupResponse(r); } async putGroup(organizationId: string, id: string, request: GroupRequest): Promise { const r = await this.send('PUT', '/organizations/' + organizationId + '/groups/' + id, request, true, true); return new GroupResponse(r); } async putGroupUsers(organizationId: string, id: string, request: string[]): Promise { await this.send('PUT', '/organizations/' + organizationId + '/groups/' + id + '/users', request, true, false); } deleteGroup(organizationId: string, id: string): Promise { return this.send('DELETE', '/organizations/' + organizationId + '/groups/' + id, null, true, false); } deleteGroupUser(organizationId: string, id: string, organizationUserId: string): Promise { return this.send('DELETE', '/organizations/' + organizationId + '/groups/' + id + '/user/' + organizationUserId, null, true, false); } // Policy APIs async getPolicy(organizationId: string, type: PolicyType): Promise { const r = await this.send('GET', '/organizations/' + organizationId + '/policies/' + type, null, true, true); return new PolicyResponse(r); } async getPolicies(organizationId: string): Promise> { const r = await this.send('GET', '/organizations/' + organizationId + '/policies', null, true, true); return new ListResponse(r, PolicyResponse); } async getPoliciesByToken(organizationId: string, token: string, email: string, organizationUserId: string): Promise> { const r = await this.send('GET', '/organizations/' + organizationId + '/policies/token?' + 'token=' + encodeURIComponent(token) + '&email=' + encodeURIComponent(email) + '&organizationUserId=' + organizationUserId, null, false, true); return new ListResponse(r, PolicyResponse); } async putPolicy(organizationId: string, type: PolicyType, request: PolicyRequest): Promise { const r = await this.send('PUT', '/organizations/' + organizationId + '/policies/' + type, request, true, true); return new PolicyResponse(r); } // Organization User APIs async getOrganizationUser(organizationId: string, id: string): Promise { const r = await this.send('GET', '/organizations/' + organizationId + '/users/' + id, null, true, true); return new OrganizationUserDetailsResponse(r); } async getOrganizationUserGroups(organizationId: string, id: string): Promise { const r = await this.send('GET', '/organizations/' + organizationId + '/users/' + id + '/groups', null, true, true); return r; } async getOrganizationUsers(organizationId: string): Promise> { const r = await this.send('GET', '/organizations/' + organizationId + '/users', null, true, true); return new ListResponse(r, OrganizationUserUserDetailsResponse); } async getOrganizationUserResetPasswordDetails(organizationId: string, id: string): Promise { const r = await this.send('GET', '/organizations/' + organizationId + '/users/' + id + '/reset-password-details', null, true, true); return new OrganizationUserResetPasswordDetailsReponse(r); } postOrganizationUserInvite(organizationId: string, request: OrganizationUserInviteRequest): Promise { return this.send('POST', '/organizations/' + organizationId + '/users/invite', request, true, false); } postOrganizationUserReinvite(organizationId: string, id: string): Promise { return this.send('POST', '/organizations/' + organizationId + '/users/' + id + '/reinvite', null, true, false); } async postManyOrganizationUserReinvite(organizationId: string, request: OrganizationUserBulkRequest): Promise> { const r = await this.send('POST', '/organizations/' + organizationId + '/users/reinvite', request, true, true); return new ListResponse(r, OrganizationUserBulkResponse); } postOrganizationUserAccept(organizationId: string, id: string, request: OrganizationUserAcceptRequest): Promise { return this.send('POST', '/organizations/' + organizationId + '/users/' + id + '/accept', request, true, false); } postOrganizationUserConfirm(organizationId: string, id: string, request: OrganizationUserConfirmRequest): Promise { return this.send('POST', '/organizations/' + organizationId + '/users/' + id + '/confirm', request, true, false); } async postOrganizationUsersPublicKey(organizationId: string, request: OrganizationUserBulkRequest): Promise> { const r = await this.send('POST', '/organizations/' + organizationId + '/users/public-keys', request, true, true); return new ListResponse(r, OrganizationUserBulkPublicKeyResponse); } async postOrganizationUserBulkConfirm(organizationId: string, request: OrganizationUserBulkConfirmRequest): Promise> { const r = await this.send('POST', '/organizations/' + organizationId + '/users/confirm', request, true, true); return new ListResponse(r, OrganizationUserBulkResponse); } putOrganizationUser(organizationId: string, id: string, request: OrganizationUserUpdateRequest): Promise { return this.send('PUT', '/organizations/' + organizationId + '/users/' + id, request, true, false); } putOrganizationUserGroups(organizationId: string, id: string, request: OrganizationUserUpdateGroupsRequest): Promise { return this.send('PUT', '/organizations/' + organizationId + '/users/' + id + '/groups', request, true, false); } putOrganizationUserResetPasswordEnrollment(organizationId: string, userId: string, request: OrganizationUserResetPasswordEnrollmentRequest): Promise { return this.send('PUT', '/organizations/' + organizationId + '/users/' + userId + '/reset-password-enrollment', request, true, false); } putOrganizationUserResetPassword(organizationId: string, id: string, request: OrganizationUserResetPasswordRequest): Promise { return this.send('PUT', '/organizations/' + organizationId + '/users/' + id + '/reset-password', request, true, false); } deleteOrganizationUser(organizationId: string, id: string): Promise { return this.send('DELETE', '/organizations/' + organizationId + '/users/' + id, null, true, false); } async deleteManyOrganizationUsers(organizationId: string, request: OrganizationUserBulkRequest): Promise> { const r = await this.send('DELETE', '/organizations/' + organizationId + '/users', request, true, true); return new ListResponse(r, OrganizationUserBulkResponse); } // Plan APIs async getPlans(): Promise> { const r = await this.send('GET', '/plans/', null, true, true); return new ListResponse(r, PlanResponse); } async postImportDirectory(organizationId: string, request: ImportDirectoryRequest): Promise { return this.send('POST', '/organizations/' + organizationId + '/import', request, true, false); } async postPublicImportDirectory(request: OrganizationImportRequest): Promise { return this.send('POST', '/public/organization/import', request, true, false); } async getTaxRates(): Promise> { const r = await this.send('GET', '/plans/sales-tax-rates/', null, true, true); return new ListResponse(r, TaxRateResponse); } // Settings APIs async getSettingsDomains(): Promise { const r = await this.send('GET', '/settings/domains', null, true, true); return new DomainsResponse(r); } async putSettingsDomains(request: UpdateDomainsRequest): Promise { const r = await this.send('PUT', '/settings/domains', request, true, true); return new DomainsResponse(r); } // Sync APIs async getSync(): Promise { const path = this.isDesktopClient || this.isWebClient ? '/sync?excludeDomains=true' : '/sync'; const r = await this.send('GET', path, null, true, true); return new SyncResponse(r); } // Two-factor APIs async getTwoFactorProviders(): Promise> { const r = await this.send('GET', '/two-factor', null, true, true); return new ListResponse(r, TwoFactorProviderResponse); } async getTwoFactorOrganizationProviders(organizationId: string): Promise> { const r = await this.send('GET', '/organizations/' + organizationId + '/two-factor', null, true, true); return new ListResponse(r, TwoFactorProviderResponse); } async getTwoFactorAuthenticator(request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/two-factor/get-authenticator', request, true, true); return new TwoFactorAuthenticatorResponse(r); } async getTwoFactorEmail(request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/two-factor/get-email', request, true, true); return new TwoFactorEmailResponse(r); } async getTwoFactorDuo(request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/two-factor/get-duo', request, true, true); return new TwoFactorDuoResponse(r); } async getTwoFactorOrganizationDuo(organizationId: string, request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/organizations/' + organizationId + '/two-factor/get-duo', request, true, true); return new TwoFactorDuoResponse(r); } async getTwoFactorYubiKey(request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/two-factor/get-yubikey', request, true, true); return new TwoFactorYubiKeyResponse(r); } async getTwoFactorWebAuthn(request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/two-factor/get-webauthn', request, true, true); return new TwoFactorWebAuthnResponse(r); } async getTwoFactorWebAuthnChallenge(request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/two-factor/get-webauthn-challenge', request, true, true); return new ChallengeResponse(r); } async getTwoFactorRecover(request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/two-factor/get-recover', request, true, true); return new TwoFactorRecoverResponse(r); } async putTwoFactorAuthenticator( request: UpdateTwoFactorAuthenticatorRequest): Promise { const r = await this.send('PUT', '/two-factor/authenticator', request, true, true); return new TwoFactorAuthenticatorResponse(r); } async putTwoFactorEmail(request: UpdateTwoFactorEmailRequest): Promise { const r = await this.send('PUT', '/two-factor/email', request, true, true); return new TwoFactorEmailResponse(r); } async putTwoFactorDuo(request: UpdateTwoFactorDuoRequest): Promise { const r = await this.send('PUT', '/two-factor/duo', request, true, true); return new TwoFactorDuoResponse(r); } async putTwoFactorOrganizationDuo(organizationId: string, request: UpdateTwoFactorDuoRequest): Promise { const r = await this.send('PUT', '/organizations/' + organizationId + '/two-factor/duo', request, true, true); return new TwoFactorDuoResponse(r); } async putTwoFactorYubiKey(request: UpdateTwoFactorYubioOtpRequest): Promise { const r = await this.send('PUT', '/two-factor/yubikey', request, true, true); return new TwoFactorYubiKeyResponse(r); } async putTwoFactorWebAuthn(request: UpdateTwoFactorWebAuthnRequest): Promise { const response = request.deviceResponse.response as AuthenticatorAttestationResponse; const data: any = Object.assign({}, request); data.deviceResponse = { id: request.deviceResponse.id, rawId: btoa(request.deviceResponse.id), type: request.deviceResponse.type, extensions: request.deviceResponse.getClientExtensionResults(), response: { AttestationObject: Utils.fromBufferToB64(response.attestationObject), clientDataJson: Utils.fromBufferToB64(response.clientDataJSON), }, }; const r = await this.send('PUT', '/two-factor/webauthn', data, true, true); return new TwoFactorWebAuthnResponse(r); } async deleteTwoFactorWebAuthn(request: UpdateTwoFactorWebAuthnDeleteRequest): Promise { const r = await this.send('DELETE', '/two-factor/webauthn', request, true, true); return new TwoFactorWebAuthnResponse(r); } async putTwoFactorDisable(request: TwoFactorProviderRequest): Promise { const r = await this.send('PUT', '/two-factor/disable', request, true, true); return new TwoFactorProviderResponse(r); } async putTwoFactorOrganizationDisable(organizationId: string, request: TwoFactorProviderRequest): Promise { const r = await this.send('PUT', '/organizations/' + organizationId + '/two-factor/disable', request, true, true); return new TwoFactorProviderResponse(r); } postTwoFactorRecover(request: TwoFactorRecoveryRequest): Promise { return this.send('POST', '/two-factor/recover', request, false, false); } postTwoFactorEmailSetup(request: TwoFactorEmailRequest): Promise { return this.send('POST', '/two-factor/send-email', request, true, false); } postTwoFactorEmail(request: TwoFactorEmailRequest): Promise { return this.send('POST', '/two-factor/send-email-login', request, false, false); } // Emergency Access APIs async getEmergencyAccessTrusted(): Promise> { const r = await this.send('GET', '/emergency-access/trusted', null, true, true); return new ListResponse(r, EmergencyAccessGranteeDetailsResponse); } async getEmergencyAccessGranted(): Promise> { const r = await this.send('GET', '/emergency-access/granted', null, true, true); return new ListResponse(r, EmergencyAccessGrantorDetailsResponse); } async getEmergencyAccess(id: string): Promise { const r = await this.send('GET', '/emergency-access/' + id, null, true, true); return new EmergencyAccessGranteeDetailsResponse(r); } async getEmergencyGrantorPolicies(id: string): Promise> { const r = await this.send('GET', '/emergency-access/' + id + '/policies', null, true, true); return new ListResponse(r, PolicyResponse); } putEmergencyAccess(id: string, request: EmergencyAccessUpdateRequest): Promise { return this.send('PUT', '/emergency-access/' + id, request, true, false); } deleteEmergencyAccess(id: string): Promise { return this.send('DELETE', '/emergency-access/' + id, null, true, false); } postEmergencyAccessInvite(request: EmergencyAccessInviteRequest): Promise { return this.send('POST', '/emergency-access/invite', request, true, false); } postEmergencyAccessReinvite(id: string): Promise { return this.send('POST', '/emergency-access/' + id + '/reinvite', null, true, false); } postEmergencyAccessAccept(id: string, request: EmergencyAccessAcceptRequest): Promise { return this.send('POST', '/emergency-access/' + id + '/accept', request, true, false); } postEmergencyAccessConfirm(id: string, request: EmergencyAccessConfirmRequest): Promise { return this.send('POST', '/emergency-access/' + id + '/confirm', request, true, false); } postEmergencyAccessInitiate(id: string): Promise { return this.send('POST', '/emergency-access/' + id + '/initiate', null, true, false); } postEmergencyAccessApprove(id: string): Promise { return this.send('POST', '/emergency-access/' + id + '/approve', null, true, false); } postEmergencyAccessReject(id: string): Promise { return this.send('POST', '/emergency-access/' + id + '/reject', null, true, false); } async postEmergencyAccessTakeover(id: string): Promise { const r = await this.send('POST', '/emergency-access/' + id + '/takeover', null, true, true); return new EmergencyAccessTakeoverResponse(r); } async postEmergencyAccessPassword(id: string, request: EmergencyAccessPasswordRequest): Promise { const r = await this.send('POST', '/emergency-access/' + id + '/password', request, true, true); } async postEmergencyAccessView(id: string): Promise { const r = await this.send('POST', '/emergency-access/' + id + '/view', null, true, true); return new EmergencyAccessViewResponse(r); } // Organization APIs async getOrganization(id: string): Promise { const r = await this.send('GET', '/organizations/' + id, null, true, true); return new OrganizationResponse(r); } async getOrganizationBilling(id: string): Promise { const r = await this.send('GET', '/organizations/' + id + '/billing', null, true, true); return new BillingResponse(r); } async getOrganizationSubscription(id: string): Promise { const r = await this.send('GET', '/organizations/' + id + '/subscription', null, true, true); return new OrganizationSubscriptionResponse(r); } async getOrganizationLicense(id: string, installationId: string): Promise { return this.send('GET', '/organizations/' + id + '/license?installationId=' + installationId, null, true, true); } async getOrganizationTaxInfo(id: string): Promise { const r = await this.send('GET', '/organizations/' + id + '/tax', null, true, true); return new TaxInfoResponse(r); } async postOrganization(request: OrganizationCreateRequest): Promise { const r = await this.send('POST', '/organizations', request, true, true); return new OrganizationResponse(r); } async putOrganization(id: string, request: OrganizationUpdateRequest): Promise { const r = await this.send('PUT', '/organizations/' + id, request, true, true); return new OrganizationResponse(r); } async putOrganizationTaxInfo(id: string, request: OrganizationTaxInfoUpdateRequest): Promise { return this.send('PUT', '/organizations/' + id + '/tax', request, true, false); } postLeaveOrganization(id: string): Promise { return this.send('POST', '/organizations/' + id + '/leave', null, true, false); } async postOrganizationLicense(data: FormData): Promise { const r = await this.send('POST', '/organizations/license', data, true, true); return new OrganizationResponse(r); } async postOrganizationLicenseUpdate(id: string, data: FormData): Promise { return this.send('POST', '/organizations/' + id + '/license', data, true, false); } async postOrganizationApiKey(id: string, request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/organizations/' + id + '/api-key', request, true, true); return new ApiKeyResponse(r); } async postOrganizationRotateApiKey(id: string, request: PasswordVerificationRequest): Promise { const r = await this.send('POST', '/organizations/' + id + '/rotate-api-key', request, true, true); return new ApiKeyResponse(r); } async postOrganizationUpgrade(id: string, request: OrganizationUpgradeRequest): Promise { const r = await this.send('POST', '/organizations/' + id + '/upgrade', request, true, true); return new PaymentResponse(r); } async postOrganizationSeat(id: string, request: SeatRequest): Promise { const r = await this.send('POST', '/organizations/' + id + '/seat', request, true, true); return new PaymentResponse(r); } async postOrganizationStorage(id: string, request: StorageRequest): Promise { const r = await this.send('POST', '/organizations/' + id + '/storage', request, true, true); return new PaymentResponse(r); } postOrganizationPayment(id: string, request: PaymentRequest): Promise { return this.send('POST', '/organizations/' + id + '/payment', request, true, false); } postOrganizationVerifyBank(id: string, request: VerifyBankRequest): Promise { return this.send('POST', '/organizations/' + id + '/verify-bank', request, true, false); } postOrganizationCancel(id: string): Promise { return this.send('POST', '/organizations/' + id + '/cancel', null, true, false); } postOrganizationReinstate(id: string): Promise { return this.send('POST', '/organizations/' + id + '/reinstate', null, true, false); } deleteOrganization(id: string, request: PasswordVerificationRequest): Promise { return this.send('DELETE', '/organizations/' + id, request, true, false); } async getOrganizationKeys(id: string): Promise { const r = await this.send('GET', '/organizations/' + id + '/keys', null, true, true); return new OrganizationKeysResponse(r); } async postOrganizationKeys(id: string, request: OrganizationKeysRequest): Promise { const r = await this.send('POST', '/organizations/' + id + '/keys', request, true, true); return new OrganizationKeysResponse(r); } // Provider APIs async postProviderSetup(id: string, request: ProviderSetupRequest) { const r = await this.send('POST', '/providers/' + id + '/setup', request, true, true); return new ProviderResponse(r); } async getProvider(id: string) { const r = await this.send('GET', '/providers/' + id, null, true, true); return new ProviderResponse(r); } async putProvider(id: string, request: ProviderUpdateRequest) { const r = await this.send('PUT', '/providers/' + id, request, true, true); return new ProviderResponse(r); } // Provider User APIs async getProviderUsers(providerId: string): Promise> { const r = await this.send('GET', '/providers/' + providerId + '/users', null, true, true); return new ListResponse(r, ProviderUserUserDetailsResponse); } async getProviderUser(providerId: string, id: string): Promise { const r = await this.send('GET', '/providers/' + providerId + '/users/' + id, null, true, true); return new ProviderUserResponse(r); } postProviderUserInvite(providerId: string, request: ProviderUserInviteRequest): Promise { return this.send('POST', '/providers/' + providerId + '/users/invite', request, true, false); } postProviderUserReinvite(providerId: string, id: string): Promise { return this.send('POST', '/providers/' + providerId + '/users/' + id + '/reinvite', null, true, false); } async postManyProviderUserReinvite(providerId: string, request: ProviderUserBulkRequest): Promise> { const r = await this.send('POST', '/providers/' + providerId + '/users/reinvite', request, true, true); return new ListResponse(r, ProviderUserBulkResponse); } async postProviderUserBulkConfirm(providerId: string, request: ProviderUserBulkConfirmRequest): Promise> { const r = await this.send('POST', '/providers/' + providerId + '/users/confirm', request, true, true); return new ListResponse(r, ProviderUserBulkResponse); } async deleteManyProviderUsers(providerId: string, request: ProviderUserBulkRequest): Promise> { const r = await this.send('DELETE', '/providers/' + providerId + '/users', request, true, true); return new ListResponse(r, ProviderUserBulkResponse); } postProviderUserAccept(providerId: string, id: string, request: ProviderUserAcceptRequest): Promise { return this.send('POST', '/providers/' + providerId + '/users/' + id + '/accept', request, true, false); } postProviderUserConfirm(providerId: string, id: string, request: ProviderUserConfirmRequest): Promise { return this.send('POST', '/providers/' + providerId + '/users/' + id + '/confirm', request, true, false); } async postProviderUsersPublicKey(providerId: string, request: ProviderUserBulkRequest): Promise> { const r = await this.send('POST', '/providers/' + providerId + '/users/public-keys', request, true, true); return new ListResponse(r, ProviderUserBulkPublicKeyResponse); } putProviderUser(providerId: string, id: string, request: ProviderUserUpdateRequest): Promise { return this.send('PUT', '/providers/' + providerId + '/users/' + id, request, true, false); } deleteProviderUser(providerId: string, id: string): Promise { return this.send('DELETE', '/providers/' + providerId + '/users/' + id, null, true, false); } // Provider Organization APIs async getProviderClients(providerId: string): Promise> { const r = await this.send('GET', '/providers/' + providerId + '/organizations', null, true, true); return new ListResponse(r, ProviderOrganizationOrganizationDetailsResponse); } postProviderAddOrganization(providerId: string, request: ProviderAddOrganizationRequest): Promise { return this.send('POST', '/providers/' + providerId + '/organizations/add', request, true, false); } async postProviderCreateOrganization(providerId: string, request: OrganizationCreateRequest): Promise { const r = await this.send('POST', '/providers/' + providerId + '/organizations', request, true, true); return new OrganizationResponse(r); } deleteProviderOrganization(providerId: string, id: string): Promise { return this.send('DELETE', '/providers/' + providerId + '/organizations/' + id, null, true, false); } // Event APIs async getEvents(start: string, end: string, token: string): Promise> { const r = await this.send('GET', this.addEventParameters('/events', start, end, token), null, true, true); return new ListResponse(r, EventResponse); } async getEventsCipher(id: string, start: string, end: string, token: string): Promise> { const r = await this.send('GET', this.addEventParameters('/ciphers/' + id + '/events', start, end, token), null, true, true); return new ListResponse(r, EventResponse); } async getEventsOrganization(id: string, start: string, end: string, token: string): Promise> { const r = await this.send('GET', this.addEventParameters('/organizations/' + id + '/events', start, end, token), null, true, true); return new ListResponse(r, EventResponse); } async getEventsOrganizationUser(organizationId: string, id: string, start: string, end: string, token: string): Promise> { const r = await this.send('GET', this.addEventParameters('/organizations/' + organizationId + '/users/' + id + '/events', start, end, token), null, true, true); return new ListResponse(r, EventResponse); } async getEventsProvider(id: string, start: string, end: string, token: string): Promise> { const r = await this.send('GET', this.addEventParameters('/providers/' + id + '/events', start, end, token), null, true, true); return new ListResponse(r, EventResponse); } async getEventsProviderUser(providerId: string, id: string, start: string, end: string, token: string): Promise> { const r = await this.send('GET', this.addEventParameters('/providers/' + providerId + '/users/' + id + '/events', start, end, token), null, true, true); return new ListResponse(r, EventResponse); } async postEventsCollect(request: EventRequest[]): Promise { const authHeader = await this.getActiveBearerToken(); const headers = new Headers({ 'Device-Type': this.deviceType, 'Authorization': 'Bearer ' + authHeader, 'Content-Type': 'application/json; charset=utf-8', }); if (this.customUserAgent != null) { headers.set('User-Agent', this.customUserAgent); } const response = await this.fetch(new Request(this.environmentService.getEventsUrl() + '/collect', { cache: 'no-store', credentials: this.getCredentials(), method: 'POST', body: JSON.stringify(request), headers: headers, })); if (response.status !== 200) { return Promise.reject('Event post failed.'); } } // User APIs async getUserPublicKey(id: string): Promise { const r = await this.send('GET', '/users/' + id + '/public-key', null, true, true); return new UserKeyResponse(r); } // HIBP APIs async getHibpBreach(username: string): Promise { const r = await this.send('GET', '/hibp/breach?username=' + username, null, true, true); return r.map((a: any) => new BreachAccountResponse(a)); } // Misc async postBitPayInvoice(request: BitPayInvoiceRequest): Promise { const r = await this.send('POST', '/bitpay-invoice', request, true, true); return r as string; } async postSetupPayment(): Promise { const r = await this.send('POST', '/setup-payment', null, true, true); return r as string; } // Helpers async getActiveBearerToken(): Promise { let accessToken = await this.tokenService.getToken(); if (this.tokenService.tokenNeedsRefresh()) { await this.doRefreshToken(); accessToken = await this.tokenService.getToken(); } return accessToken; } fetch(request: Request): Promise { if (request.method === 'GET') { request.headers.set('Cache-Control', 'no-store'); request.headers.set('Pragma', 'no-cache'); } return this.nativeFetch(request); } nativeFetch(request: Request): Promise { return fetch(request); } async preValidateSso(identifier: string): Promise { if (identifier == null || identifier === '') { throw new Error('Organization Identifier was not provided.'); } const headers = new Headers({ 'Accept': 'application/json', 'Device-Type': this.deviceType, }); if (this.customUserAgent != null) { headers.set('User-Agent', this.customUserAgent); } const path = `/account/prevalidate?domainHint=${encodeURIComponent(identifier)}`; const response = await this.fetch(new Request(this.environmentService.getIdentityUrl() + path, { cache: 'no-store', credentials: this.getCredentials(), headers: headers, method: 'GET', })); if (response.status === 200) { return true; } else { const error = await this.handleError(response, false, true); return Promise.reject(error); } } protected async doRefreshToken(): Promise { const refreshToken = await this.tokenService.getRefreshToken(); if (refreshToken == null || refreshToken === '') { throw new Error(); } const headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'Accept': 'application/json', 'Device-Type': this.deviceType, }); if (this.customUserAgent != null) { headers.set('User-Agent', this.customUserAgent); } const decodedToken = this.tokenService.decodeToken(); const response = await this.fetch(new Request(this.environmentService.getIdentityUrl() + '/connect/token', { body: this.qsStringify({ grant_type: 'refresh_token', client_id: decodedToken.client_id, refresh_token: refreshToken, }), cache: 'no-store', credentials: this.getCredentials(), headers: headers, method: 'POST', })); if (response.status === 200) { const responseJson = await response.json(); const tokenResponse = new IdentityTokenResponse(responseJson); await this.tokenService.setTokens(tokenResponse.accessToken, tokenResponse.refreshToken); } else { const error = await this.handleError(response, true, true); return Promise.reject(error); } } private async send(method: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, body: any, authed: boolean, hasResponse: boolean, apiUrl?: string, alterHeaders?: (headers: Headers) => void): Promise { apiUrl = Utils.isNullOrWhitespace(apiUrl) ? this.environmentService.getApiUrl() : apiUrl; const headers = new Headers({ 'Device-Type': this.deviceType, }); if (this.customUserAgent != null) { headers.set('User-Agent', this.customUserAgent); } const requestInit: RequestInit = { cache: 'no-store', credentials: this.getCredentials(), method: method, }; if (authed) { const authHeader = await this.getActiveBearerToken(); headers.set('Authorization', 'Bearer ' + authHeader); } if (body != null) { if (typeof body === 'string') { requestInit.body = body; headers.set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'); } else if (typeof body === 'object') { if (body instanceof FormData) { requestInit.body = body; } else { headers.set('Content-Type', 'application/json; charset=utf-8'); requestInit.body = JSON.stringify(body); } } } if (hasResponse) { headers.set('Accept', 'application/json'); } if (alterHeaders != null) { alterHeaders(headers); } requestInit.headers = headers; const response = await this.fetch(new Request(apiUrl + path, requestInit)); if (hasResponse && response.status === 200) { const responseJson = await response.json(); return responseJson; } else if (response.status !== 200) { const error = await this.handleError(response, false, authed); return Promise.reject(error); } } private async handleError(response: Response, tokenError: boolean, authed: boolean): Promise { if (authed && ((tokenError && response.status === 400) || response.status === 401 || response.status === 403)) { await this.logoutCallback(true); return null; } let responseJson: any = null; if (this.isJsonResponse(response)) { responseJson = await response.json(); } else if (this.isTextResponse(response)) { responseJson = { Message: await response.text() }; } return new ErrorResponse(responseJson, response.status, tokenError); } private qsStringify(params: any): string { return Object.keys(params).map(key => { return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]); }).join('&'); } private getCredentials(): RequestCredentials { if (!this.isWebClient || this.environmentService.hasBaseUrl()) { return 'include'; } return undefined; } private addEventParameters(base: string, start: string, end: string, token: string) { if (start != null) { base += ('?start=' + start); } if (end != null) { base += (base.indexOf('?') > -1 ? '&' : '?'); base += ('end=' + end); } if (token != null) { base += (base.indexOf('?') > -1 ? '&' : '?'); base += ('continuationToken=' + token); } return base; } private isJsonResponse(response: Response): boolean { const typeHeader = response.headers.get('content-type'); return typeHeader != null && typeHeader.indexOf('application/json') > -1; } private isTextResponse(response: Response): boolean { const typeHeader = response.headers.get('content-type'); return typeHeader != null && typeHeader.indexOf('text') > -1; } }