mirror of
https://github.com/bitwarden/web
synced 2025-12-15 07:43:16 +00:00
OnlyOrg Policy (#669)
* added localization strings needed for the OnlyOrg policy * added deprecation warning to policies page * allowed OnlyOrg policy configuration * blocked creating new orgs if already in an org with OnlyOrg enabled * code review cleanup for onlyOrg * removed a blank line * code review cleanup for onlyOrg
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
<app-callout [type]="'warning'">
|
||||||
|
<p>{{'webPoliciesDeprecationWarning' | i18n}}</p>
|
||||||
|
<button type="button" class="btn btn-outline-secondary"
|
||||||
|
(click)="goToEnterprisePortal()">{{'businessPortal' | i18n}}</button>
|
||||||
|
</app-callout>
|
||||||
<div class="page-header d-flex">
|
<div class="page-header d-flex">
|
||||||
<h1>{{'policies' | i18n}}</h1>
|
<h1>{{'policies' | i18n}}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
import { PolicyType } from 'jslib/enums/policyType';
|
import { PolicyType } from 'jslib/enums/policyType';
|
||||||
|
|
||||||
import { ApiService } from 'jslib/abstractions/api.service';
|
import { ApiService } from 'jslib/abstractions/api.service';
|
||||||
|
import { EnvironmentService } from 'jslib/abstractions';
|
||||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||||
import { UserService } from 'jslib/abstractions/user.service';
|
import { UserService } from 'jslib/abstractions/user.service';
|
||||||
@@ -34,14 +35,19 @@ export class PoliciesComponent implements OnInit {
|
|||||||
organizationId: string;
|
organizationId: string;
|
||||||
policies: any[];
|
policies: any[];
|
||||||
|
|
||||||
|
// Remove when removing deprecation warning
|
||||||
|
enterpriseTokenPromise: Promise<any>;
|
||||||
|
private enterpriseUrl: string;
|
||||||
|
|
||||||
private modal: ModalComponent = null;
|
private modal: ModalComponent = null;
|
||||||
private orgPolicies: PolicyResponse[];
|
private orgPolicies: PolicyResponse[];
|
||||||
private policiesEnabledMap: Map<PolicyType, boolean> = new Map<PolicyType, boolean>();
|
private policiesEnabledMap: Map<PolicyType, boolean> = new Map<PolicyType, boolean>();
|
||||||
|
|
||||||
|
|
||||||
constructor(private apiService: ApiService, private route: ActivatedRoute,
|
constructor(private apiService: ApiService, private route: ActivatedRoute,
|
||||||
private i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver,
|
private i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver,
|
||||||
private platformUtilsService: PlatformUtilsService, private userService: UserService,
|
private platformUtilsService: PlatformUtilsService, private userService: UserService,
|
||||||
private router: Router) {
|
private router: Router, private environmentService: EnvironmentService) {
|
||||||
this.policies = [
|
this.policies = [
|
||||||
{
|
{
|
||||||
name: i18nService.t('twoStepLogin'),
|
name: i18nService.t('twoStepLogin'),
|
||||||
@@ -61,6 +67,12 @@ export class PoliciesComponent implements OnInit {
|
|||||||
type: PolicyType.PasswordGenerator,
|
type: PolicyType.PasswordGenerator,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: i18nService.t('onlyOrg'),
|
||||||
|
description: i18nService.t('onlyOrgDesc'),
|
||||||
|
type: PolicyType.OnlyOrg,
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +86,14 @@ export class PoliciesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
await this.load();
|
await this.load();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Remove when removing deprecation warning
|
||||||
|
this.enterpriseUrl = 'https://portal.bitwarden.com';
|
||||||
|
if (this.environmentService.enterpriseUrl != null) {
|
||||||
|
this.enterpriseUrl = this.environmentService.enterpriseUrl;
|
||||||
|
} else if (this.environmentService.baseUrl != null) {
|
||||||
|
this.enterpriseUrl = this.environmentService.baseUrl + '/portal';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
@@ -111,4 +131,22 @@ export class PoliciesComponent implements OnInit {
|
|||||||
this.modal = null;
|
this.modal = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Remove when removing deprecation warning
|
||||||
|
async goToEnterprisePortal() {
|
||||||
|
if (this.enterpriseTokenPromise != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.enterpriseTokenPromise = this.apiService.getEnterprisePortalSignInToken();
|
||||||
|
const token = await this.enterpriseTokenPromise;
|
||||||
|
if (token != null) {
|
||||||
|
const userId = await this.userService.getUserId();
|
||||||
|
this.platformUtilsService.launchUri(this.enterpriseUrl + '/login?userId=' + userId +
|
||||||
|
'&token=' + (window as any).encodeURIComponent(token) + '&organizationId=' + this.organizationId);
|
||||||
|
}
|
||||||
|
} catch { }
|
||||||
|
this.enterpriseTokenPromise = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
title="{{'warning' | i18n}}" icon="fa-warning">
|
title="{{'warning' | i18n}}" icon="fa-warning">
|
||||||
{{'twoStepLoginPolicyWarning' | i18n}}
|
{{'twoStepLoginPolicyWarning' | i18n}}
|
||||||
</app-callout>
|
</app-callout>
|
||||||
|
<app-callout type="warning" *ngIf="type === policyType.OnlyOrg"
|
||||||
|
title="{{'warning' | i18n}}" icon="fa-warning">
|
||||||
|
{{'onlyOrgPolicyWarning' | i18n}}
|
||||||
|
</app-callout>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" id="enabled" [(ngModel)]="enabled"
|
<input class="form-check-input" type="checkbox" id="enabled" [(ngModel)]="enabled"
|
||||||
|
|||||||
@@ -222,6 +222,9 @@
|
|||||||
<small class="text-muted font-italic mt-2 d-block" *ngIf="!createOrganization">
|
<small class="text-muted font-italic mt-2 d-block" *ngIf="!createOrganization">
|
||||||
{{'paymentCharged' | i18n : (interval | i18n) }}</small>
|
{{'paymentCharged' | i18n : (interval | i18n) }}</small>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="onlyOrgPolicyBlock" class="mt-4">
|
||||||
|
<app-callout [type]="'error'">{{'onlyOrgBlockCreateMessage' | i18n}}</app-callout>
|
||||||
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
||||||
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
|
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ 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 { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||||
|
import { PolicyService } from 'jslib/abstractions/policy.service';
|
||||||
import { SyncService } from 'jslib/abstractions/sync.service';
|
import { SyncService } from 'jslib/abstractions/sync.service';
|
||||||
|
|
||||||
import { PaymentComponent } from './payment.component';
|
import { PaymentComponent } from './payment.component';
|
||||||
import { TaxInfoComponent } from './tax-info.component';
|
import { TaxInfoComponent } from './tax-info.component';
|
||||||
|
|
||||||
import { PlanType } from 'jslib/enums/planType';
|
import { PlanType } from 'jslib/enums/planType';
|
||||||
|
import { PolicyType } from 'jslib/enums/policyType';
|
||||||
import { ProductType } from 'jslib/enums/productType';
|
import { ProductType } from 'jslib/enums/productType';
|
||||||
|
|
||||||
import { OrganizationCreateRequest } from 'jslib/models/request/organizationCreateRequest';
|
import { OrganizationCreateRequest } from 'jslib/models/request/organizationCreateRequest';
|
||||||
@@ -56,13 +58,15 @@ export class OrganizationPlansComponent implements OnInit {
|
|||||||
businessName: string;
|
businessName: string;
|
||||||
productTypes = ProductType;
|
productTypes = ProductType;
|
||||||
formPromise: Promise<any>;
|
formPromise: Promise<any>;
|
||||||
|
onlyOrgPolicyBlock: boolean = false;
|
||||||
|
|
||||||
plans: PlanResponse[];
|
plans: PlanResponse[];
|
||||||
|
|
||||||
constructor(private apiService: ApiService, private i18nService: I18nService,
|
constructor(private apiService: ApiService, private i18nService: I18nService,
|
||||||
private analytics: Angulartics2, private toasterService: ToasterService,
|
private analytics: Angulartics2, private toasterService: ToasterService,
|
||||||
platformUtilsService: PlatformUtilsService, private cryptoService: CryptoService,
|
platformUtilsService: PlatformUtilsService, private cryptoService: CryptoService,
|
||||||
private router: Router, private syncService: SyncService) {
|
private router: Router, private syncService: SyncService,
|
||||||
|
private policyService: PolicyService) {
|
||||||
this.selfHosted = platformUtilsService.isSelfHost();
|
this.selfHosted = platformUtilsService.isSelfHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +197,16 @@ export class OrganizationPlansComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
|
if (this.onlyOrgPolicyBlock) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const policies = await this.policyService.getAll(PolicyType.OnlyOrg);
|
||||||
|
this.onlyOrgPolicyBlock = policies.some(policy => policy.enabled);
|
||||||
|
if (this.onlyOrgPolicyBlock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let files: FileList = null;
|
let files: FileList = null;
|
||||||
if (this.createOrganization && this.selfHosted) {
|
if (this.createOrganization && this.selfHosted) {
|
||||||
const fileEl = document.getElementById('file') as HTMLInputElement;
|
const fileEl = document.getElementById('file') as HTMLInputElement;
|
||||||
|
|||||||
@@ -3206,5 +3206,20 @@
|
|||||||
},
|
},
|
||||||
"linkSso": {
|
"linkSso": {
|
||||||
"message": "Link SSO"
|
"message": "Link SSO"
|
||||||
|
},
|
||||||
|
"webPoliciesDeprecationWarning": {
|
||||||
|
"message": "Policy configuration has been moved, and this page will soon be deprecated. Please click below to use the Business Portal policies page instead."
|
||||||
|
},
|
||||||
|
"onlyOrg": {
|
||||||
|
"message": "Only Organization"
|
||||||
|
},
|
||||||
|
"onlyOrgDesc": {
|
||||||
|
"message": "Restrict users from being able to join any other organizations."
|
||||||
|
},
|
||||||
|
"onlyOrgBlockCreateMessage": {
|
||||||
|
"message": "Your current organization has a policy that does not allow you to join more than one organization. Please contact your organization admins or sign up from a different Bitwarden account."
|
||||||
|
},
|
||||||
|
"onlyOrgPolicyWarning": {
|
||||||
|
"message": "Organization members who are already a member of another organization will be removed from your organization."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user