org cipher add/edit
This commit is contained in:
parent
b97378dd40
commit
f578ebe4ef
2
jslib
2
jslib
|
@ -1 +1 @@
|
||||||
Subproject commit 278b4402da94ab36b4def76f520599a23308f7f1
|
Subproject commit 9b008ff382d1dd6682185cf092afbf02a83ce951
|
|
@ -32,6 +32,7 @@ import { RegisterComponent } from './accounts/register.component';
|
||||||
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
||||||
import { TwoFactorComponent } from './accounts/two-factor.component';
|
import { TwoFactorComponent } from './accounts/two-factor.component';
|
||||||
|
|
||||||
|
import { AddEditComponent as OrgAddEditComponent } from './organizations/add-edit.component';
|
||||||
import { CiphersComponent as OrgCiphersComponent } from './organizations/ciphers.component';
|
import { CiphersComponent as OrgCiphersComponent } from './organizations/ciphers.component';
|
||||||
import { GroupingsComponent as OrgGroupingsComponent } from './organizations/groupings.component';
|
import { GroupingsComponent as OrgGroupingsComponent } from './organizations/groupings.component';
|
||||||
import { VaultComponent as OrgVaultComponent } from './organizations/vault.component';
|
import { VaultComponent as OrgVaultComponent } from './organizations/vault.component';
|
||||||
|
@ -152,6 +153,7 @@ import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe';
|
||||||
ModalComponent,
|
ModalComponent,
|
||||||
NavbarComponent,
|
NavbarComponent,
|
||||||
OptionsComponent,
|
OptionsComponent,
|
||||||
|
OrgAddEditComponent,
|
||||||
OrgCiphersComponent,
|
OrgCiphersComponent,
|
||||||
OrgGroupingsComponent,
|
OrgGroupingsComponent,
|
||||||
OrganizationsComponent,
|
OrganizationsComponent,
|
||||||
|
@ -197,6 +199,7 @@ import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe';
|
||||||
DeleteAccountComponent,
|
DeleteAccountComponent,
|
||||||
FolderAddEditComponent,
|
FolderAddEditComponent,
|
||||||
ModalComponent,
|
ModalComponent,
|
||||||
|
OrgAddEditComponent,
|
||||||
PasswordGeneratorHistoryComponent,
|
PasswordGeneratorHistoryComponent,
|
||||||
PurgeVaultComponent,
|
PurgeVaultComponent,
|
||||||
ShareComponent,
|
ShareComponent,
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { ToasterService } from 'angular2-toaster';
|
||||||
|
import { Angulartics2 } from 'angulartics2';
|
||||||
|
|
||||||
|
import { ApiService } from 'jslib/abstractions/api.service';
|
||||||
|
import { AuditService } from 'jslib/abstractions/audit.service';
|
||||||
|
import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||||
|
import { FolderService } from 'jslib/abstractions/folder.service';
|
||||||
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
|
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
||||||
|
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||||
|
import { StateService } from 'jslib/abstractions/state.service';
|
||||||
|
import { TokenService } from 'jslib/abstractions/token.service';
|
||||||
|
import { TotpService } from 'jslib/abstractions/totp.service';
|
||||||
|
|
||||||
|
import { CipherData } from 'jslib/models/data/cipherData';
|
||||||
|
import { Cipher } from 'jslib/models/domain/cipher';
|
||||||
|
import { Organization } from 'jslib/models/domain/organization';
|
||||||
|
import { CipherRequest } from 'jslib/models/request/cipherRequest';
|
||||||
|
|
||||||
|
import { AddEditComponent as BaseAddEditComponent } from '../vault/add-edit.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-org-vault-add-edit',
|
||||||
|
templateUrl: '../vault/add-edit.component.html',
|
||||||
|
})
|
||||||
|
export class AddEditComponent extends BaseAddEditComponent implements OnInit {
|
||||||
|
organization: Organization;
|
||||||
|
|
||||||
|
constructor(cipherService: CipherService, folderService: FolderService,
|
||||||
|
i18nService: I18nService, platformUtilsService: PlatformUtilsService,
|
||||||
|
analytics: Angulartics2, toasterService: ToasterService,
|
||||||
|
auditService: AuditService, stateService: StateService,
|
||||||
|
tokenService: TokenService, totpService: TotpService,
|
||||||
|
passwordGenerationService: PasswordGenerationService, private apiService: ApiService) {
|
||||||
|
super(cipherService, folderService, i18nService, platformUtilsService, analytics,
|
||||||
|
toasterService, auditService, stateService, tokenService, totpService, passwordGenerationService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async loadCipher() {
|
||||||
|
if (this.organization.isAdmin) {
|
||||||
|
const response = await this.apiService.getCipherAdmin(this.cipherId);
|
||||||
|
return new Cipher(new CipherData(response));
|
||||||
|
} else {
|
||||||
|
return await super.loadCipher();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async saveCipher(cipher: Cipher) {
|
||||||
|
if (this.organization.isAdmin) {
|
||||||
|
const request = new CipherRequest(cipher);
|
||||||
|
if (this.editMode) {
|
||||||
|
return this.apiService.putCipherAdmin(this.cipherId, request);
|
||||||
|
} else {
|
||||||
|
return this.apiService.postCipherAdmin(request);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return super.saveCipher(cipher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async deleteCipher() {
|
||||||
|
if (this.organization.isAdmin) {
|
||||||
|
return this.apiService.deleteCipherAdmin(this.cipherId);
|
||||||
|
} else {
|
||||||
|
return super.deleteCipher();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
|
ComponentFactoryResolver,
|
||||||
OnInit,
|
OnInit,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
|
ViewContainerRef,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import {
|
import {
|
||||||
ActivatedRoute,
|
ActivatedRoute,
|
||||||
|
@ -18,6 +20,9 @@ import { CipherView } from 'jslib/models/view/cipherView';
|
||||||
|
|
||||||
import { CipherType } from 'jslib/enums/cipherType';
|
import { CipherType } from 'jslib/enums/cipherType';
|
||||||
|
|
||||||
|
import { ModalComponent } from '../modal.component';
|
||||||
|
|
||||||
|
import { AddEditComponent } from './add-edit.component';
|
||||||
import { CiphersComponent } from './ciphers.component';
|
import { CiphersComponent } from './ciphers.component';
|
||||||
import { GroupingsComponent } from './groupings.component';
|
import { GroupingsComponent } from './groupings.component';
|
||||||
|
|
||||||
|
@ -28,14 +33,18 @@ import { GroupingsComponent } from './groupings.component';
|
||||||
export class VaultComponent implements OnInit {
|
export class VaultComponent implements OnInit {
|
||||||
@ViewChild(GroupingsComponent) groupingsComponent: GroupingsComponent;
|
@ViewChild(GroupingsComponent) groupingsComponent: GroupingsComponent;
|
||||||
@ViewChild(CiphersComponent) ciphersComponent: CiphersComponent;
|
@ViewChild(CiphersComponent) ciphersComponent: CiphersComponent;
|
||||||
|
@ViewChild('cipherAddEdit', { read: ViewContainerRef }) cipherAddEditModalRef: ViewContainerRef;
|
||||||
|
|
||||||
organization: Organization;
|
organization: Organization;
|
||||||
collectionId: string;
|
collectionId: string;
|
||||||
type: CipherType;
|
type: CipherType;
|
||||||
|
|
||||||
|
private modal: ModalComponent = null;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private userService: UserService,
|
constructor(private route: ActivatedRoute, private userService: UserService,
|
||||||
private location: Location, private router: Router,
|
private location: Location, private router: Router,
|
||||||
private syncService: SyncService, private i18nService: I18nService) { }
|
private syncService: SyncService, private i18nService: I18nService,
|
||||||
|
private componentFactoryResolver: ComponentFactoryResolver) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.parent.params.subscribe(async (params) => {
|
this.route.parent.params.subscribe(async (params) => {
|
||||||
|
@ -116,6 +125,38 @@ export class VaultComponent implements OnInit {
|
||||||
this.ciphersComponent.searchText = searchText;
|
this.ciphersComponent.searchText = searchText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addCipher() {
|
||||||
|
const component = this.editCipher(null);
|
||||||
|
component.type = this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
editCipher(cipher: CipherView) {
|
||||||
|
if (this.modal != null) {
|
||||||
|
this.modal.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
|
||||||
|
this.modal = this.cipherAddEditModalRef.createComponent(factory).instance;
|
||||||
|
const childComponent = this.modal.show<AddEditComponent>(AddEditComponent, this.cipherAddEditModalRef);
|
||||||
|
|
||||||
|
childComponent.organization = this.organization;
|
||||||
|
childComponent.cipherId = cipher == null ? null : cipher.id;
|
||||||
|
childComponent.onSavedCipher.subscribe(async (c: CipherView) => {
|
||||||
|
this.modal.close();
|
||||||
|
await this.ciphersComponent.refresh();
|
||||||
|
});
|
||||||
|
childComponent.onDeletedCipher.subscribe(async (c: CipherView) => {
|
||||||
|
this.modal.close();
|
||||||
|
await this.ciphersComponent.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.modal.onClosed.subscribe(() => {
|
||||||
|
this.modal = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return childComponent;
|
||||||
|
}
|
||||||
|
|
||||||
private clearFilters() {
|
private clearFilters() {
|
||||||
this.collectionId = null;
|
this.collectionId = null;
|
||||||
this.type = null;
|
this.type = null;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<label for="name">{{'name' | i18n}}</label>
|
<label for="name">{{'name' | i18n}}</label>
|
||||||
<input id="name" class="form-control" type="text" name="Name" [(ngModel)]="cipher.name">
|
<input id="name" class="form-control" type="text" name="Name" [(ngModel)]="cipher.name">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 form-group">
|
<div class="col-6 form-group" *ngIf="!organization">
|
||||||
<label for="folder">{{'folder' | i18n}}</label>
|
<label for="folder">{{'folder' | i18n}}</label>
|
||||||
<select id="folder" name="FolderId" [(ngModel)]="cipher.folderId" class="form-control">
|
<select id="folder" name="FolderId" [(ngModel)]="cipher.folderId" class="form-control">
|
||||||
<option *ngFor="let f of folders" [ngValue]="f.id">{{f.name}}</option>
|
<option *ngFor="let f of folders" [ngValue]="f.id">{{f.name}}</option>
|
||||||
|
@ -356,7 +356,7 @@
|
||||||
{{'cancel' | i18n}}
|
{{'cancel' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
<div class="ml-auto" *ngIf="cipher">
|
<div class="ml-auto" *ngIf="cipher">
|
||||||
<button appBlurClick type="button" (click)="toggleFavorite()" class="btn btn-link" title="{{(cipher.favorite ? 'unfavorite' : 'favorite') | i18n}}">
|
<button *ngIf="!organization" appBlurClick type="button" (click)="toggleFavorite()" class="btn btn-link" title="{{(cipher.favorite ? 'unfavorite' : 'favorite') | i18n}}">
|
||||||
<i class="fa fa-lg" [ngClass]="{'fa-star': cipher.favorite, 'fa-star-o': !cipher.favorite}"></i>
|
<i class="fa fa-lg" [ngClass]="{'fa-star': cipher.favorite, 'fa-star-o': !cipher.favorite}"></i>
|
||||||
</button>
|
</button>
|
||||||
<button #deleteBtn appBlurClick type="button" (click)="delete()" class="btn btn-outline-danger" title="{{'delete' | i18n}}"
|
<button #deleteBtn appBlurClick type="button" (click)="delete()" class="btn btn-outline-danger" title="{{'delete' | i18n}}"
|
||||||
|
|
|
@ -33,14 +33,14 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit {
|
||||||
totpSec: number;
|
totpSec: number;
|
||||||
totpLow: boolean;
|
totpLow: boolean;
|
||||||
|
|
||||||
private totpInterval: number;
|
protected totpInterval: number;
|
||||||
|
|
||||||
constructor(cipherService: CipherService, folderService: FolderService,
|
constructor(cipherService: CipherService, folderService: FolderService,
|
||||||
i18nService: I18nService, platformUtilsService: PlatformUtilsService,
|
i18nService: I18nService, platformUtilsService: PlatformUtilsService,
|
||||||
analytics: Angulartics2, toasterService: ToasterService,
|
analytics: Angulartics2, toasterService: ToasterService,
|
||||||
auditService: AuditService, stateService: StateService,
|
auditService: AuditService, stateService: StateService,
|
||||||
private tokenService: TokenService, private totpService: TotpService,
|
protected tokenService: TokenService, protected totpService: TotpService,
|
||||||
private passwordGenerationService: PasswordGenerationService) {
|
protected passwordGenerationService: PasswordGenerationService) {
|
||||||
super(cipherService, folderService, i18nService, platformUtilsService, analytics,
|
super(cipherService, folderService, i18nService, platformUtilsService, analytics,
|
||||||
toasterService, auditService, stateService);
|
toasterService, auditService, stateService);
|
||||||
}
|
}
|
||||||
|
@ -94,13 +94,13 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit {
|
||||||
return confirmed;
|
return confirmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private cleanUp() {
|
protected cleanUp() {
|
||||||
if (this.totpInterval) {
|
if (this.totpInterval) {
|
||||||
window.clearInterval(this.totpInterval);
|
window.clearInterval(this.totpInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async totpUpdateCode() {
|
protected async totpUpdateCode() {
|
||||||
if (this.cipher == null || this.cipher.type !== CipherType.Login || this.cipher.login.totp == null) {
|
if (this.cipher == null || this.cipher.type !== CipherType.Login || this.cipher.login.totp == null) {
|
||||||
if (this.totpInterval) {
|
if (this.totpInterval) {
|
||||||
window.clearInterval(this.totpInterval);
|
window.clearInterval(this.totpInterval);
|
||||||
|
@ -119,7 +119,7 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async totpTick() {
|
protected async totpTick() {
|
||||||
const epoch = Math.round(new Date().getTime() / 1000.0);
|
const epoch = Math.round(new Date().getTime() / 1000.0);
|
||||||
const mod = epoch % 30;
|
const mod = epoch % 30;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue