mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-23 11:56:00 +01:00
Feature/split manage collections permission (#1211)
* Update guard services and routing * Add depenent checkbox to handle sub permissions * Present new collections premissions * Use new split permissions * Rename to nested-checkbox.component * Clarify css class name * update jslib
This commit is contained in:
parent
7a43510cf5
commit
998d36a5d1
2
jslib
2
jslib
@ -1 +1 @@
|
||||
Subproject commit ce71c0c0bd6667573e0e611222dc415770ba3909
|
||||
Subproject commit 91c5393ae7a84e9f4d90391d072cae56e7a3ff41
|
18
src/app/components/nested-checkbox.component.html
Normal file
18
src/app/components/nested-checkbox.component.html
Normal file
@ -0,0 +1,18 @@
|
||||
<div class="form-group mb-0">
|
||||
<div class="form-check mt-1 form-check-block">
|
||||
<input class="form-check-input" type="checkbox" [name]="pascalize(parentId)" [id]="parentId"
|
||||
[(ngModel)]="parentChecked" [indeterminate]="parentIndeterminate">
|
||||
<label class="form-check-label font-weight-normal" [for]="parentId">
|
||||
{{parentId | i18n}}
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group form-group-child-check mb-0">
|
||||
<div class="form-check mt-1" *ngFor="let c of checkboxes">
|
||||
<input class="form-check-input" type="checkbox" [name]="pascalize(c.id)" [id]="c.id" [ngModel]="c.get()"
|
||||
(ngModelChange)="c.set($event)">
|
||||
<label class="form-check-label font-weight-normal" [for]="c.id">
|
||||
{{c.id | i18n}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
37
src/app/components/nested-checkbox.component.ts
Normal file
37
src/app/components/nested-checkbox.component.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import {
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
Output,
|
||||
} from '@angular/core';
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-nested-checkbox',
|
||||
templateUrl: 'nested-checkbox.component.html',
|
||||
})
|
||||
export class NestedCheckboxComponent {
|
||||
@Input() parentId: string;
|
||||
@Input() checkboxes: { id: string, get: () => boolean, set: (v: boolean) => void; }[];
|
||||
@Output() onSavedUser = new EventEmitter();
|
||||
@Output() onDeletedUser = new EventEmitter();
|
||||
|
||||
get parentIndeterminate() {
|
||||
return !this.parentChecked &&
|
||||
this.checkboxes.some(c => c.get());
|
||||
}
|
||||
|
||||
get parentChecked() {
|
||||
return this.checkboxes.every(c => c.get());
|
||||
}
|
||||
|
||||
set parentChecked(value: boolean) {
|
||||
this.checkboxes.forEach(c => {
|
||||
c.set(value);
|
||||
});
|
||||
}
|
||||
|
||||
pascalize(s: string) {
|
||||
return Utils.camelToPascalCase(s);
|
||||
}
|
||||
}
|
@ -82,8 +82,8 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
|
||||
|
||||
get showManageTab(): boolean {
|
||||
return this.organization.canManageUsers ||
|
||||
this.organization.canManageAssignedCollections ||
|
||||
this.organization.canManageAllCollections ||
|
||||
this.organization.canViewAllCollections ||
|
||||
this.organization.canViewAssignedCollections ||
|
||||
this.organization.canManageGroups ||
|
||||
this.organization.canManagePolicies ||
|
||||
this.organization.canAccessEventLogs;
|
||||
@ -109,7 +109,7 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
|
||||
case this.organization.canManageUsers:
|
||||
route = 'manage/people';
|
||||
break;
|
||||
case this.organization.canManageAssignedCollections || this.organization.canManageAllCollections:
|
||||
case this.organization.canViewAssignedCollections || this.organization.canViewAllCollections:
|
||||
route = 'manage/collections';
|
||||
break;
|
||||
case this.organization.canManageGroups:
|
||||
|
@ -69,7 +69,7 @@ export class CollectionsComponent implements OnInit {
|
||||
async load() {
|
||||
const organization = await this.userService.getOrganization(this.organizationId);
|
||||
let response: ListResponse<CollectionResponse>;
|
||||
if (organization.canManageAllCollections) {
|
||||
if (organization.canViewAllCollections) {
|
||||
response = await this.apiService.getCollections(this.organizationId);
|
||||
} else {
|
||||
response = await this.apiService.getUserCollections();
|
||||
|
@ -9,7 +9,7 @@
|
||||
{{'people' | i18n}}
|
||||
</a>
|
||||
<a routerLink="collections" class="list-group-item" routerLinkActive="active"
|
||||
*ngIf="organization.canManageAssignedCollections || organization.canManageAllCollections">
|
||||
*ngIf="organization.canViewAssignedCollections || organization.canViewAllCollections">
|
||||
{{'collections' | i18n}}
|
||||
</a>
|
||||
<a routerLink="groups" class="list-group-item" routerLinkActive="active"
|
||||
|
@ -80,7 +80,8 @@
|
||||
<div class="mb-3">
|
||||
<label class="font-weight-bold mb-0">Manager Permissions</label>
|
||||
<hr class="my-0 mr-2" />
|
||||
<div class="form-group mb-0">
|
||||
<!-- Deprecated Sep 29 2021 -->
|
||||
<div class="form-group mb-0" *ngIf="fallbackToManageAssignedCollections">
|
||||
<div class="form-check mt-1 form-check-block">
|
||||
<input class="form-check-input" type="checkbox" name="manageAssignedCollections"
|
||||
id="manageAssignedCollections"
|
||||
@ -91,6 +92,10 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- -->
|
||||
<app-nested-checkbox *ngIf="!fallbackToManageAssignedCollections" parentId="manageAssignedCollections"
|
||||
[checkboxes]="manageAssignedCollectionsCheckboxes">
|
||||
</app-nested-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
@ -133,7 +138,8 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<!-- Deprecated 29 Sep 2021 -->
|
||||
<div class="form-group mb-0" *ngIf="fallbackToManageAllCollections">
|
||||
<div class="form-check mt-1 form-check-block">
|
||||
<input class="form-check-input" type="checkbox" name="manageAllCollections"
|
||||
id="manageAllCollections" [(ngModel)]="permissions.manageAllCollections">
|
||||
@ -142,6 +148,10 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- -->
|
||||
<app-nested-checkbox *ngIf="!fallbackToManageAllCollections" parentId="manageAllCollections"
|
||||
[checkboxes]="manageAllCollectionsCheckboxes">
|
||||
</app-nested-checkbox>
|
||||
<div class="form-group mb-0">
|
||||
<div class="form-check mt-1 form-check-block">
|
||||
<input class="form-check-input" type="checkbox" name="manageGroups"
|
||||
|
@ -48,6 +48,48 @@ export class UserAddEditComponent implements OnInit {
|
||||
deletePromise: Promise<any>;
|
||||
organizationUserType = OrganizationUserType;
|
||||
|
||||
manageAllCollectionsCheckboxes = [
|
||||
{
|
||||
id: 'createNewCollections',
|
||||
get: () => this.permissions.createNewCollections,
|
||||
set: (v: boolean) => this.permissions.createNewCollections = v,
|
||||
},
|
||||
{
|
||||
id: 'editAnyCollection',
|
||||
get: () => this.permissions.editAnyCollection,
|
||||
set: (v: boolean) => this.permissions.editAnyCollection = v,
|
||||
},
|
||||
{
|
||||
id: 'deleteAnyCollection',
|
||||
get: () => this.permissions.deleteAnyCollection,
|
||||
set: (v: boolean) => this.permissions.deleteAnyCollection = v,
|
||||
},
|
||||
];
|
||||
|
||||
manageAssignedCollectionsCheckboxes = [
|
||||
{
|
||||
id: 'editAssignedCollections',
|
||||
get: () => this.permissions.editAssignedCollections,
|
||||
set: (v: boolean) => this.permissions.editAssignedCollections = v,
|
||||
},
|
||||
{
|
||||
id: 'deleteAssignedCollections',
|
||||
get: () => this.permissions.deleteAssignedCollections,
|
||||
set: (v: boolean) => this.permissions.deleteAssignedCollections = v,
|
||||
},
|
||||
];
|
||||
|
||||
get fallbackToManageAllCollections() {
|
||||
return this.permissions.createNewCollections == null &&
|
||||
this.permissions.editAnyCollection == null &&
|
||||
this.permissions.deleteAnyCollection == null;
|
||||
}
|
||||
|
||||
get fallbackToManageAssignedCollections() {
|
||||
return this.permissions.editAssignedCollections == null &&
|
||||
this.permissions.deleteAssignedCollections == null;
|
||||
}
|
||||
|
||||
get customUserTypeSelected(): boolean {
|
||||
return this.type === OrganizationUserType.Custom;
|
||||
}
|
||||
@ -107,39 +149,7 @@ export class UserAddEditComponent implements OnInit {
|
||||
}
|
||||
|
||||
setRequestPermissions(p: PermissionsApi, clearPermissions: boolean) {
|
||||
p.accessBusinessPortal = clearPermissions ?
|
||||
false :
|
||||
this.permissions.accessBusinessPortal;
|
||||
p.accessEventLogs = this.permissions.accessEventLogs = clearPermissions ?
|
||||
false :
|
||||
this.permissions.accessEventLogs;
|
||||
p.accessImportExport = clearPermissions ?
|
||||
false :
|
||||
this.permissions.accessImportExport;
|
||||
p.accessReports = clearPermissions ?
|
||||
false :
|
||||
this.permissions.accessReports;
|
||||
p.manageAllCollections = clearPermissions ?
|
||||
false :
|
||||
this.permissions.manageAllCollections;
|
||||
p.manageAssignedCollections = clearPermissions ?
|
||||
false :
|
||||
this.permissions.manageAssignedCollections;
|
||||
p.manageGroups = clearPermissions ?
|
||||
false :
|
||||
this.permissions.manageGroups;
|
||||
p.manageSso = clearPermissions ?
|
||||
false :
|
||||
this.permissions.manageSso;
|
||||
p.managePolicies = clearPermissions ?
|
||||
false :
|
||||
this.permissions.managePolicies;
|
||||
p.manageUsers = clearPermissions ?
|
||||
false :
|
||||
this.permissions.manageUsers;
|
||||
p.manageResetPassword = clearPermissions ?
|
||||
false :
|
||||
this.permissions.manageResetPassword;
|
||||
Object.assign(p, clearPermissions ? new PermissionsApi() : this.permissions);
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -203,5 +213,4 @@ export class UserAddEditComponent implements OnInit {
|
||||
this.onDeletedUser.emit();
|
||||
} catch { }
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
protected allowOwnershipAssignment() {
|
||||
if (this.ownershipOptions != null && (this.ownershipOptions.length > 1 || !this.allowPersonal)) {
|
||||
if (this.organization != null) {
|
||||
return this.cloneMode && this.organization.canManageAllCollections;
|
||||
return this.cloneMode && this.organization.canEditAnyCollection;
|
||||
} else {
|
||||
return !this.editMode || this.cloneMode;
|
||||
}
|
||||
@ -55,14 +55,14 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
}
|
||||
|
||||
protected loadCollections() {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canEditAnyCollection) {
|
||||
return super.loadCollections();
|
||||
}
|
||||
return Promise.resolve(this.collections);
|
||||
}
|
||||
|
||||
protected async loadCipher() {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canEditAnyCollection) {
|
||||
return await super.loadCipher();
|
||||
}
|
||||
const response = await this.apiService.getCipherAdmin(this.cipherId);
|
||||
@ -72,14 +72,14 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
}
|
||||
|
||||
protected encryptCipher() {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canEditAnyCollection) {
|
||||
return super.encryptCipher();
|
||||
}
|
||||
return this.cipherService.encrypt(this.cipher, null, this.originalCipher);
|
||||
}
|
||||
|
||||
protected async saveCipher(cipher: Cipher) {
|
||||
if (!this.organization.canManageAllCollections || cipher.organizationId == null) {
|
||||
if (!this.organization.canEditAnyCollection || cipher.organizationId == null) {
|
||||
return super.saveCipher(cipher);
|
||||
}
|
||||
if (this.editMode && !this.cloneMode) {
|
||||
@ -92,7 +92,7 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
}
|
||||
|
||||
protected async deleteCipher() {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canEditAnyCollection) {
|
||||
return super.deleteCipher();
|
||||
}
|
||||
return this.cipher.isDeleted ? this.apiService.deleteCipherAdmin(this.cipherId)
|
||||
|
@ -30,13 +30,13 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
}
|
||||
|
||||
protected async reupload(attachment: AttachmentView) {
|
||||
if (this.organization.canManageAllCollections && this.showFixOldAttachments(attachment)) {
|
||||
if (this.organization.canEditAnyCollection && this.showFixOldAttachments(attachment)) {
|
||||
await super.reuploadCipherAttachment(attachment, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected async loadCipher() {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canEditAnyCollection) {
|
||||
return await super.loadCipher();
|
||||
}
|
||||
const response = await this.apiService.getCipherAdmin(this.cipherId);
|
||||
@ -44,17 +44,17 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
}
|
||||
|
||||
protected saveCipherAttachment(file: File) {
|
||||
return this.cipherService.saveAttachmentWithServer(this.cipherDomain, file, this.organization.canManageAllCollections);
|
||||
return this.cipherService.saveAttachmentWithServer(this.cipherDomain, file, this.organization.canEditAnyCollection);
|
||||
}
|
||||
|
||||
protected deleteCipherAttachment(attachmentId: string) {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canEditAnyCollection) {
|
||||
return super.deleteCipherAttachment(attachmentId);
|
||||
}
|
||||
return this.apiService.deleteCipherAttachmentAdmin(this.cipherId, attachmentId);
|
||||
}
|
||||
|
||||
protected showFixOldAttachments(attachment: AttachmentView) {
|
||||
return attachment.key == null && this.organization.canManageAllCollections;
|
||||
return attachment.key == null && this.organization.canEditAnyCollection;
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ export class CiphersComponent extends BaseCiphersComponent {
|
||||
}
|
||||
|
||||
async load(filter: (cipher: CipherView) => boolean = null) {
|
||||
if (this.organization.canManageAllCollections) {
|
||||
if (this.organization.canViewAllCollections) {
|
||||
this.accessEvents = this.organization.useEvents;
|
||||
this.allCiphers = await this.cipherService.getAllFromApiForOrganization(this.organization.id);
|
||||
} else {
|
||||
@ -54,7 +54,7 @@ export class CiphersComponent extends BaseCiphersComponent {
|
||||
}
|
||||
|
||||
async applyFilter(filter: (cipher: CipherView) => boolean = null) {
|
||||
if (this.organization.canManageAllCollections) {
|
||||
if (this.organization.canViewAllCollections) {
|
||||
await super.applyFilter(filter);
|
||||
} else {
|
||||
const f = (c: CipherView) => c.organizationId === this.organization.id && (filter == null || filter(c));
|
||||
@ -70,13 +70,13 @@ export class CiphersComponent extends BaseCiphersComponent {
|
||||
}
|
||||
|
||||
protected deleteCipher(id: string) {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canEditAnyCollection) {
|
||||
return super.deleteCipher(id, this.deleted);
|
||||
}
|
||||
return this.deleted ? this.apiService.deleteCipherAdmin(id) : this.apiService.putDeleteCipherAdmin(id);
|
||||
}
|
||||
|
||||
protected showFixOldAttachments(c: CipherView) {
|
||||
return this.organization.canManageAllCollections && c.hasOldAttachments;
|
||||
return this.organization.canEditAnyCollection && c.hasOldAttachments;
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ export class CollectionsComponent extends BaseCollectionsComponent {
|
||||
}
|
||||
|
||||
protected async loadCipher() {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canViewAllCollections) {
|
||||
return await super.loadCipher();
|
||||
}
|
||||
const response = await this.apiService.getCipherAdmin(this.cipherId);
|
||||
@ -36,21 +36,21 @@ export class CollectionsComponent extends BaseCollectionsComponent {
|
||||
}
|
||||
|
||||
protected loadCipherCollections() {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canViewAllCollections) {
|
||||
return super.loadCipherCollections();
|
||||
}
|
||||
return this.collectionIds;
|
||||
}
|
||||
|
||||
protected loadCollections() {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canViewAllCollections) {
|
||||
return super.loadCollections();
|
||||
}
|
||||
return Promise.resolve(this.collections);
|
||||
}
|
||||
|
||||
protected saveCollections() {
|
||||
if (this.organization.canManageAllCollections) {
|
||||
if (this.organization.canEditAnyCollection) {
|
||||
const request = new CipherCollectionsRequest(this.cipherDomain.collectionIds);
|
||||
return this.apiService.putCipherCollectionsAdmin(this.cipherId, request);
|
||||
} else {
|
||||
|
@ -29,7 +29,7 @@ export class GroupingsComponent extends BaseGroupingsComponent {
|
||||
}
|
||||
|
||||
async loadCollections() {
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canViewAllCollections) {
|
||||
await super.loadCollections(this.organization.id);
|
||||
return;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
|
||||
const queryParamsSub = this.route.queryParams.subscribe(async qParams => {
|
||||
this.ciphersComponent.searchText = this.groupingsComponent.searchText = qParams.search;
|
||||
if (!this.organization.canManageAllCollections) {
|
||||
if (!this.organization.canViewAllCollections) {
|
||||
await this.syncService.fullSync(false);
|
||||
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
||||
this.ngZone.run(async () => {
|
||||
@ -223,7 +223,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
|
||||
async editCipherCollections(cipher: CipherView) {
|
||||
const [modal] = await this.modalService.openViewRef(CollectionsComponent, this.collectionsModalRef, comp => {
|
||||
if (this.organization.canManageAllCollections) {
|
||||
if (this.organization.canEditAnyCollection) {
|
||||
comp.collectionIds = cipher.collectionIds;
|
||||
comp.collections = this.groupingsComponent.collections.filter(c => !c.readOnly);
|
||||
}
|
||||
@ -240,7 +240,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
const component = await this.editCipher(null);
|
||||
component.organizationId = this.organization.id;
|
||||
component.type = this.type;
|
||||
if (this.organization.canManageAllCollections) {
|
||||
if (this.organization.canEditAnyCollection) {
|
||||
component.collections = this.groupingsComponent.collections.filter(c => !c.readOnly);
|
||||
}
|
||||
if (this.collectionId != null) {
|
||||
@ -273,7 +273,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
const component = await this.editCipher(cipher);
|
||||
component.cloneMode = true;
|
||||
component.organizationId = this.organization.id;
|
||||
if (this.organization.canManageAllCollections) {
|
||||
if (this.organization.canEditAnyCollection) {
|
||||
component.collections = this.groupingsComponent.collections.filter(c => !c.readOnly);
|
||||
}
|
||||
// Regardless of Admin state, the collection Ids need to passed manually as they are not assigned value
|
||||
|
@ -350,8 +350,11 @@ const routes: Routes = [
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
permissions: [
|
||||
Permissions.ManageAssignedCollections,
|
||||
Permissions.ManageAllCollections,
|
||||
Permissions.CreateNewCollections,
|
||||
Permissions.EditAnyCollection,
|
||||
Permissions.DeleteAnyCollection,
|
||||
Permissions.EditAssignedCollections,
|
||||
Permissions.DeleteAssignedCollections,
|
||||
Permissions.AccessEventLogs,
|
||||
Permissions.ManageGroups,
|
||||
Permissions.ManageUsers,
|
||||
@ -370,7 +373,13 @@ const routes: Routes = [
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: 'collections',
|
||||
permissions: [Permissions.ManageAssignedCollections, Permissions.ManageAllCollections],
|
||||
permissions: [
|
||||
Permissions.CreateNewCollections,
|
||||
Permissions.EditAnyCollection,
|
||||
Permissions.DeleteAnyCollection,
|
||||
Permissions.EditAssignedCollections,
|
||||
Permissions.DeleteAssignedCollections,
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -12,6 +12,7 @@ import { ToasterModule } from 'angular2-toaster';
|
||||
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
||||
|
||||
import { AvatarComponent } from './components/avatar.component';
|
||||
import { NestedCheckboxComponent } from './components/nested-checkbox.component';
|
||||
import { PasswordRepromptComponent } from './components/password-reprompt.component';
|
||||
import { PasswordStrengthComponent } from './components/password-strength.component';
|
||||
|
||||
@ -356,6 +357,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
LockComponent,
|
||||
LoginComponent,
|
||||
NavbarComponent,
|
||||
NestedCheckboxComponent,
|
||||
OptionsComponent,
|
||||
OrgAccountComponent,
|
||||
OrgAddEditComponent,
|
||||
|
@ -22,8 +22,11 @@ export class OrganizationTypeGuardService implements CanActivate {
|
||||
(permissions.indexOf(Permissions.AccessEventLogs) !== -1 && org.canAccessEventLogs) ||
|
||||
(permissions.indexOf(Permissions.AccessImportExport) !== -1 && org.canAccessImportExport) ||
|
||||
(permissions.indexOf(Permissions.AccessReports) !== -1 && org.canAccessReports) ||
|
||||
(permissions.indexOf(Permissions.ManageAllCollections) !== -1 && org.canManageAllCollections) ||
|
||||
(permissions.indexOf(Permissions.ManageAssignedCollections) !== -1 && org.canManageAssignedCollections) ||
|
||||
(permissions.indexOf(Permissions.CreateNewCollections) !== -1 && org.canCreateNewCollections) ||
|
||||
(permissions.indexOf(Permissions.EditAnyCollection) !== -1 && org.canEditAnyCollection) ||
|
||||
(permissions.indexOf(Permissions.DeleteAnyCollection) !== -1 && org.canDeleteAnyCollection) ||
|
||||
(permissions.indexOf(Permissions.EditAssignedCollections) !== -1 && org.canEditAssignedCollections) ||
|
||||
(permissions.indexOf(Permissions.DeleteAssignedCollections) !== -1 && org.canDeleteAssignedCollections) ||
|
||||
(permissions.indexOf(Permissions.ManageGroups) !== -1 && org.canManageGroups) ||
|
||||
(permissions.indexOf(Permissions.ManageOrganization) !== -1 && org.isOwner) ||
|
||||
(permissions.indexOf(Permissions.ManagePolicies) !== -1 && org.canManagePolicies) ||
|
||||
|
@ -29,7 +29,7 @@ export class BulkDeleteComponent {
|
||||
private i18nService: I18nService, private apiService: ApiService) { }
|
||||
|
||||
async submit() {
|
||||
if (!this.organization || !this.organization.canManageAllCollections) {
|
||||
if (!this.organization || !this.organization.canEditAnyCollection) {
|
||||
await this.deleteCiphers();
|
||||
} else {
|
||||
await this.deleteCiphersAdmin();
|
||||
|
@ -3824,9 +3824,24 @@
|
||||
"manageAllCollections": {
|
||||
"message": "Manage All Collections"
|
||||
},
|
||||
"createNewCollections": {
|
||||
"message": "Create New Collections"
|
||||
},
|
||||
"editAnyCollection": {
|
||||
"message": "Edit Any Collection"
|
||||
},
|
||||
"deleteAnyCollection": {
|
||||
"message": "Delete Any Collection"
|
||||
},
|
||||
"manageAssignedCollections": {
|
||||
"message": "Manage Assigned Collections"
|
||||
},
|
||||
"editAssignedCollections": {
|
||||
"message": "Edit Assigned Collections"
|
||||
},
|
||||
"deleteAssignedCollections": {
|
||||
"message": "Delete Assigned Collections"
|
||||
},
|
||||
"manageGroups": {
|
||||
"message": "Manage Groups"
|
||||
},
|
||||
|
@ -58,6 +58,12 @@ label.form-check-label, .form-control-file {
|
||||
}
|
||||
}
|
||||
|
||||
.form-group {
|
||||
.form-group-child-check {
|
||||
@extend .ml-4
|
||||
}
|
||||
}
|
||||
|
||||
.form-inline {
|
||||
input[type='datetime-local'] {
|
||||
width: 200px;
|
||||
|
Loading…
Reference in New Issue
Block a user