mirror of
https://github.com/bitwarden/browser
synced 2026-01-04 09:33:27 +00:00
Merge branch 'master' into feature/org-admin-refresh
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { first } from "rxjs/operators";
|
||||
import { Component, OnDestroy, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { combineLatest, concatMap, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ValidationService } from "@bitwarden/angular/services/validation.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
@@ -13,11 +12,11 @@ import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/abstractions/policy/policy-api.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||
import { ValidationService } from "@bitwarden/common/abstractions/validation.service";
|
||||
import { OrganizationUserStatusType } from "@bitwarden/common/enums/organizationUserStatusType";
|
||||
import { OrganizationUserType } from "@bitwarden/common/enums/organizationUserType";
|
||||
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
||||
@@ -43,10 +42,9 @@ import { UserGroupsComponent } from "./user-groups.component";
|
||||
selector: "app-org-people",
|
||||
templateUrl: "people.component.html",
|
||||
})
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
export class PeopleComponent
|
||||
extends BasePeopleComponent<OrganizationUserUserDetailsResponse>
|
||||
implements OnInit
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
@ViewChild("addEdit", { read: ViewContainerRef, static: true }) addEditModalRef: ViewContainerRef;
|
||||
@ViewChild("groupsTemplate", { read: ViewContainerRef, static: true })
|
||||
@@ -77,6 +75,8 @@ export class PeopleComponent
|
||||
orgResetPasswordPolicyEnabled = false;
|
||||
callingUserType: OrganizationUserType = null;
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
apiService: ApiService,
|
||||
private route: ActivatedRoute,
|
||||
@@ -84,10 +84,8 @@ export class PeopleComponent
|
||||
modalService: ModalService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
cryptoService: CryptoService,
|
||||
private router: Router,
|
||||
searchService: SearchService,
|
||||
validationService: ValidationService,
|
||||
private policyApiService: PolicyApiServiceAbstraction,
|
||||
private policyService: PolicyService,
|
||||
logService: LogService,
|
||||
searchPipe: SearchPipe,
|
||||
@@ -113,53 +111,63 @@ export class PeopleComponent
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||
this.route.parent.params.subscribe(async (params) => {
|
||||
this.organizationId = params.organizationId;
|
||||
const organization = await this.organizationService.get(this.organizationId);
|
||||
this.accessEvents = organization.useEvents;
|
||||
this.accessGroups = organization.useGroups;
|
||||
this.canResetPassword = organization.canManageUsersPassword;
|
||||
this.orgUseResetPassword = organization.useResetPassword;
|
||||
this.callingUserType = organization.type;
|
||||
this.orgHasKeys = organization.hasPublicAndPrivateKeys;
|
||||
combineLatest([this.route.params, this.route.queryParams, this.policyService.policies$])
|
||||
.pipe(
|
||||
concatMap(async ([params, qParams, policies]) => {
|
||||
this.organizationId = params.organizationId;
|
||||
const organization = await this.organizationService.get(this.organizationId);
|
||||
this.accessEvents = organization.useEvents;
|
||||
this.accessGroups = organization.useGroups;
|
||||
this.canResetPassword = organization.canManageUsersPassword;
|
||||
this.orgUseResetPassword = organization.useResetPassword;
|
||||
this.callingUserType = organization.type;
|
||||
this.orgHasKeys = organization.hasPublicAndPrivateKeys;
|
||||
|
||||
// Backfill pub/priv key if necessary
|
||||
if (this.canResetPassword && !this.orgHasKeys) {
|
||||
const orgShareKey = await this.cryptoService.getOrgKey(this.organizationId);
|
||||
const orgKeys = await this.cryptoService.makeKeyPair(orgShareKey);
|
||||
const request = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
|
||||
const response = await this.organizationApiService.updateKeys(this.organizationId, request);
|
||||
if (response != null) {
|
||||
this.orgHasKeys = response.publicKey != null && response.privateKey != null;
|
||||
await this.syncService.fullSync(true); // Replace oganizations with new data
|
||||
} else {
|
||||
throw new Error(this.i18nService.t("resetPasswordOrgKeysError"));
|
||||
}
|
||||
}
|
||||
|
||||
await this.load();
|
||||
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe, rxjs/no-nested-subscribe
|
||||
this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
|
||||
this.searchText = qParams.search;
|
||||
if (qParams.viewEvents != null) {
|
||||
const user = this.users.filter((u) => u.id === qParams.viewEvents);
|
||||
if (user.length > 0 && user[0].status === OrganizationUserStatusType.Confirmed) {
|
||||
this.events(user[0]);
|
||||
// Backfill pub/priv key if necessary
|
||||
if (this.canResetPassword && !this.orgHasKeys) {
|
||||
const orgShareKey = await this.cryptoService.getOrgKey(this.organizationId);
|
||||
const orgKeys = await this.cryptoService.makeKeyPair(orgShareKey);
|
||||
const request = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
|
||||
const response = await this.organizationApiService.updateKeys(
|
||||
this.organizationId,
|
||||
request
|
||||
);
|
||||
if (response != null) {
|
||||
this.orgHasKeys = response.publicKey != null && response.privateKey != null;
|
||||
await this.syncService.fullSync(true); // Replace oganizations with new data
|
||||
} else {
|
||||
throw new Error(this.i18nService.t("resetPasswordOrgKeysError"));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const resetPasswordPolicy = policies
|
||||
.filter((policy) => policy.type === PolicyType.ResetPassword)
|
||||
.find((p) => p.organizationId === this.organizationId);
|
||||
this.orgResetPasswordPolicyEnabled = resetPasswordPolicy?.enabled;
|
||||
|
||||
await this.load();
|
||||
|
||||
this.searchText = qParams.search;
|
||||
if (qParams.viewEvents != null) {
|
||||
const user = this.users.filter((u) => u.id === qParams.viewEvents);
|
||||
if (user.length > 0 && user[0].status === OrganizationUserStatusType.Confirmed) {
|
||||
this.events(user[0]);
|
||||
}
|
||||
}
|
||||
}),
|
||||
takeUntil(this.destroy$)
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
async load() {
|
||||
const resetPasswordPolicy = await this.policyApiService.getPolicyForOrganization(
|
||||
PolicyType.ResetPassword,
|
||||
this.organizationId
|
||||
);
|
||||
this.orgResetPasswordPolicyEnabled = resetPasswordPolicy?.enabled;
|
||||
super.load();
|
||||
await super.load();
|
||||
}
|
||||
|
||||
getUsers(): Promise<ListResponse<OrganizationUserUserDetailsResponse>> {
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from "@angular/core";
|
||||
import {
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
ViewChild,
|
||||
} from "@angular/core";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
import zxcvbn from "zxcvbn";
|
||||
|
||||
import { PasswordStrengthComponent } from "@bitwarden/angular/shared/components/password-strength/password-strength.component";
|
||||
@@ -18,7 +27,7 @@ import { OrganizationUserResetPasswordRequest } from "@bitwarden/common/models/r
|
||||
selector: "app-reset-password",
|
||||
templateUrl: "reset-password.component.html",
|
||||
})
|
||||
export class ResetPasswordComponent implements OnInit {
|
||||
export class ResetPasswordComponent implements OnInit, OnDestroy {
|
||||
@Input() name: string;
|
||||
@Input() email: string;
|
||||
@Input() id: string;
|
||||
@@ -32,6 +41,8 @@ export class ResetPasswordComponent implements OnInit {
|
||||
passwordStrengthResult: zxcvbn.ZXCVBNResult;
|
||||
formPromise: Promise<any>;
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private i18nService: I18nService,
|
||||
@@ -43,8 +54,18 @@ export class ResetPasswordComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
// Get Enforced Policy Options
|
||||
this.enforcedPolicyOptions = await this.policyService.getMasterPasswordPolicyOptions();
|
||||
this.policyService
|
||||
.masterPasswordPolicyOptions$()
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(
|
||||
(enforcedPasswordPolicyOptions) =>
|
||||
(this.enforcedPolicyOptions = enforcedPasswordPolicyOptions)
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
get loggedOutWarningName() {
|
||||
@@ -52,7 +73,7 @@ export class ResetPasswordComponent implements OnInit {
|
||||
}
|
||||
|
||||
async generatePassword() {
|
||||
const options = (await this.passwordGenerationService.getOptions())[0];
|
||||
const options = (await this.passwordGenerationService.getOptions())?.[0] ?? {};
|
||||
this.newPassword = await this.passwordGenerationService.generatePassword(options);
|
||||
this.passwordStrengthComponent.updatePasswordStrength(this.newPassword);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ import { Observable, Subject } from "rxjs";
|
||||
import { first, map, takeUntil } from "rxjs/operators";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ValidationService } from "@bitwarden/angular/services/validation.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { SyncService } from "@bitwarden/common/abstractions/sync/sync.service.abstraction";
|
||||
import { ValidationService } from "@bitwarden/common/abstractions/validation.service";
|
||||
import { PlanSponsorshipType } from "@bitwarden/common/enums/planSponsorshipType";
|
||||
import { PlanType } from "@bitwarden/common/enums/planType";
|
||||
import { ProductType } from "@bitwarden/common/enums/productType";
|
||||
|
||||
@@ -47,7 +47,6 @@ export class OrganizationImportComponent extends ImportComponent {
|
||||
this.organizationId = params.organizationId;
|
||||
this.successNavigate = ["organizations", this.organizationId, "vault"];
|
||||
await super.ngOnInit();
|
||||
this.importBlockedByPolicy = false;
|
||||
});
|
||||
const organization = await this.organizationService.get(this.organizationId);
|
||||
this.organizationName = organization.name;
|
||||
|
||||
Reference in New Issue
Block a user