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:
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
@@ -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,
|
||||
],
|
||||
|
||||
@@ -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",
|
||||
|
||||
12
apps/web/src/app/organizations/policies/index.ts
Normal file
12
apps/web/src/app/organizations/policies/index.ts
Normal 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";
|
||||
@@ -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";
|
||||
|
||||
46
apps/web/src/app/organizations/policies/policies.module.ts
Normal file
46
apps/web/src/app/organizations/policies/policies.module.ts
Normal 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 {}
|
||||
@@ -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",
|
||||
@@ -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>
|
||||
|
||||
2
apps/web/src/app/organizations/settings/index.ts
Normal file
2
apps/web/src/app/organizations/settings/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./organization-settings.module";
|
||||
export { DeleteOrganizationComponent } from "./delete-organization.component";
|
||||
@@ -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 {}
|
||||
@@ -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 {}
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user