1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-08 03:23:50 +00:00

[EC-19] Update Organization Settings Page (#3251)

* [EC-19] Refactor existing organization settings components to its own module

* [EC-19] Move SSO page to settings tab

* [EC-19] Move Policies page to Settings tab

Refactor Policy components into its own module

* [EC-19] Move ImageSubscriptionHiddenComponent

* [EC-19] Lazy load org settings module

* [EC-19] Add SSO Id to SSO config view

* [EC-19] Remove SSO identfier from org info page

* [EC-19] Update org settings/policies to follow ADR-0011

* [EC-19] Update two-step login setup description

* [EC-19] Revert nested policy components folder

* [EC-19] Revert nested org setting components folder

* [EC-19] Remove left over image component

* [EC-19] Prettier

* [EC-19] Fix missing i18n

* [EC-19] Update SSO form to use CL

* [EC-19] Remove unused SSO input components

* [EC-19] Fix bad SSO locale identifier

* [EC-19] Fix import order linting

* [EC-19] Add explicit whitespace check for launch click directive

* [EC-19] Add restricted import paths to eslint config

* [EC-19] Tag deprecated field with Jira issue to cleanup in future release

* [EC-19] Remove out of date comment

* [EC-19] Move policy components to policies module

* [EC-19] Remove dityRequired validator

* [EC-19] Use explicit type for SSO config form

* [EC-19] Fix rxjs linter errors

* [EC-19] Fix RxJS eslint comments in org settings component

* [EC-19] Use explicit ControlsOf<T> helper for nested SSO form groups.

* [EC-19] Attribute source of ControlsOf<T> helper

* [EC-19] Fix missing settings side nav links

* [EC-19] Fix member/user language for policy modals
This commit is contained in:
Shane Melton
2022-09-27 14:40:04 -07:00
committed by GitHub
parent 38204bf4dd
commit 75965b080f
48 changed files with 750 additions and 641 deletions

View File

@@ -4,6 +4,7 @@ import { LooseComponentsModule } from "../../shared/loose-components.module";
import { SharedModule } from "../../shared/shared.module";
import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component";
import { ImageSubscriptionHiddenComponent } from "./image-subscription-hidden.component";
import { OrgBillingHistoryViewComponent } from "./organization-billing-history-view.component";
import { OrganizationBillingRoutingModule } from "./organization-billing-routing.module";
import { OrganizationBillingTabComponent } from "./organization-billing-tab.component";
@@ -14,6 +15,7 @@ import { OrganizationSubscriptionComponent } from "./organization-subscription.c
declarations: [
BillingSyncApiKeyComponent,
OrganizationBillingTabComponent,
ImageSubscriptionHiddenComponent,
OrganizationSubscriptionComponent,
OrgBillingHistoryViewComponent,
],

View File

@@ -11,11 +11,7 @@ import {
canAccessGroupsTab,
canAccessMembersTab,
canAccessOrgAdmin,
canAccessSettingsTab,
} from "./navigation-permissions";
import { AccountComponent } from "./settings/account.component";
import { SettingsComponent } from "./settings/settings.component";
import { TwoFactorSetupComponent } from "./settings/two-factor-setup.component";
import { VaultModule } from "./vault/vault.module";
const routes: Routes = [
@@ -34,18 +30,7 @@ const routes: Routes = [
},
{
path: "settings",
component: SettingsComponent,
canActivate: [OrganizationPermissionsGuard],
data: { organizationPermissions: canAccessSettingsTab },
children: [
{ path: "", pathMatch: "full", redirectTo: "account" },
{ path: "account", component: AccountComponent, data: { titleId: "organizationInfo" } },
{
path: "two-factor",
component: TwoFactorSetupComponent,
data: { titleId: "twoStepLogin" },
},
],
loadChildren: () => import("./settings").then((m) => m.OrganizationSettingsModule),
},
{
path: "members",

View File

@@ -0,0 +1,12 @@
export * from "./policies.module";
export { BasePolicy, BasePolicyComponent } from "./base-policy.component";
export { DisableSendPolicy } from "./disable-send.component";
export { MasterPasswordPolicy } from "./master-password.component";
export { PasswordGeneratorPolicy } from "./password-generator.component";
export { PersonalOwnershipPolicy } from "./personal-ownership.component";
export { RequireSsoPolicy } from "./require-sso.component";
export { ResetPasswordPolicy } from "./reset-password.component";
export { SendOptionsPolicy } from "./send-options.component";
export { SingleOrgPolicy } from "./single-org.component";
export { TwoFactorAuthenticationPolicy } from "./two-factor-authentication.component";
export { PoliciesComponent } from "./policies.component";

View File

@@ -10,7 +10,7 @@ import { Organization } from "@bitwarden/common/models/domain/organization";
import { PolicyResponse } from "@bitwarden/common/models/response/policyResponse";
import { PolicyListService } from "../../core";
import { BasePolicy } from "../policies/base-policy.component";
import { BasePolicy } from "../policies";
import { PolicyEditComponent } from "./policy-edit.component";

View File

@@ -0,0 +1,46 @@
import { NgModule } from "@angular/core";
import { LooseComponentsModule, SharedModule } from "../../shared";
import { DisableSendPolicyComponent } from "./disable-send.component";
import { MasterPasswordPolicyComponent } from "./master-password.component";
import { PasswordGeneratorPolicyComponent } from "./password-generator.component";
import { PersonalOwnershipPolicyComponent } from "./personal-ownership.component";
import { PoliciesComponent } from "./policies.component";
import { PolicyEditComponent } from "./policy-edit.component";
import { RequireSsoPolicyComponent } from "./require-sso.component";
import { ResetPasswordPolicyComponent } from "./reset-password.component";
import { SendOptionsPolicyComponent } from "./send-options.component";
import { SingleOrgPolicyComponent } from "./single-org.component";
import { TwoFactorAuthenticationPolicyComponent } from "./two-factor-authentication.component";
@NgModule({
imports: [SharedModule, LooseComponentsModule],
declarations: [
DisableSendPolicyComponent,
MasterPasswordPolicyComponent,
PasswordGeneratorPolicyComponent,
PersonalOwnershipPolicyComponent,
RequireSsoPolicyComponent,
ResetPasswordPolicyComponent,
SendOptionsPolicyComponent,
SingleOrgPolicyComponent,
TwoFactorAuthenticationPolicyComponent,
PoliciesComponent,
PolicyEditComponent,
],
exports: [
DisableSendPolicyComponent,
MasterPasswordPolicyComponent,
PasswordGeneratorPolicyComponent,
PersonalOwnershipPolicyComponent,
RequireSsoPolicyComponent,
ResetPasswordPolicyComponent,
SendOptionsPolicyComponent,
SingleOrgPolicyComponent,
TwoFactorAuthenticationPolicyComponent,
PoliciesComponent,
PolicyEditComponent,
],
})
export class PoliciesModule {}

View File

@@ -17,7 +17,7 @@ import { PolicyType } from "@bitwarden/common/enums/policyType";
import { PolicyRequest } from "@bitwarden/common/models/request/policyRequest";
import { PolicyResponse } from "@bitwarden/common/models/response/policyResponse";
import { BasePolicy, BasePolicyComponent } from "../policies/base-policy.component";
import { BasePolicy, BasePolicyComponent } from "../policies";
@Component({
selector: "app-policy-edit",

View File

@@ -51,16 +51,6 @@
[disabled]="selfHosted || !canManageBilling"
/>
</div>
<div class="form-group">
<label for="identifier">{{ "identifier" | i18n }}</label>
<input
id="identifier"
class="form-control"
type="text"
name="Identifier"
[(ngModel)]="org.identifier"
/>
</div>
</div>
<div class="col-6">
<app-avatar data="{{ org.name }}" dynamic="true" size="75" fontSize="35"></app-avatar>

View File

@@ -0,0 +1,2 @@
export * from "./organization-settings.module";
export { DeleteOrganizationComponent } from "./delete-organization.component";

View File

@@ -0,0 +1,52 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { OrganizationPermissionsGuard } from "../guards/org-permissions.guard";
import { canAccessSettingsTab } from "../navigation-permissions";
import { PoliciesComponent } from "../policies";
import { AccountComponent } from "./account.component";
import { SettingsComponent } from "./settings.component";
import { TwoFactorSetupComponent } from "./two-factor-setup.component";
const routes: Routes = [
{
path: "",
component: SettingsComponent,
canActivate: [OrganizationPermissionsGuard],
data: { organizationPermissions: canAccessSettingsTab },
children: [
{ path: "", pathMatch: "full", redirectTo: "account" },
{ path: "account", component: AccountComponent, data: { titleId: "organizationInfo" } },
{
path: "two-factor",
component: TwoFactorSetupComponent,
data: { titleId: "twoStepLogin" },
},
{
path: "policies",
component: PoliciesComponent,
canActivate: [OrganizationPermissionsGuard],
data: {
organizationPermissions: (org: Organization) => org.canManagePolicies,
titleId: "policies",
},
},
{
path: "tools",
loadChildren: () =>
import("../tools/import-export/org-import-export.module").then(
(m) => m.OrganizationImportExportModule
),
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class OrganizationSettingsRoutingModule {}

View File

@@ -0,0 +1,27 @@
import { NgModule } from "@angular/core";
import { LooseComponentsModule, SharedModule } from "../../shared";
import { PoliciesModule } from "../policies";
import { AccountComponent } from "./account.component";
import { AdjustSubscription } from "./adjust-subscription.component";
import { ChangePlanComponent } from "./change-plan.component";
import { DeleteOrganizationComponent } from "./delete-organization.component";
import { DownloadLicenseComponent } from "./download-license.component";
import { OrganizationSettingsRoutingModule } from "./organization-settings-routing.module";
import { SettingsComponent } from "./settings.component";
import { TwoFactorSetupComponent } from "./two-factor-setup.component";
@NgModule({
imports: [SharedModule, LooseComponentsModule, PoliciesModule, OrganizationSettingsRoutingModule],
declarations: [
SettingsComponent,
AccountComponent,
AdjustSubscription,
ChangePlanComponent,
DeleteOrganizationComponent,
DownloadLicenseComponent,
TwoFactorSetupComponent,
],
})
export class OrganizationSettingsModule {}

View File

@@ -7,14 +7,54 @@
<a routerLink="account" class="list-group-item" routerLinkActive="active">
{{ "organizationInfo" | i18n }}
</a>
<a
routerLink="policies"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization?.canManagePolicies"
>
{{ "policies" | i18n }}
</a>
<a
routerLink="two-factor"
class="list-group-item"
routerLinkActive="active"
*ngIf="access2fa"
*ngIf="organization?.use2fa"
>
{{ "twoStepLogin" | i18n }}
</a>
<a
routerLink="tools/import"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization?.canAccessImportExport"
>
{{ "importData" | i18n }}
</a>
<a
routerLink="tools/export"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization?.canAccessImportExport"
>
{{ "exportVault" | i18n }}
</a>
<a
routerLink="sso"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization?.canManageSso"
>
{{ "singleSignOn" | i18n }}
</a>
<a
routerLink="scim"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization?.canManageScim"
>
{{ "scim" | i18n }}
</a>
</div>
</div>
</div>

View File

@@ -1,30 +1,34 @@
import { Component } from "@angular/core";
import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { Subject, switchMap, takeUntil } from "rxjs";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { Organization } from "@bitwarden/common/models/domain/organization";
@Component({
selector: "app-org-settings",
templateUrl: "settings.component.html",
})
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
export class SettingsComponent {
access2fa = false;
showBilling: boolean;
export class SettingsComponent implements OnInit, OnDestroy {
organization: Organization;
constructor(
private route: ActivatedRoute,
private organizationService: OrganizationService,
private platformUtilsService: PlatformUtilsService
) {}
private destroy$ = new Subject<void>();
constructor(private route: ActivatedRoute, private organizationService: OrganizationService) {}
ngOnInit() {
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
this.route.parent.params.subscribe(async (params) => {
const organization = await this.organizationService.get(params.organizationId);
this.showBilling = !this.platformUtilsService.isSelfHost() && organization.canManageBilling;
this.access2fa = organization.use2fa;
});
this.route.params
.pipe(
switchMap(async (params) => await this.organizationService.get(params.organizationId)),
takeUntil(this.destroy$)
)
.subscribe((organization) => {
this.organization = organization;
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}

View File

@@ -15,8 +15,8 @@ import { ProductType } from "@bitwarden/common/enums/productType";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { OrganizationSponsorshipRedeemRequest } from "@bitwarden/common/models/request/organization/organizationSponsorshipRedeemRequest";
import { DeleteOrganizationComponent } from "../../organizations/settings";
import { OrganizationPlansComponent } from "../../settings/organization-plans.component";
import { DeleteOrganizationComponent } from "../settings/delete-organization.component";
@Component({
selector: "families-for-enterprise-setup",