mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 23:33:31 +00:00
Move to libs
This commit is contained in:
577
libs/angular/src/components/add-edit.component.ts
Normal file
577
libs/angular/src/components/add-edit.component.ts
Normal file
@@ -0,0 +1,577 @@
|
||||
import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core";
|
||||
|
||||
import { AuditService } from "jslib-common/abstractions/audit.service";
|
||||
import { CipherService } from "jslib-common/abstractions/cipher.service";
|
||||
import { CollectionService } from "jslib-common/abstractions/collection.service";
|
||||
import { EventService } from "jslib-common/abstractions/event.service";
|
||||
import { FolderService } from "jslib-common/abstractions/folder.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { OrganizationService } from "jslib-common/abstractions/organization.service";
|
||||
import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { PolicyService } from "jslib-common/abstractions/policy.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType";
|
||||
import { CipherType } from "jslib-common/enums/cipherType";
|
||||
import { EventType } from "jslib-common/enums/eventType";
|
||||
import { OrganizationUserStatusType } from "jslib-common/enums/organizationUserStatusType";
|
||||
import { PolicyType } from "jslib-common/enums/policyType";
|
||||
import { SecureNoteType } from "jslib-common/enums/secureNoteType";
|
||||
import { UriMatchType } from "jslib-common/enums/uriMatchType";
|
||||
import { Utils } from "jslib-common/misc/utils";
|
||||
import { Cipher } from "jslib-common/models/domain/cipher";
|
||||
import { CardView } from "jslib-common/models/view/cardView";
|
||||
import { CipherView } from "jslib-common/models/view/cipherView";
|
||||
import { CollectionView } from "jslib-common/models/view/collectionView";
|
||||
import { FolderView } from "jslib-common/models/view/folderView";
|
||||
import { IdentityView } from "jslib-common/models/view/identityView";
|
||||
import { LoginUriView } from "jslib-common/models/view/loginUriView";
|
||||
import { LoginView } from "jslib-common/models/view/loginView";
|
||||
import { SecureNoteView } from "jslib-common/models/view/secureNoteView";
|
||||
|
||||
@Directive()
|
||||
export class AddEditComponent implements OnInit {
|
||||
@Input() cloneMode = false;
|
||||
@Input() folderId: string = null;
|
||||
@Input() cipherId: string;
|
||||
@Input() type: CipherType;
|
||||
@Input() collectionIds: string[];
|
||||
@Input() organizationId: string = null;
|
||||
@Output() onSavedCipher = new EventEmitter<CipherView>();
|
||||
@Output() onDeletedCipher = new EventEmitter<CipherView>();
|
||||
@Output() onRestoredCipher = new EventEmitter<CipherView>();
|
||||
@Output() onCancelled = new EventEmitter<CipherView>();
|
||||
@Output() onEditAttachments = new EventEmitter<CipherView>();
|
||||
@Output() onShareCipher = new EventEmitter<CipherView>();
|
||||
@Output() onEditCollections = new EventEmitter<CipherView>();
|
||||
@Output() onGeneratePassword = new EventEmitter();
|
||||
@Output() onGenerateUsername = new EventEmitter();
|
||||
|
||||
editMode = false;
|
||||
cipher: CipherView;
|
||||
folders: FolderView[];
|
||||
collections: CollectionView[] = [];
|
||||
title: string;
|
||||
formPromise: Promise<any>;
|
||||
deletePromise: Promise<any>;
|
||||
restorePromise: Promise<any>;
|
||||
checkPasswordPromise: Promise<number>;
|
||||
showPassword = false;
|
||||
showCardNumber = false;
|
||||
showCardCode = false;
|
||||
cipherType = CipherType;
|
||||
typeOptions: any[];
|
||||
cardBrandOptions: any[];
|
||||
cardExpMonthOptions: any[];
|
||||
identityTitleOptions: any[];
|
||||
uriMatchOptions: any[];
|
||||
ownershipOptions: any[] = [];
|
||||
autofillOnPageLoadOptions: any[];
|
||||
currentDate = new Date();
|
||||
allowPersonal = true;
|
||||
reprompt = false;
|
||||
canUseReprompt = true;
|
||||
|
||||
protected writeableCollections: CollectionView[];
|
||||
private previousCipherId: string;
|
||||
|
||||
constructor(
|
||||
protected cipherService: CipherService,
|
||||
protected folderService: FolderService,
|
||||
protected i18nService: I18nService,
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected auditService: AuditService,
|
||||
protected stateService: StateService,
|
||||
protected collectionService: CollectionService,
|
||||
protected messagingService: MessagingService,
|
||||
protected eventService: EventService,
|
||||
protected policyService: PolicyService,
|
||||
private logService: LogService,
|
||||
protected passwordRepromptService: PasswordRepromptService,
|
||||
private organizationService: OrganizationService
|
||||
) {
|
||||
this.typeOptions = [
|
||||
{ name: i18nService.t("typeLogin"), value: CipherType.Login },
|
||||
{ name: i18nService.t("typeCard"), value: CipherType.Card },
|
||||
{ name: i18nService.t("typeIdentity"), value: CipherType.Identity },
|
||||
{ name: i18nService.t("typeSecureNote"), value: CipherType.SecureNote },
|
||||
];
|
||||
this.cardBrandOptions = [
|
||||
{ name: "-- " + i18nService.t("select") + " --", value: null },
|
||||
{ name: "Visa", value: "Visa" },
|
||||
{ name: "Mastercard", value: "Mastercard" },
|
||||
{ name: "American Express", value: "Amex" },
|
||||
{ name: "Discover", value: "Discover" },
|
||||
{ name: "Diners Club", value: "Diners Club" },
|
||||
{ name: "JCB", value: "JCB" },
|
||||
{ name: "Maestro", value: "Maestro" },
|
||||
{ name: "UnionPay", value: "UnionPay" },
|
||||
{ name: "RuPay", value: "RuPay" },
|
||||
{ name: i18nService.t("other"), value: "Other" },
|
||||
];
|
||||
this.cardExpMonthOptions = [
|
||||
{ name: "-- " + i18nService.t("select") + " --", value: null },
|
||||
{ name: "01 - " + i18nService.t("january"), value: "1" },
|
||||
{ name: "02 - " + i18nService.t("february"), value: "2" },
|
||||
{ name: "03 - " + i18nService.t("march"), value: "3" },
|
||||
{ name: "04 - " + i18nService.t("april"), value: "4" },
|
||||
{ name: "05 - " + i18nService.t("may"), value: "5" },
|
||||
{ name: "06 - " + i18nService.t("june"), value: "6" },
|
||||
{ name: "07 - " + i18nService.t("july"), value: "7" },
|
||||
{ name: "08 - " + i18nService.t("august"), value: "8" },
|
||||
{ name: "09 - " + i18nService.t("september"), value: "9" },
|
||||
{ name: "10 - " + i18nService.t("october"), value: "10" },
|
||||
{ name: "11 - " + i18nService.t("november"), value: "11" },
|
||||
{ name: "12 - " + i18nService.t("december"), value: "12" },
|
||||
];
|
||||
this.identityTitleOptions = [
|
||||
{ name: "-- " + i18nService.t("select") + " --", value: null },
|
||||
{ name: i18nService.t("mr"), value: i18nService.t("mr") },
|
||||
{ name: i18nService.t("mrs"), value: i18nService.t("mrs") },
|
||||
{ name: i18nService.t("ms"), value: i18nService.t("ms") },
|
||||
{ name: i18nService.t("dr"), value: i18nService.t("dr") },
|
||||
];
|
||||
this.uriMatchOptions = [
|
||||
{ name: i18nService.t("defaultMatchDetection"), value: null },
|
||||
{ name: i18nService.t("baseDomain"), value: UriMatchType.Domain },
|
||||
{ name: i18nService.t("host"), value: UriMatchType.Host },
|
||||
{ name: i18nService.t("startsWith"), value: UriMatchType.StartsWith },
|
||||
{ name: i18nService.t("regEx"), value: UriMatchType.RegularExpression },
|
||||
{ name: i18nService.t("exact"), value: UriMatchType.Exact },
|
||||
{ name: i18nService.t("never"), value: UriMatchType.Never },
|
||||
];
|
||||
this.autofillOnPageLoadOptions = [
|
||||
{ name: i18nService.t("autoFillOnPageLoadUseDefault"), value: null },
|
||||
{ name: i18nService.t("autoFillOnPageLoadYes"), value: true },
|
||||
{ name: i18nService.t("autoFillOnPageLoadNo"), value: false },
|
||||
];
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
if (this.ownershipOptions.length) {
|
||||
this.ownershipOptions = [];
|
||||
}
|
||||
if (await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership)) {
|
||||
this.allowPersonal = false;
|
||||
} else {
|
||||
const myEmail = await this.stateService.getEmail();
|
||||
this.ownershipOptions.push({ name: myEmail, value: null });
|
||||
}
|
||||
|
||||
const orgs = await this.organizationService.getAll();
|
||||
orgs.sort(Utils.getSortFunction(this.i18nService, "name")).forEach((o) => {
|
||||
if (o.enabled && o.status === OrganizationUserStatusType.Confirmed) {
|
||||
this.ownershipOptions.push({ name: o.name, value: o.id });
|
||||
}
|
||||
});
|
||||
if (!this.allowPersonal) {
|
||||
this.organizationId = this.ownershipOptions[0].value;
|
||||
}
|
||||
|
||||
this.writeableCollections = await this.loadCollections();
|
||||
|
||||
this.canUseReprompt = await this.passwordRepromptService.enabled();
|
||||
}
|
||||
|
||||
async load() {
|
||||
this.editMode = this.cipherId != null;
|
||||
if (this.editMode) {
|
||||
this.editMode = true;
|
||||
if (this.cloneMode) {
|
||||
this.cloneMode = true;
|
||||
this.title = this.i18nService.t("addItem");
|
||||
} else {
|
||||
this.title = this.i18nService.t("editItem");
|
||||
}
|
||||
} else {
|
||||
this.title = this.i18nService.t("addItem");
|
||||
}
|
||||
|
||||
const addEditCipherInfo: any = await this.stateService.getAddEditCipherInfo();
|
||||
if (addEditCipherInfo != null) {
|
||||
this.cipher = addEditCipherInfo.cipher;
|
||||
this.collectionIds = addEditCipherInfo.collectionIds;
|
||||
}
|
||||
await this.stateService.setAddEditCipherInfo(null);
|
||||
|
||||
if (this.cipher == null) {
|
||||
if (this.editMode) {
|
||||
const cipher = await this.loadCipher();
|
||||
this.cipher = await cipher.decrypt();
|
||||
|
||||
// Adjust Cipher Name if Cloning
|
||||
if (this.cloneMode) {
|
||||
this.cipher.name += " - " + this.i18nService.t("clone");
|
||||
// If not allowing personal ownership, update cipher's org Id to prompt downstream changes
|
||||
if (this.cipher.organizationId == null && !this.allowPersonal) {
|
||||
this.cipher.organizationId = this.organizationId;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.cipher = new CipherView();
|
||||
this.cipher.organizationId = this.organizationId == null ? null : this.organizationId;
|
||||
this.cipher.folderId = this.folderId;
|
||||
this.cipher.type = this.type == null ? CipherType.Login : this.type;
|
||||
this.cipher.login = new LoginView();
|
||||
this.cipher.login.uris = [new LoginUriView()];
|
||||
this.cipher.card = new CardView();
|
||||
this.cipher.identity = new IdentityView();
|
||||
this.cipher.secureNote = new SecureNoteView();
|
||||
this.cipher.secureNote.type = SecureNoteType.Generic;
|
||||
this.cipher.reprompt = CipherRepromptType.None;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.cipher != null && (!this.editMode || addEditCipherInfo != null || this.cloneMode)) {
|
||||
await this.organizationChanged();
|
||||
if (
|
||||
this.collectionIds != null &&
|
||||
this.collectionIds.length > 0 &&
|
||||
this.collections.length > 0
|
||||
) {
|
||||
this.collections.forEach((c) => {
|
||||
if (this.collectionIds.indexOf(c.id) > -1) {
|
||||
(c as any).checked = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.folders = await this.folderService.getAllDecrypted();
|
||||
|
||||
if (this.editMode && this.previousCipherId !== this.cipherId) {
|
||||
this.eventService.collect(EventType.Cipher_ClientViewed, this.cipherId);
|
||||
}
|
||||
this.previousCipherId = this.cipherId;
|
||||
this.reprompt = this.cipher.reprompt !== CipherRepromptType.None;
|
||||
}
|
||||
|
||||
async submit(): Promise<boolean> {
|
||||
if (this.cipher.isDeleted) {
|
||||
return this.restore();
|
||||
}
|
||||
|
||||
if (this.cipher.name == null || this.cipher.name === "") {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("nameRequired")
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
(!this.editMode || this.cloneMode) &&
|
||||
!this.allowPersonal &&
|
||||
this.cipher.organizationId == null
|
||||
) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("personalOwnershipSubmitError")
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
(!this.editMode || this.cloneMode) &&
|
||||
this.cipher.type === CipherType.Login &&
|
||||
this.cipher.login.uris != null &&
|
||||
this.cipher.login.uris.length === 1 &&
|
||||
(this.cipher.login.uris[0].uri == null || this.cipher.login.uris[0].uri === "")
|
||||
) {
|
||||
this.cipher.login.uris = null;
|
||||
}
|
||||
|
||||
// Allows saving of selected collections during "Add" and "Clone" flows
|
||||
if ((!this.editMode || this.cloneMode) && this.cipher.organizationId != null) {
|
||||
this.cipher.collectionIds =
|
||||
this.collections == null
|
||||
? []
|
||||
: this.collections.filter((c) => (c as any).checked).map((c) => c.id);
|
||||
}
|
||||
|
||||
// Clear current Cipher Id to trigger "Add" cipher flow
|
||||
if (this.cloneMode) {
|
||||
this.cipher.id = null;
|
||||
}
|
||||
|
||||
const cipher = await this.encryptCipher();
|
||||
try {
|
||||
this.formPromise = this.saveCipher(cipher);
|
||||
await this.formPromise;
|
||||
this.cipher.id = cipher.id;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t(this.editMode && !this.cloneMode ? "editedItem" : "addedItem")
|
||||
);
|
||||
this.onSavedCipher.emit(this.cipher);
|
||||
this.messagingService.send(this.editMode && !this.cloneMode ? "editedCipher" : "addedCipher");
|
||||
return true;
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
addUri() {
|
||||
if (this.cipher.type !== CipherType.Login) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.cipher.login.uris == null) {
|
||||
this.cipher.login.uris = [];
|
||||
}
|
||||
|
||||
this.cipher.login.uris.push(new LoginUriView());
|
||||
}
|
||||
|
||||
removeUri(uri: LoginUriView) {
|
||||
if (this.cipher.type !== CipherType.Login || this.cipher.login.uris == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const i = this.cipher.login.uris.indexOf(uri);
|
||||
if (i > -1) {
|
||||
this.cipher.login.uris.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
trackByFunction(index: number, item: any) {
|
||||
return index;
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.onCancelled.emit(this.cipher);
|
||||
}
|
||||
|
||||
attachments() {
|
||||
this.onEditAttachments.emit(this.cipher);
|
||||
}
|
||||
|
||||
share() {
|
||||
this.onShareCipher.emit(this.cipher);
|
||||
}
|
||||
|
||||
editCollections() {
|
||||
this.onEditCollections.emit(this.cipher);
|
||||
}
|
||||
|
||||
async delete(): Promise<boolean> {
|
||||
const confirmed = await this.platformUtilsService.showDialog(
|
||||
this.i18nService.t(
|
||||
this.cipher.isDeleted ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation"
|
||||
),
|
||||
this.i18nService.t("deleteItem"),
|
||||
this.i18nService.t("yes"),
|
||||
this.i18nService.t("no"),
|
||||
"warning"
|
||||
);
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
this.deletePromise = this.deleteCipher();
|
||||
await this.deletePromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t(this.cipher.isDeleted ? "permanentlyDeletedItem" : "deletedItem")
|
||||
);
|
||||
this.onDeletedCipher.emit(this.cipher);
|
||||
this.messagingService.send(
|
||||
this.cipher.isDeleted ? "permanentlyDeletedCipher" : "deletedCipher"
|
||||
);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async restore(): Promise<boolean> {
|
||||
if (!this.cipher.isDeleted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const confirmed = await this.platformUtilsService.showDialog(
|
||||
this.i18nService.t("restoreItemConfirmation"),
|
||||
this.i18nService.t("restoreItem"),
|
||||
this.i18nService.t("yes"),
|
||||
this.i18nService.t("no"),
|
||||
"warning"
|
||||
);
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
this.restorePromise = this.restoreCipher();
|
||||
await this.restorePromise;
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("restoredItem"));
|
||||
this.onRestoredCipher.emit(this.cipher);
|
||||
this.messagingService.send("restoredCipher");
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async generateUsername(): Promise<boolean> {
|
||||
if (this.cipher.login?.username?.length) {
|
||||
const confirmed = await this.platformUtilsService.showDialog(
|
||||
this.i18nService.t("overwriteUsernameConfirmation"),
|
||||
this.i18nService.t("overwriteUsername"),
|
||||
this.i18nService.t("yes"),
|
||||
this.i18nService.t("no")
|
||||
);
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.onGenerateUsername.emit();
|
||||
return true;
|
||||
}
|
||||
|
||||
async generatePassword(): Promise<boolean> {
|
||||
if (this.cipher.login?.password?.length) {
|
||||
const confirmed = await this.platformUtilsService.showDialog(
|
||||
this.i18nService.t("overwritePasswordConfirmation"),
|
||||
this.i18nService.t("overwritePassword"),
|
||||
this.i18nService.t("yes"),
|
||||
this.i18nService.t("no")
|
||||
);
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.onGeneratePassword.emit();
|
||||
return true;
|
||||
}
|
||||
|
||||
togglePassword() {
|
||||
this.showPassword = !this.showPassword;
|
||||
document.getElementById("loginPassword").focus();
|
||||
if (this.editMode && this.showPassword) {
|
||||
this.eventService.collect(EventType.Cipher_ClientToggledPasswordVisible, this.cipherId);
|
||||
}
|
||||
}
|
||||
|
||||
async toggleCardNumber() {
|
||||
this.showCardNumber = !this.showCardNumber;
|
||||
if (this.showCardNumber) {
|
||||
this.eventService.collect(EventType.Cipher_ClientToggledCardNumberVisible, this.cipherId);
|
||||
}
|
||||
}
|
||||
|
||||
toggleCardCode() {
|
||||
this.showCardCode = !this.showCardCode;
|
||||
document.getElementById("cardCode").focus();
|
||||
if (this.editMode && this.showCardCode) {
|
||||
this.eventService.collect(EventType.Cipher_ClientToggledCardCodeVisible, this.cipherId);
|
||||
}
|
||||
}
|
||||
|
||||
toggleUriOptions(uri: LoginUriView) {
|
||||
const u = uri as any;
|
||||
u.showOptions = u.showOptions == null && uri.match != null ? false : !u.showOptions;
|
||||
}
|
||||
|
||||
loginUriMatchChanged(uri: LoginUriView) {
|
||||
const u = uri as any;
|
||||
u.showOptions = u.showOptions == null ? true : u.showOptions;
|
||||
}
|
||||
|
||||
async organizationChanged() {
|
||||
if (this.writeableCollections != null) {
|
||||
this.writeableCollections.forEach((c) => ((c as any).checked = false));
|
||||
}
|
||||
if (this.cipher.organizationId != null) {
|
||||
this.collections = this.writeableCollections.filter(
|
||||
(c) => c.organizationId === this.cipher.organizationId
|
||||
);
|
||||
const org = await this.organizationService.get(this.cipher.organizationId);
|
||||
if (org != null) {
|
||||
this.cipher.organizationUseTotp = org.useTotp;
|
||||
}
|
||||
} else {
|
||||
this.collections = [];
|
||||
}
|
||||
}
|
||||
|
||||
async checkPassword() {
|
||||
if (this.checkPasswordPromise != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.cipher.login == null ||
|
||||
this.cipher.login.password == null ||
|
||||
this.cipher.login.password === ""
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.checkPasswordPromise = this.auditService.passwordLeaked(this.cipher.login.password);
|
||||
const matches = await this.checkPasswordPromise;
|
||||
this.checkPasswordPromise = null;
|
||||
|
||||
if (matches > 0) {
|
||||
this.platformUtilsService.showToast(
|
||||
"warning",
|
||||
null,
|
||||
this.i18nService.t("passwordExposed", matches.toString())
|
||||
);
|
||||
} else {
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("passwordSafe"));
|
||||
}
|
||||
}
|
||||
|
||||
repromptChanged() {
|
||||
this.reprompt = !this.reprompt;
|
||||
if (this.reprompt) {
|
||||
this.cipher.reprompt = CipherRepromptType.Password;
|
||||
} else {
|
||||
this.cipher.reprompt = CipherRepromptType.None;
|
||||
}
|
||||
}
|
||||
|
||||
protected async loadCollections() {
|
||||
const allCollections = await this.collectionService.getAllDecrypted();
|
||||
return allCollections.filter((c) => !c.readOnly);
|
||||
}
|
||||
|
||||
protected loadCipher() {
|
||||
return this.cipherService.get(this.cipherId);
|
||||
}
|
||||
|
||||
protected encryptCipher() {
|
||||
return this.cipherService.encrypt(this.cipher);
|
||||
}
|
||||
|
||||
protected saveCipher(cipher: Cipher) {
|
||||
return this.cipherService.saveWithServer(cipher);
|
||||
}
|
||||
|
||||
protected deleteCipher() {
|
||||
return this.cipher.isDeleted
|
||||
? this.cipherService.deleteWithServer(this.cipher.id)
|
||||
: this.cipherService.softDeleteWithServer(this.cipher.id);
|
||||
}
|
||||
|
||||
protected restoreCipher() {
|
||||
return this.cipherService.restoreWithServer(this.cipher.id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user