1
0
mirror of https://github.com/bitwarden/web synced 2025-12-13 14:53:25 +00:00

Resolve org user confirm not showing error when hide fingerprint is enabled (#918)

This commit is contained in:
Oscar Hinton
2021-04-09 00:46:16 +02:00
committed by GitHub
parent 133d30ba97
commit f81ad479dd
4 changed files with 47 additions and 47 deletions

View File

@@ -13,6 +13,7 @@ import {
import { ToasterService } from 'angular2-toaster'; import { ToasterService } from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2'; import { Angulartics2 } from 'angulartics2';
import { ValidationService } from 'jslib/angular/services/validation.service';
import { ConstantsService } from 'jslib/services/constants.service'; import { ConstantsService } from 'jslib/services/constants.service';
import { ApiService } from 'jslib/abstractions/api.service'; import { ApiService } from 'jslib/abstractions/api.service';
@@ -73,7 +74,8 @@ export class PeopleComponent implements OnInit {
private platformUtilsService: PlatformUtilsService, private analytics: Angulartics2, private platformUtilsService: PlatformUtilsService, private analytics: Angulartics2,
private toasterService: ToasterService, private cryptoService: CryptoService, private toasterService: ToasterService, private cryptoService: CryptoService,
private userService: UserService, private router: Router, private userService: UserService, private router: Router,
private storageService: StorageService, private searchService: SearchService) { } private storageService: StorageService, private searchService: SearchService,
private validationService: ValidationService) { }
async ngOnInit() { async ngOnInit() {
this.route.parent.parent.params.subscribe(async params => { this.route.parent.parent.params.subscribe(async params => {
@@ -258,6 +260,21 @@ export class PeopleComponent implements OnInit {
} }
} }
const confirmUser = async (publicKey: Uint8Array) => {
try {
this.actionPromise = this.doConfirmation(user, publicKey);
await this.actionPromise;
updateUser(this);
this.analytics.eventTrack.next({ action: 'Confirmed User' });
this.toasterService.popAsync('success', null, this.i18nService.t('hasBeenConfirmed', user.name || user.email));
} catch (e) {
this.validationService.showError(e);
throw e;
} finally {
this.actionPromise = null;
}
};
if (this.actionPromise != null) { if (this.actionPromise != null) {
return; return;
} }
@@ -277,9 +294,14 @@ export class PeopleComponent implements OnInit {
childComponent.organizationId = this.organizationId; childComponent.organizationId = this.organizationId;
childComponent.organizationUserId = user != null ? user.id : null; childComponent.organizationUserId = user != null ? user.id : null;
childComponent.userId = user != null ? user.userId : null; childComponent.userId = user != null ? user.userId : null;
childComponent.onConfirmedUser.subscribe(() => { childComponent.onConfirmedUser.subscribe(async (publicKey: Uint8Array) => {
try {
await confirmUser(publicKey);
this.modal.close(); this.modal.close();
updateUser(this); } catch (e) {
// tslint:disable-next-line
console.error('Handled exception:', e);
}
}); });
this.modal.onClosed.subscribe(() => { this.modal.onClosed.subscribe(() => {
@@ -288,12 +310,19 @@ export class PeopleComponent implements OnInit {
return; return;
} }
this.actionPromise = this.doConfirmation(user); try {
await this.actionPromise; const publicKeyResponse = await this.apiService.getUserPublicKey(user.userId);
updateUser(this); const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey);
this.analytics.eventTrack.next({ action: 'Confirmed User' }); try {
this.toasterService.popAsync('success', null, this.i18nService.t('hasBeenConfirmed', user.name || user.email)); // tslint:disable-next-line
this.actionPromise = null; console.log('User\'s fingerprint: ' +
(await this.cryptoService.getFingerprint(user.userId, publicKey.buffer)).join('-'));
} catch { }
await confirmUser(publicKey);
} catch (e) {
// tslint:disable-next-line
console.error('Handled exception:', e);
}
} }
async events(user: OrganizationUserUserDetailsResponse) { async events(user: OrganizationUserUserDetailsResponse) {
@@ -334,15 +363,8 @@ export class PeopleComponent implements OnInit {
return !searching && this.users && this.users.length > this.pageSize; return !searching && this.users && this.users.length > this.pageSize;
} }
private async doConfirmation(user: OrganizationUserUserDetailsResponse) { private async doConfirmation(user: OrganizationUserUserDetailsResponse, publicKey: Uint8Array) {
const orgKey = await this.cryptoService.getOrgKey(this.organizationId); const orgKey = await this.cryptoService.getOrgKey(this.organizationId);
const publicKeyResponse = await this.apiService.getUserPublicKey(user.userId);
const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey);
try {
// tslint:disable-next-line
console.log('User\'s fingerprint: ' +
(await this.cryptoService.getFingerprint(user.userId, publicKey.buffer)).join('-'));
} catch { }
const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey.buffer); const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey.buffer);
const request = new OrganizationUserConfirmRequest(); const request = new OrganizationUserConfirmRequest();
request.key = key.encryptedString; request.key = key.encryptedString;

View File

@@ -1,6 +1,6 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="confirmUserTitle"> <div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="confirmUserTitle">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise"> <form class="modal-content" #form (ngSubmit)="submit()">
<div class="modal-header"> <div class="modal-header">
<h2 class="modal-title" id="confirmUserTitle"> <h2 class="modal-title" id="confirmUserTitle">
{{'confirmUser' | i18n}} {{'confirmUser' | i18n}}

View File

@@ -6,18 +6,12 @@ import {
Output, Output,
} from '@angular/core'; } from '@angular/core';
import { ToasterService } from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
import { ConstantsService } from 'jslib/services/constants.service'; import { ConstantsService } from 'jslib/services/constants.service';
import { ApiService } from 'jslib/abstractions/api.service'; import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoService } from 'jslib/abstractions/crypto.service'; import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { StorageService } from 'jslib/abstractions/storage.service'; import { StorageService } from 'jslib/abstractions/storage.service';
import { OrganizationUserConfirmRequest } from 'jslib/models/request/organizationUserConfirmRequest';
import { Utils } from 'jslib/misc/utils'; import { Utils } from 'jslib/misc/utils';
@Component({ @Component({
@@ -34,13 +28,11 @@ export class UserConfirmComponent implements OnInit {
dontAskAgain = false; dontAskAgain = false;
loading = true; loading = true;
fingerprint: string; fingerprint: string;
formPromise: Promise<any>;
private publicKey: Uint8Array = null; private publicKey: Uint8Array = null;
constructor(private apiService: ApiService, private i18nService: I18nService, constructor(private apiService: ApiService, private cryptoService: CryptoService,
private analytics: Angulartics2, private toasterService: ToasterService, private storageService: StorageService) { }
private cryptoService: CryptoService, private storageService: StorageService) { }
async ngOnInit() { async ngOnInit() {
try { try {
@@ -65,20 +57,6 @@ export class UserConfirmComponent implements OnInit {
await this.storageService.save(ConstantsService.autoConfirmFingerprints, true); await this.storageService.save(ConstantsService.autoConfirmFingerprints, true);
} }
try { this.onConfirmedUser.emit(this.publicKey);
this.formPromise = this.doConfirmation();
await this.formPromise;
this.analytics.eventTrack.next({ action: 'Confirmed User' });
this.toasterService.popAsync('success', null, this.i18nService.t('hasBeenConfirmed', this.name));
this.onConfirmedUser.emit();
} catch { }
}
private async doConfirmation() {
const orgKey = await this.cryptoService.getOrgKey(this.organizationId);
const key = await this.cryptoService.rsaEncrypt(orgKey.key, this.publicKey.buffer);
const request = new OrganizationUserConfirmRequest();
request.key = key.encryptedString;
await this.apiService.postOrganizationUserConfirm(this.organizationId, this.organizationUserId, request);
} }
} }

View File

@@ -42,10 +42,10 @@ export class WeakPasswordsReportComponent extends CipherReportComponent implemen
const weakPasswordCiphers: CipherView[] = []; const weakPasswordCiphers: CipherView[] = [];
const isUserNameNotEmpty = (c: CipherView): boolean => { const isUserNameNotEmpty = (c: CipherView): boolean => {
return c.login.username != null && c.login.username.trim() !== ''; return c.login.username != null && c.login.username.trim() !== '';
} };
const getCacheKey = (c:CipherView): string => { const getCacheKey = (c: CipherView): string => {
return c.login.password + '_____' + (isUserNameNotEmpty(c) ? c.login.username : ''); return c.login.password + '_____' + (isUserNameNotEmpty(c) ? c.login.username : '');
} };
allCiphers.forEach(c => { allCiphers.forEach(c => {
if (c.type !== CipherType.Login || c.login.password == null || c.login.password === '' || c.isDeleted) { if (c.type !== CipherType.Login || c.login.password == null || c.login.password === '' || c.isDeleted) {