1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 08:13:42 +00:00
Files
browser/apps/cli/src/commands/get.command.ts
Jake Fink f9a89916a2 [EC-14] Part II: Add Collection Rows to Vault List (#3875)
* [EC-14] initial refactoring of vault filter

* [EC-14] return observable trees for all filters with head node

* [EC-14] Remove bindings on callbacks

* [EC-14] fix formatting on disabled orgs

* [EC-14] hide MyVault if personal org policy

* [EC-14] add check for single org policy

* [EC-14] add policies to org and change node constructor

* [EC-14] don't show options if personal vault policy

* [EC-14] default to all vaults

* [EC-14] add default selection to filters

* [EC-14] finish filter model callbacks

* [EC-14] finish filter functionality and begin cleaning up

* [EC-14] clean up old components and start on org vault

* [EC-14] loop through filters for presentation

* [EC-14] refactor VaultFilterService and put filter presentation data back into Vault Filter component. Remove VaultService

* [EC-14] begin refactoring org vault

* [EC-14] Refactor Vault Filter Service to use observables

* [EC-14] finish org vault filter

* [EC-14] fix vault model tests

* [EC-14] fix org service calls

* [EC-14] pull refactor out of shared code

* [EC-14] include head node for collections even if collections aren't loaded yet

* [EC-14] fix url params for vaults

* [EC-14] remove comments

* [EC-14] Remove unnecesary getter for org on vault filter

* [EC-14] fix linter

* [EC-14] fix prettier

* [EC-14] add deprecated methods to collection service for desktop and browser

* [EC-14] simplify cipher type node check

* [EC-14] add getters to vault filter model

* [EC-14] refactor how we build the filter list into methods

* [EC-14] add getters to build filter method

* [EC-14] start adding header and collection rows

* [EC-14] remove param ids if false

* [EC-14] Make collection rows navigatable

* [EC-14] fix collapsing nodes

* [EC-14] add specific type to search placeholder

* [EC-14] remove extra constructor and comment from org vault filter

* [EC-14] extract subscription callback to methods

* [EC-14] Remove unecessary await

* [EC-14] Remove ternary operators while building org filter

* [EC-14] remove unnecessary deps array in vault filter service declaration

* [EC-14] consolidate new models into one file

* [EC-14] change name of edit collections method

* [EC-14] add collection badges to item rows

* [EC-14] show groups badge on collection rows

* [EC-14] add bulk actions to header menu button

* [EC-14] initialize nested observable inside of service

Signed-off-by: Jacob Fink <jfink@bitwarden.com>

* [EC-14] change how we load orgs into the vault filter and select the default filter

* [EC-14] remove get from getters name

* [EC-14] remove eslint-disable comment

* [EC-14] move vault filter service abstraction to angular folder and separate

* [EC-14] rename filter types and delete VaultFilterLabel

* [EC-14] remove changes to workspace file

* [EC-14] remove deprecated service from jslib module

* [EC-14] remove any remaining files from common code

* [EC-14] consolidate vault filter components into components folder

* [EC-14] simplify method call

* [EC-14] refactor the vault filter service
- orgs now have observable property
- BehaviorSubjects have been migrated to ReplaySubjects if they don't need starting value
- added unit tests
- fix small error when selecting org badge of personal vault
- renamed some properties

* [EC-14] replace mergeMap with switchMap in vault filter service

* [EC-14] early return to prevent nesting

* [EC-14] clean up filterCollections method

* [EC-14] use isDeleted helper in html

* [EC-14] add jsdoc comments to ServiceUtils

* [EC-14] fix linter

* [EC-14] use array.slice instead of setting length

* [EC-14] resolve merge conflicts

* [EC-14] remove checkbox from end user vault collection rows

* [EC-14] add owner column to collections in end user vault

* [EC-14] add a11y titles for vault filters

* Update apps/web/src/app/vault/vault-filter/services/vault-filter.service.ts

Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>

* [EC-14] add missing high level jsdoc description

* [EC-14] fix storybook absolute imports

* [EC-14] delete vault-shared.module

* [EC-14] change search placeholder text to getter and add missing strings

* [EC-14] remove two way binding from search text in vault filter

* [EC-14] removed all binding from search text and just use input event

* [EC-14] remove async from apply vault filter

* [EC-14] remove circular observable calls in vault filter service

Co-authored-by: Thomas Rittson <eliykat@users.noreply.github.com>

* [EC-14] move collapsed nodes to vault filter section

* [EC-14] deconstruct filter section inside component

* [EC-14] fix merge conflicts and introduce refactored organization service to vault filter service

* [EC-14] remove mutation from filter builders

* [EC-14] fix styling on buildFolderTree

* [EC-14] remove leftover folder-filters reference and use ternary for collapse icon

* [EC-14] remove unecessary checks

* [EC-14] stop rebuilding filters when the organization changes

* [EC-14] Move subscription out of setter in vault filter section

* [EC-14] remove extra policy service methods from vault filter service

* [EC-14] remove new methods from old vault-filter.service

* [EC-14] Use vault filter service in vault components

* [EC-14] reload collections from vault now that we have vault filter service

* [EC-14] remove currentFilterCollections in vault filter component

* [EC-14] change VaultFilterType to more specific OrganizationFilter in organization-options

* [EC-14] include org check in isNodeSelected

* [EC-14] add getters to filter function, fix storybook, and add test for All Collections

* [EC-14] Resolve merge conflicts

* [EC-14] fix merge conflicts

* [EC-14] fix merge conflicts: org service protected and remove absolute path

* [EC-14] separate org vault filter service observables

* [EC-14] remove folder subject in vault filter service

* [EC-14] remove collections subject from vault filter service

* [EC-14] change collection api call name
- getCollectionsWithDetails to getManyCollectionsWithDetails

* [EC-14] add collection functionality
- add endpoint to bulk delete collections
- add logic to bulk delete both ciphers and collections
- refresh ciphers list after making collection changes
- stop making api calls from ciphers list each time a filter changes

* [EC-14] get collections from vault filter service
- for badge, instead of passing through @Input variable

* [EC-14] only bulk delete collections if passed

* [EC-14] fix deleting ciphers in org vault
- reuse same logic from end user vault
- call different api endpoints

* [EC-14] include collections in MaxCheckedCount

* [EC-14] add paging to collections

* [EC-14] hide collections if searching

* [EC-14] change vault table to new table component
- removed a lot of scss classes to use tailwind alternatives
- added getters for arrays in component that template can reference
- imported and used new bitIconButton for options button

* [EC-14] remove cursor pointer when checkbox not available

* [EC-14] stop reloading cipher list too early

* [EC-14] stop setting cipher component to loaded too early
- loaded variable on cipher component hides the loaded indicator
- when setting the default filter, we were triggering that variable
- instead, we'll just set the active filter and let it grab the filter when ready

* [EC-14] check/navigate collection when clicked

* [EC-14] rename edit collections callback
- used to be onEditCollection
- renamed to onEditCipherCollections

* [EC-14] remove showOrganizationBadge property
- property used to tell template whether it was org vault or end user
- replace with check for organization property

* [EC-14] replace || with ?? in load function of ciphers

* [EC-14] remove nested subscriptions
- nested subscriptions = bad
- the only dependency any of the subscriptions have is on the organization
- use withLatestFrom to verify that the org has been set before firing

* [EC-14] add getters and rename method

* [EC-14] add null check in bulk delete component
- some input variables can be null, so we can't just check the length

* [EC-14] add ItemRow type
- ItemRow can be either CipherView or CollectionFilter
- Consolidated a large portion of selection logic

* [EC-14] remove extra applyFilter override
- Removed extra applyFIlter, allCiphers has already been filtered by org
- Also reordered some of the methods to make more sense

* [EC-14] remove extra collections uncheck

* [EC-14] transition bulk delete to dialog service

* [EC-14] transition bulk restore to dialog service

* [EC-14] transition bulk move to dialog service

* [EC-14] transition bulk share to dialog service

* [EC-14] remove modal references

* [EC-14] reload cipher list when changing orgs

* [EC-14] add helper method to bulk delete dialog
- Gives us built in typing instead of having to redeclare

* [EC-14] add helper to open bulk restore dialog
- Gives us typing without redeclaring

* [EC-14] add open helper to bulk move dialog

* [EC-14] add open helper to bulk share dialog
- Adds typing to data
- also removed the component refs from bulk actions

* [EC-14] remove modal service from bulk actions

* [EC-14] introduce VaultItemRow to combine cipher and collections

* [EC-14] show loading indicator while switching orgs

* [EC-14] remove indexing every time filter changes
- also reverted back to using setter for changing org

* [EC-14] allow searching by function in search pipe
- this allows us to search parent properties in objects

Co-authored-by: Andreas Coroiu <andreas@andreascoroiu.com>

* [EC-14] make collections searchable
- used search pipe to filter based on search text

* [EC-14] consolidate bulk dialogs in single module

* [EC-14] remove form promise from bulk dialogs

* [EC-14] stop casting dialog return type
- we now have a helper function that gives us typing on result

* [EC-14] add length check to array guard

* [EC-14] remove extra false assignment

* [EC-14] move to sentence case

* [EC-14] address pr feedback

* [EC-14] add back the default assignment to deleted
- we need this default assignment to check for null or undefined values

* [EC-14] remove optional chaining
- everything is initialized to an empty array so it should never be null

* [EC-14] remove manager check to show org vault
- this is fixed upstream in a more comprehensive way

* [EC-686] add tests and comments to serviceUtils (#4092)

* [EC-686] add tests and comments to serviceUtls

* [EC-686] whitelist spec filename from linter

* [EC-686] fix prettier

* [EC-14] use new collection admin service

* [EC-14] fix groups searching

* [EC-14] use new groups service and models

* [EC-14] fix shared module

* [EC-14] remove leftover empty vault filter service

* [EC-14] remove CollectionGroupDetailsView models

* [EC-14] replace GroupDetails with AdminView
- Collections in vault filter now use admin view to get access details
- Collections shown in cipher list use admin view for access details

* [EC-14] add back the dialog to shared module

* [EC-14] hide org vault if lacking permissions

* [EC-14] add edit collection dialog to vault

* [EC-14] add screen reader label to share dialog

* [EC-14] moved sync call below subscription
- the subscription gives a callback for when we finish a sync
- by awaiting the sync before we weren't using the callback to refresh

* [EC-14] move cipher params check to switchMap
- we want to avoid async subscriptions

* [EC-14] clean up subscriptions in org vault
- added takeUntil
- use combineLatest

* [EC-14] clean up vault subscriptions
- remove nested subscriptions
- use takeUntil

* [EC-14] init ciphers component first

* [EC-14] fix view vault tab permissions
- CanViewAssignedCollections doesn't include CanViewAllCollections
- CanViewAssignedCollections does include IsManager

* [EC-14] reduce nesting

* [EC-14] rename bulk action dialogs selectors

* [EC-14] fix permissions for collection management
- users with custom admin permissions should be able to edit as well

* [EC-14] prettier

* [EC-14] use percentages for table columns widths

* [EC-14] use GetCollectionAccessDetails in cli
- renamed api call

Signed-off-by: Jacob Fink <jfink@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Thomas Rittson <eliykat@users.noreply.github.com>
Co-authored-by: Andreas Coroiu <andreas@andreascoroiu.com>
2022-12-19 12:40:00 -05:00

541 lines
18 KiB
TypeScript

import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
import { CollectionService } from "@bitwarden/common/abstractions/collection.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { FolderService } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
import { CipherType } from "@bitwarden/common/enums/cipherType";
import { SendType } from "@bitwarden/common/enums/sendType";
import { Utils } from "@bitwarden/common/misc/utils";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { CardExport } from "@bitwarden/common/models/export/card.export";
import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
import { FieldExport } from "@bitwarden/common/models/export/field.export";
import { FolderExport } from "@bitwarden/common/models/export/folder.export";
import { IdentityExport } from "@bitwarden/common/models/export/identity.export";
import { LoginUriExport } from "@bitwarden/common/models/export/login-uri.export";
import { LoginExport } from "@bitwarden/common/models/export/login.export";
import { SecureNoteExport } from "@bitwarden/common/models/export/secure-note.export";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { CipherView } from "@bitwarden/common/models/view/cipher.view";
import { CollectionView } from "@bitwarden/common/models/view/collection.view";
import { FolderView } from "@bitwarden/common/models/view/folder.view";
import { OrganizationCollectionRequest } from "../models/request/organization-collection.request";
import { Response } from "../models/response";
import { CipherResponse } from "../models/response/cipher.response";
import { CollectionResponse } from "../models/response/collection.response";
import { FolderResponse } from "../models/response/folder.response";
import { OrganizationCollectionResponse } from "../models/response/organization-collection.response";
import { OrganizationResponse } from "../models/response/organization.response";
import { SendResponse } from "../models/response/send.response";
import { StringResponse } from "../models/response/string.response";
import { TemplateResponse } from "../models/response/template.response";
import { SelectionReadOnly } from "../models/selection-read-only";
import { CliUtils } from "../utils";
import { DownloadCommand } from "./download.command";
export class GetCommand extends DownloadCommand {
constructor(
private cipherService: CipherService,
private folderService: FolderService,
private collectionService: CollectionService,
private totpService: TotpService,
private auditService: AuditService,
cryptoService: CryptoService,
private stateService: StateService,
private searchService: SearchService,
private apiService: ApiService,
private organizationService: OrganizationService
) {
super(cryptoService);
}
async run(object: string, id: string, cmdOptions: Record<string, any>): Promise<Response> {
if (id != null) {
id = id.toLowerCase();
}
const normalizedOptions = new Options(cmdOptions);
switch (object.toLowerCase()) {
case "item":
return await this.getCipher(id);
case "username":
return await this.getUsername(id);
case "password":
return await this.getPassword(id);
case "uri":
return await this.getUri(id);
case "totp":
return await this.getTotp(id);
case "notes":
return await this.getNotes(id);
case "exposed":
return await this.getExposed(id);
case "attachment":
return await this.getAttachment(id, normalizedOptions);
case "folder":
return await this.getFolder(id);
case "collection":
return await this.getCollection(id);
case "org-collection":
return await this.getOrganizationCollection(id, normalizedOptions);
case "organization":
return await this.getOrganization(id);
case "template":
return await this.getTemplate(id);
case "fingerprint":
return await this.getFingerprint(id);
default:
return Response.badRequest("Unknown object.");
}
}
private async getCipherView(id: string): Promise<CipherView | CipherView[]> {
let decCipher: CipherView = null;
if (Utils.isGuid(id)) {
const cipher = await this.cipherService.get(id);
if (cipher != null) {
decCipher = await cipher.decrypt();
}
} else if (id.trim() !== "") {
let ciphers = await this.cipherService.getAllDecrypted();
ciphers = this.searchService.searchCiphersBasic(ciphers, id);
if (ciphers.length > 1) {
return ciphers;
}
if (ciphers.length > 0) {
decCipher = ciphers[0];
}
}
return decCipher;
}
private async getCipher(id: string, filter?: (c: CipherView) => boolean) {
let decCipher = await this.getCipherView(id);
if (decCipher == null) {
return Response.notFound();
}
if (Array.isArray(decCipher)) {
if (filter != null) {
decCipher = decCipher.filter(filter);
if (decCipher.length === 1) {
decCipher = decCipher[0];
}
}
if (Array.isArray(decCipher)) {
return Response.multipleResults(decCipher.map((c) => c.id));
}
}
const res = new CipherResponse(decCipher);
return Response.success(res);
}
private async getUsername(id: string) {
const cipherResponse = await this.getCipher(
id,
(c) => c.type === CipherType.Login && !Utils.isNullOrWhitespace(c.login.username)
);
if (!cipherResponse.success) {
return cipherResponse;
}
const cipher = cipherResponse.data as CipherResponse;
if (cipher.type !== CipherType.Login) {
return Response.badRequest("Not a login.");
}
if (Utils.isNullOrWhitespace(cipher.login.username)) {
return Response.error("No username available for this login.");
}
const res = new StringResponse(cipher.login.username);
return Response.success(res);
}
private async getPassword(id: string) {
const cipherResponse = await this.getCipher(
id,
(c) => c.type === CipherType.Login && !Utils.isNullOrWhitespace(c.login.password)
);
if (!cipherResponse.success) {
return cipherResponse;
}
const cipher = cipherResponse.data as CipherResponse;
if (cipher.type !== CipherType.Login) {
return Response.badRequest("Not a login.");
}
if (Utils.isNullOrWhitespace(cipher.login.password)) {
return Response.error("No password available for this login.");
}
const res = new StringResponse(cipher.login.password);
return Response.success(res);
}
private async getUri(id: string) {
const cipherResponse = await this.getCipher(
id,
(c) =>
c.type === CipherType.Login &&
c.login.uris != null &&
c.login.uris.length > 0 &&
c.login.uris[0].uri !== ""
);
if (!cipherResponse.success) {
return cipherResponse;
}
const cipher = cipherResponse.data as CipherResponse;
if (cipher.type !== CipherType.Login) {
return Response.badRequest("Not a login.");
}
if (
cipher.login.uris == null ||
cipher.login.uris.length === 0 ||
cipher.login.uris[0].uri === ""
) {
return Response.error("No uri available for this login.");
}
const res = new StringResponse(cipher.login.uris[0].uri);
return Response.success(res);
}
private async getTotp(id: string) {
const cipherResponse = await this.getCipher(
id,
(c) => c.type === CipherType.Login && !Utils.isNullOrWhitespace(c.login.totp)
);
if (!cipherResponse.success) {
return cipherResponse;
}
const cipher = cipherResponse.data as CipherResponse;
if (cipher.type !== CipherType.Login) {
return Response.badRequest("Not a login.");
}
if (Utils.isNullOrWhitespace(cipher.login.totp)) {
return Response.error("No TOTP available for this login.");
}
const totp = await this.totpService.getCode(cipher.login.totp);
if (totp == null) {
return Response.error("Couldn't generate TOTP code.");
}
const canAccessPremium = await this.stateService.getCanAccessPremium();
if (!canAccessPremium) {
const originalCipher = await this.cipherService.get(cipher.id);
if (
originalCipher == null ||
originalCipher.organizationId == null ||
!originalCipher.organizationUseTotp
) {
return Response.error("Premium status is required to use this feature.");
}
}
const res = new StringResponse(totp);
return Response.success(res);
}
private async getNotes(id: string) {
const cipherResponse = await this.getCipher(id, (c) => !Utils.isNullOrWhitespace(c.notes));
if (!cipherResponse.success) {
return cipherResponse;
}
const cipher = cipherResponse.data as CipherResponse;
if (Utils.isNullOrWhitespace(cipher.notes)) {
return Response.error("No notes available for this item.");
}
const res = new StringResponse(cipher.notes);
return Response.success(res);
}
private async getExposed(id: string) {
const passwordResponse = await this.getPassword(id);
if (!passwordResponse.success) {
return passwordResponse;
}
const exposedNumber = await this.auditService.passwordLeaked(
(passwordResponse.data as StringResponse).data
);
const res = new StringResponse(exposedNumber.toString());
return Response.success(res);
}
private async getAttachment(id: string, options: Options) {
if (options.itemId == null || options.itemId === "") {
return Response.badRequest("--itemid <itemid> required.");
}
const itemId = options.itemId.toLowerCase();
const cipherResponse = await this.getCipher(itemId);
if (!cipherResponse.success) {
return cipherResponse;
}
const cipher = await this.getCipherView(itemId);
if (
cipher == null ||
Array.isArray(cipher) ||
cipher.attachments == null ||
cipher.attachments.length === 0
) {
return Response.error("No attachments available for this item.");
}
let attachments = cipher.attachments.filter(
(a) =>
a.id.toLowerCase() === id ||
(a.fileName != null && a.fileName.toLowerCase().indexOf(id) > -1)
);
if (attachments.length === 0) {
return Response.error("Attachment `" + id + "` was not found.");
}
const exactMatches = attachments.filter((a) => a.fileName.toLowerCase() === id);
if (exactMatches.length === 1) {
attachments = exactMatches;
}
if (attachments.length > 1) {
return Response.multipleResults(attachments.map((a) => a.id));
}
if (!(await this.stateService.getCanAccessPremium())) {
const originalCipher = await this.cipherService.get(cipher.id);
if (originalCipher == null || originalCipher.organizationId == null) {
return Response.error("Premium status is required to use this feature.");
}
}
let url: string;
try {
const attachmentDownloadResponse = await this.apiService.getAttachmentData(
cipher.id,
attachments[0].id
);
url = attachmentDownloadResponse.url;
} catch (e) {
if (e instanceof ErrorResponse && (e as ErrorResponse).statusCode === 404) {
url = attachments[0].url;
} else if (e instanceof ErrorResponse) {
throw new Error((e as ErrorResponse).getSingleMessage());
} else {
throw e;
}
}
const key =
attachments[0].key != null
? attachments[0].key
: await this.cryptoService.getOrgKey(cipher.organizationId);
return await this.saveAttachmentToFile(url, key, attachments[0].fileName, options.output);
}
private async getFolder(id: string) {
let decFolder: FolderView = null;
if (Utils.isGuid(id)) {
const folder = await this.folderService.getFromState(id);
if (folder != null) {
decFolder = await folder.decrypt();
}
} else if (id.trim() !== "") {
let folders = await this.folderService.getAllDecryptedFromState();
folders = CliUtils.searchFolders(folders, id);
if (folders.length > 1) {
return Response.multipleResults(folders.map((f) => f.id));
}
if (folders.length > 0) {
decFolder = folders[0];
}
}
if (decFolder == null) {
return Response.notFound();
}
const res = new FolderResponse(decFolder);
return Response.success(res);
}
private async getCollection(id: string) {
let decCollection: CollectionView = null;
if (Utils.isGuid(id)) {
const collection = await this.collectionService.get(id);
if (collection != null) {
decCollection = await collection.decrypt();
}
} else if (id.trim() !== "") {
let collections = await this.collectionService.getAllDecrypted();
collections = CliUtils.searchCollections(collections, id);
if (collections.length > 1) {
return Response.multipleResults(collections.map((c) => c.id));
}
if (collections.length > 0) {
decCollection = collections[0];
}
}
if (decCollection == null) {
return Response.notFound();
}
const res = new CollectionResponse(decCollection);
return Response.success(res);
}
private async getOrganizationCollection(id: string, options: Options) {
if (options.organizationId == null || options.organizationId === "") {
return Response.badRequest("`organizationid` option is required.");
}
if (!Utils.isGuid(id)) {
return Response.badRequest("`" + id + "` is not a GUID.");
}
if (!Utils.isGuid(options.organizationId)) {
return Response.badRequest("`" + options.organizationId + "` is not a GUID.");
}
try {
const orgKey = await this.cryptoService.getOrgKey(options.organizationId);
if (orgKey == null) {
throw new Error("No encryption key for this organization.");
}
const response = await this.apiService.getCollectionAccessDetails(options.organizationId, id);
const decCollection = new CollectionView(response);
decCollection.name = await this.cryptoService.decryptToUtf8(
new EncString(response.name),
orgKey
);
const groups =
response.groups == null
? null
: response.groups.map((g) => new SelectionReadOnly(g.id, g.readOnly, g.hidePasswords));
const res = new OrganizationCollectionResponse(decCollection, groups);
return Response.success(res);
} catch (e) {
return Response.error(e);
}
}
private async getOrganization(id: string) {
let org: Organization = null;
if (Utils.isGuid(id)) {
org = await this.organizationService.getFromState(id);
} else if (id.trim() !== "") {
let orgs = await this.organizationService.getAll();
orgs = CliUtils.searchOrganizations(orgs, id);
if (orgs.length > 1) {
return Response.multipleResults(orgs.map((c) => c.id));
}
if (orgs.length > 0) {
org = orgs[0];
}
}
if (org == null) {
return Response.notFound();
}
const res = new OrganizationResponse(org);
return Response.success(res);
}
private async getTemplate(id: string) {
let template: any = null;
switch (id.toLowerCase()) {
case "item":
template = CipherExport.template();
break;
case "item.field":
template = FieldExport.template();
break;
case "item.login":
template = LoginExport.template();
break;
case "item.login.uri":
template = LoginUriExport.template();
break;
case "item.card":
template = CardExport.template();
break;
case "item.identity":
template = IdentityExport.template();
break;
case "item.securenote":
template = SecureNoteExport.template();
break;
case "folder":
template = FolderExport.template();
break;
case "collection":
template = CollectionExport.template();
break;
case "item-collections":
template = ["collection-id1", "collection-id2"];
break;
case "org-collection":
template = OrganizationCollectionRequest.template();
break;
case "send.text":
template = SendResponse.template(SendType.Text);
break;
case "send.file":
template = SendResponse.template(SendType.File);
break;
default:
return Response.badRequest("Unknown template object.");
}
const res = new TemplateResponse(template);
return Response.success(res);
}
private async getFingerprint(id: string) {
let fingerprint: string[] = null;
if (id === "me") {
fingerprint = await this.cryptoService.getFingerprint(await this.stateService.getUserId());
} else if (Utils.isGuid(id)) {
try {
const response = await this.apiService.getUserPublicKey(id);
const pubKey = Utils.fromB64ToArray(response.publicKey);
fingerprint = await this.cryptoService.getFingerprint(id, pubKey.buffer);
} catch {
// eslint-disable-next-line
}
}
if (fingerprint == null) {
return Response.notFound();
}
const res = new StringResponse(fingerprint.join("-"));
return Response.success(res);
}
}
class Options {
itemId: string;
organizationId: string;
output: string;
constructor(passedOptions: Record<string, any>) {
this.organizationId = passedOptions?.organizationid || passedOptions?.organizationId;
this.itemId = passedOptions?.itemid || passedOptions?.itemId;
this.output = passedOptions?.output;
}
}