From 7b23b90054f18c2093386d62cc39abb9be67b075 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Fri, 6 Jul 2018 15:00:55 -0400 Subject: [PATCH] org user apis, sort function utils --- src/abstractions/api.service.ts | 13 ++++++ src/abstractions/collection.service.ts | 1 - src/misc/utils.ts | 19 +++++++++ .../response/organizationUserResponse.ts | 41 +++++++++++++++++++ src/services/api.service.ts | 8 ++++ src/services/collection.service.ts | 21 ++-------- src/services/folder.service.ts | 21 ++-------- 7 files changed, 87 insertions(+), 37 deletions(-) create mode 100644 src/models/response/organizationUserResponse.ts diff --git a/src/abstractions/api.service.ts b/src/abstractions/api.service.ts index d5c490be33..54891450a1 100644 --- a/src/abstractions/api.service.ts +++ b/src/abstractions/api.service.ts @@ -52,6 +52,7 @@ import { IdentityTokenResponse } from '../models/response/identityTokenResponse' import { IdentityTwoFactorResponse } from '../models/response/identityTwoFactorResponse'; import { ListResponse } from '../models/response/listResponse'; import { OrganizationResponse } from '../models/response/organizationResponse'; +import { OrganizationUserUserDetailsResponse } from '../models/response/organizationUserResponse'; import { ProfileResponse } from '../models/response/profileResponse'; import { SyncResponse } from '../models/response/syncResponse'; import { TwoFactorAuthenticatorResponse } from '../models/response/twoFactorAuthenticatorResponse'; @@ -70,6 +71,7 @@ export abstract class ApiService { setUrls: (urls: EnvironmentUrls) => void; postIdentityToken: (request: TokenRequest) => Promise; refreshIdentityToken: () => Promise; + getProfile: () => Promise; getUserBilling: () => Promise; putProfile: (request: UpdateProfileRequest) => Promise; @@ -88,9 +90,11 @@ export abstract class ApiService { postAccountPayment: (request: PaymentRequest) => Promise; postAccountLicense: (data: FormData) => Promise; postAccountKeys: (request: KeysRequest) => Promise; + postFolder: (request: FolderRequest) => Promise; putFolder: (id: string, request: FolderRequest) => Promise; deleteFolder: (id: string) => Promise; + getCipher: (id: string) => Promise; getCipherAdmin: (id: string) => Promise; getCiphersOrganization: (organizationId: string) => Promise>; @@ -109,28 +113,36 @@ export abstract class ApiService { postPurgeCiphers: (request: PasswordVerificationRequest) => Promise; postImportCiphers: (request: ImportCiphersRequest) => Promise; postImportOrganizationCiphers: (organizationId: string, request: ImportOrganizationCiphersRequest) => Promise; + postCipherAttachment: (id: string, data: FormData) => Promise; postCipherAttachmentAdmin: (id: string, data: FormData) => Promise; deleteCipherAttachment: (id: string, attachmentId: string) => Promise; deleteCipherAttachmentAdmin: (id: string, attachmentId: string) => Promise; postShareCipherAttachment: (id: string, attachmentId: string, data: FormData, organizationId: string) => Promise; + getCollectionDetails: (organizationId: string, id: string) => Promise; getCollections: (organizationId: string) => Promise>; getCollectionUsers: (organizationId: string, id: string) => Promise>; postCollection: (request: CollectionRequest) => Promise; putCollection: (id: string, request: CollectionRequest) => Promise; deleteCollection: (id: string) => Promise; + getGroupDetails: (organizationId: string, id: string) => Promise; getGroups: (organizationId: string) => Promise>; getGroupUsers: (organizationId: string, id: string) => Promise>; postGroup: (request: GroupRequest) => Promise; putGroup: (id: string, request: GroupRequest) => Promise; deleteGroup: (id: string) => Promise; + + getOrganizationUsers: (organizationId: string) => Promise>; + getSync: () => Promise; postImportDirectory: (organizationId: string, request: ImportDirectoryRequest) => Promise; + getSettingsDomains: () => Promise; putSettingsDomains: (request: UpdateDomainsRequest) => Promise; + getTwoFactorProviders: () => Promise>; getTwoFactorAuthenticator: (request: PasswordVerificationRequest) => Promise; getTwoFactorEmail: (request: PasswordVerificationRequest) => Promise; @@ -148,6 +160,7 @@ export abstract class ApiService { postTwoFactorRecover: (request: TwoFactorRecoveryRequest) => Promise; postTwoFactorEmailSetup: (request: TwoFactorEmailRequest) => Promise; postTwoFactorEmail: (request: TwoFactorEmailRequest) => Promise; + postOrganization: (request: OrganizationCreateRequest) => Promise; postLeaveOrganization: (id: string) => Promise; postOrganizationLicense: (data: FormData) => Promise; diff --git a/src/abstractions/collection.service.ts b/src/abstractions/collection.service.ts index 64bf22def6..a6decc2c09 100644 --- a/src/abstractions/collection.service.ts +++ b/src/abstractions/collection.service.ts @@ -17,5 +17,4 @@ export abstract class CollectionService { replace: (collections: { [id: string]: CollectionData; }) => Promise; clear: (userId: string) => Promise; delete: (id: string | string[]) => Promise; - getLocaleSortingFunction: () => (a: CollectionView, b: CollectionView) => number; } diff --git a/src/misc/utils.ts b/src/misc/utils.ts index 637330ea34..b507f2aba1 100644 --- a/src/misc/utils.ts +++ b/src/misc/utils.ts @@ -1,3 +1,5 @@ +import { I18nService } from '../abstractions/i18n.service'; + // tslint:disable-next-line const nodeURL = typeof window === 'undefined' ? require('url').URL : null; @@ -149,6 +151,23 @@ export class Utils { return url != null ? url.host : null; } + static getSortFunction(i18nService: I18nService, prop: string) { + return (a: any, b: any) => { + if (a[prop] == null && b[prop] != null) { + return -1; + } + if (a[prop] != null && b[prop] == null) { + return 1; + } + if (a[prop] == null && b[prop] == null) { + return 0; + } + + return i18nService.collator ? i18nService.collator.compare(a[prop], b[prop]) : + a[prop].localeCompare(b[prop]); + }; + } + private static getUrl(uriString: string): URL { if (uriString == null) { return null; diff --git a/src/models/response/organizationUserResponse.ts b/src/models/response/organizationUserResponse.ts new file mode 100644 index 0000000000..12006b665d --- /dev/null +++ b/src/models/response/organizationUserResponse.ts @@ -0,0 +1,41 @@ +import { OrganizationUserStatusType } from '../../enums/organizationUserStatusType'; +import { OrganizationUserType } from '../../enums/organizationUserType'; +import { SelectionReadOnlyResponse } from './selectionReadOnlyResponse'; + +export class OrganizationUserResponse { + id: string; + userId: string; + type: OrganizationUserType; + status: OrganizationUserStatusType; + accessAll: boolean; + + constructor(response: any) { + this.id = response.Id; + this.userId = response.UserId; + this.type = response.Type; + this.status = response.Status; + this.accessAll = response.AccessAll; + } +} + +export class OrganizationUserUserDetailsResponse extends OrganizationUserResponse { + name: string; + email: string; + + constructor(response: any) { + super(response); + this.name = response.Name; + this.email = response.Email; + } +} + +export class OrganizationUserDetailsResponse extends OrganizationUserResponse { + collections: SelectionReadOnlyResponse; + + constructor(response: any) { + super(response); + if (response.Collections != null) { + this.collections = response.Collections.map((c: any) => new SelectionReadOnlyResponse(c)); + } + } +} diff --git a/src/services/api.service.ts b/src/services/api.service.ts index e8a1cdedbd..f738e2942e 100644 --- a/src/services/api.service.ts +++ b/src/services/api.service.ts @@ -59,6 +59,7 @@ import { IdentityTokenResponse } from '../models/response/identityTokenResponse' import { IdentityTwoFactorResponse } from '../models/response/identityTwoFactorResponse'; import { ListResponse } from '../models/response/listResponse'; import { OrganizationResponse } from '../models/response/organizationResponse'; +import { OrganizationUserUserDetailsResponse } from '../models/response/organizationUserResponse'; import { ProfileResponse } from '../models/response/profileResponse'; import { SyncResponse } from '../models/response/syncResponse'; import { TwoFactorAuthenticatorResponse } from '../models/response/twoFactorAuthenticatorResponse'; @@ -425,6 +426,13 @@ export class ApiService implements ApiServiceAbstraction { return this.send('DELETE', '/groups/' + id, null, true, false); } + // Organization User APIs + + async getOrganizationUsers(organizationId: string): Promise> { + const r = await this.send('GET', '/organizations/' + organizationId + '/users', null, true, true); + return new ListResponse(r, OrganizationUserUserDetailsResponse); + } + // Sync APIs async getSync(): Promise { diff --git a/src/services/collection.service.ts b/src/services/collection.service.ts index ce26f72dcc..152d91713b 100644 --- a/src/services/collection.service.ts +++ b/src/services/collection.service.ts @@ -10,6 +10,8 @@ import { I18nService } from '../abstractions/i18n.service'; import { StorageService } from '../abstractions/storage.service'; import { UserService } from '../abstractions/user.service'; +import { Utils } from '../misc/utils'; + const Keys = { collectionsPrefix: 'collections_', }; @@ -51,7 +53,7 @@ export class CollectionService implements CollectionServiceAbstraction { promises.push(collection.decrypt().then((c) => decCollections.push(c))); }); await Promise.all(promises); - return decCollections.sort(this.getLocaleSortingFunction()); + return decCollections.sort(Utils.getSortFunction(this.i18nService, 'name')); } async get(id: string): Promise { @@ -145,21 +147,4 @@ export class CollectionService implements CollectionServiceAbstraction { await this.storageService.save(Keys.collectionsPrefix + userId, collections); this.decryptedCollectionCache = null; } - - getLocaleSortingFunction(): (a: CollectionView, b: CollectionView) => number { - return (a, b) => { - if (a.name == null && b.name != null) { - return -1; - } - if (a.name != null && b.name == null) { - return 1; - } - if (a.name == null && b.name == null) { - return 0; - } - - return this.i18nService.collator ? this.i18nService.collator.compare(a.name, b.name) : - a.name.localeCompare(b.name); - }; - } } diff --git a/src/services/folder.service.ts b/src/services/folder.service.ts index 51ec8e4bb8..955cc2387a 100644 --- a/src/services/folder.service.ts +++ b/src/services/folder.service.ts @@ -17,6 +17,8 @@ import { StorageService } from '../abstractions/storage.service'; import { UserService } from '../abstractions/user.service'; import { CipherData } from '../models/data/cipherData'; +import { Utils } from '../misc/utils'; + const Keys = { foldersPrefix: 'folders_', ciphersPrefix: 'ciphers_', @@ -82,7 +84,7 @@ export class FolderService implements FolderServiceAbstraction { }); await Promise.all(promises); - decFolders.sort(this.getLocaleSortingFunction()); + decFolders.sort(Utils.getSortFunction(this.i18nService, 'name')); const noneFolder = new FolderView(); noneFolder.name = this.i18nService.t('noneFolder'); @@ -180,21 +182,4 @@ export class FolderService implements FolderServiceAbstraction { await this.apiService.deleteFolder(id); await this.delete(id); } - - private getLocaleSortingFunction(): (a: FolderView, b: FolderView) => number { - return (a, b) => { - if (a.name == null && b.name != null) { - return -1; - } - if (a.name != null && b.name == null) { - return 1; - } - if (a.name == null && b.name == null) { - return 0; - } - - return this.i18nService.collator ? this.i18nService.collator.compare(a.name, b.name) : - a.name.localeCompare(b.name); - }; - } }