Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change restrictor for Orgaadmin #4382

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { ActivatedRoute } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Observable, Subject } from 'rxjs';
import { Collection, Fqid, Id } from 'src/app/domain/definitions/key-types';
import { OML } from 'src/app/domain/definitions/organization-permission';
import { Selectable } from 'src/app/domain/interfaces';
import { BaseModel } from 'src/app/domain/models/base/base-model';
import { HistoryPosition, HistoryPresenterService } from 'src/app/gateways/presenter/history-presenter.service';
Expand Down Expand Up @@ -93,10 +92,6 @@ export class HistoryListComponent extends BaseMeetingComponent implements OnInit
}
}

public get isSuperadmin(): boolean {
return this.operator.hasOrganizationPermissions(OML.superadmin);
}

public constructor(
protected override translate: TranslateService,
private viewModelStore: ViewModelStoreService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,6 @@ export class GroupListComponent extends BaseMeetingComponent implements OnInit,
* Function to allow to edit the external_id
*/
public get allowExternalId(): boolean {
return this.operator.isMeetingAdmin || this.operator.isSuperAdmin;
return this.operator.isMeetingAdmin || this.operator.canSkipPermissionCheck;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export class AccountAddToMeetingsComponent extends BaseUiComponent implements On
.getViewModelListObservable()
.pipe(
map(meetings =>
this.operator.isSuperAdmin
this.operator.canSkipPermissionCheck
? meetings.filter(meeting => !meeting.locked_from_inside)
: meetings.filter(
meeting => this.operator.isInMeeting(meeting.id) && !meeting.locked_from_inside
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ export class AccountDetailComponent extends BaseComponent implements OnInit {
}

public get orgaManagementLevelChangeDisabled(): boolean {
return this.user?.id === this.operator.operatorId && this.operator.isSuperAdmin;
return (
this.user?.id === this.operator.operatorId &&
(this.operator.isSuperAdmin || this.operator.isOrgaManager || this.operator.isAccountAdmin)
);
}

@ViewChild(UserDetailViewComponent, { static: false })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export class AccountListComponent extends BaseListViewComponent<ViewUser> {
const meetings = this.meetingRepo.getViewModelList();
const result = await this.choiceService.open<ViewMeeting>({
title,
choices: this.operator.isSuperAdmin
choices: this.operator.canSkipPermissionCheck
? meetings.filter(meeting => !meeting.locked_from_inside)
: meetings.filter(meeting => this.operator.isInMeeting(meeting.id) && !meeting.locked_from_inside),
multiSelect: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
@if (meeting.isArchived) {
<mat-label class="archived-label">{{ 'Archived' | translate }}</mat-label>
}
<ng-container *osCmlPerms="CML.can_manage; committeeId: committee.id; nonAdminCheck: true">
<ng-container *osCmlPerms="CML.can_manage; committeeId: committee.id">
@if (isTemplateMeeting) {
<div class="template-indicator">
<mat-icon [matTooltip]="'Public template' | translate">star</mat-icon>
Expand Down Expand Up @@ -131,7 +131,7 @@

<mat-menu #meetingMenu="matMenu">
<ng-template matMenuContent>
@if (!meeting.isArchived && (meeting?.canBeEnteredBy(operator.user) || operator.isSuperAdmin)) {
@if (!meeting.isArchived && (meeting?.canBeEnteredBy(operator.user) || operator.canSkipPermissionCheck)) {
<a mat-menu-item [routerLink]="['meeting', 'edit', meeting.id]">
<mat-icon>edit</mat-icon>
<span>{{ 'Edit' | translate }}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export class MeetingEditComponent extends BaseComponent implements OnInit {

private onAfterCreateForm(): void {
this.enableFormControls();
if (!this.operator.isSuperAdmin && !this.isMeetingAdmin && !this.isCreateView) {
if (!this.operator.canSkipPermissionCheck && !this.isMeetingAdmin && !this.isCreateView) {
Object.keys(this.meetingForm.controls).forEach(controlName => {
if (!ORGA_ADMIN_ALLOWED_CONTROLNAMES.includes(controlName)) {
this.meetingForm.get(controlName)!.disable();
Expand Down Expand Up @@ -347,7 +347,7 @@ export class MeetingEditComponent extends BaseComponent implements OnInit {

private async doUpdateMeeting(): Promise<void> {
const options =
this.operator.isSuperAdmin && !this.isMeetingAdmin && this.editMeeting?.locked_from_inside
this.operator.canSkipPermissionCheck && !this.isMeetingAdmin && this.editMeeting?.locked_from_inside
? {}
: this.getUsersToUpdateForMeetingObject();
await this.meetingRepo.update(this.sanitizePayload(this.getPayload()), {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<os-head-bar
[customMenu]="true"
[hasMainButton]="canManageMeetingsInCommittee"
[hasMainButton]="canManageCommittee"
[mainActionTooltip]="'New meeting' | translate"
[nav]="false"
(mainEvent)="onCreateMeeting()"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ export class CommitteeDetailViewComponent extends BaseUiComponent {
public forwardingExpanded = false;
public requireDuplicateFrom = false;

public get canManageMeetingsInCommittee(): boolean {
return this.operator.hasCommitteePermissionsNonAdminCheck(this.committeeId, CML.can_manage);
}

public get canManageCommittee(): boolean {
return this.operator.hasCommitteePermissions(this.committeeId, CML.can_manage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export class DashboardComponent extends BaseComponent {
const filteredMeetings = meetings.filter(
meeting =>
this.operator.isInMeeting(meeting.id) ||
this.operator.isSuperAdmin ||
this.operator.canSkipPermissionCheck ||
(meeting.publicAccessPossible() && this.operator.isAnonymous)
);
const currentDate = new Date();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,7 @@ <h2>{{ 'Meetings' | translate }}</h2>

<!-- Is Template -->
<span
*osCmlPerms="
CML.can_manage;
committeeId: meeting.committee_id;
nonAdminCheck: true;
and: meeting.isTemplate
"
*osCmlPerms="CML.can_manage; committeeId: meeting.committee_id; and: meeting.isTemplate"
class="icon-prefix"
>
<mat-icon [matTooltip]="'Public template' | translate">star</mat-icon>
Expand Down Expand Up @@ -181,7 +176,7 @@ <h2>{{ 'Meetings' | translate }}</h2>

<div *osScrollingTableCell="'menu'; row as meeting; config: { width: 40 }">
<button
*osCmlPerms="CML.can_manage; committeeId: meeting.committee?.id; nonAdminCheck: true"
*osCmlPerms="CML.can_manage; committeeId: meeting.committee?.id"
data-cy="meetingListSingleMenuTrigger"
mat-icon-button
[disabled]="isMultiSelect"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export class MeetingListFilterService extends BaseFilterListService<ViewMeeting>
}

protected override preFilter(rawInputData: ViewMeeting[]): ViewMeeting[] {
return this.operator.isSuperAdmin
return this.operator.canSkipPermissionCheck
? rawInputData
: rawInputData.filter(meeting => this.operator.isInMeeting(meeting.id));
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/site/services/auth-check.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export class AuthCheckService {
await this.fetchMeetingIfNotExists(+meetingIdString);

await this.operator.ready;
return this.operator.isInMeeting(Number(meetingIdString)) || this.operator.isSuperAdmin;
return this.operator.isInMeeting(Number(meetingIdString)) || this.operator.canSkipPermissionCheck;
}

private async fetchMeetingIfNotExists(meetingId: Id): Promise<void> {
Expand Down
41 changes: 17 additions & 24 deletions client/src/app/site/services/operator.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ export class OperatorService {
return this.hasOrganizationPermissions(OML.can_manage_organization);
}

public get canSkipPermissionCheck(): boolean {
return this.isSuperAdmin || this.isOrgaManager;
}

public get isAccountAdmin(): boolean {
return this.hasOrganizationPermissions(OML.can_manage_users);
}
Expand All @@ -100,9 +104,7 @@ export class OperatorService {
}

public get isAnyManager(): boolean {
return this.isSuperAdmin || this.isOrgaManager || this.readyDeferred.wasResolved
? this.isCommitteeManager
: false;
return this.canSkipPermissionCheck || this.readyDeferred.wasResolved ? this.isCommitteeManager : false;
}

public get knowsMultipleMeetings(): boolean {
Expand Down Expand Up @@ -588,7 +590,7 @@ export class OperatorService {
// console.warn(`has perms: Usage outside of meeting!`);
return false;
}
if (this.isSuperAdmin && !this.activeMeeting.locked_from_inside) {
if (this.canSkipPermissionCheck && !this.activeMeeting.locked_from_inside) {
return true;
}

Expand All @@ -612,7 +614,7 @@ export class OperatorService {
// console.warn(`has perms: Operator is not ready!`);
return false;
}
if (this.isSuperAdmin && !this.activeMeeting.locked_from_inside) {
if (this.canSkipPermissionCheck && !this.activeMeeting.locked_from_inside) {
return true;
}
const groups = this.user.groups(meetingId);
Expand Down Expand Up @@ -660,17 +662,8 @@ export class OperatorService {
* @returns A boolean whether an operator's CML is high enough.
*/
public hasCommitteePermissions(committeeId: Id | null, ...permissionsToCheck: CML[]): boolean {
// If a user can manage an entire organization, they can also manage every committee.
// Regardless, if they have no CML.
if (this.isOrgaManager) {
return true;
}
return this.hasCommitteePermissionsNonAdminCheck(committeeId, ...permissionsToCheck);
}

public hasCommitteePermissionsNonAdminCheck(committeeId: Id | null, ...permissionsToCheck: CML[]): boolean {
// A superadmin can still do everything
if (this.isSuperAdmin) {
// A superadmin and orgaadmin can do everything
if (this.canSkipPermissionCheck) {
return true;
}
// A user can have a CML for any committee but they could be not present in some of them.
Expand All @@ -694,7 +687,7 @@ export class OperatorService {
* @returns `true`, if the current operator is included in at least one of the given committees.
*/
public isInCommittees(...committees: Committee[]): boolean {
if (this.isSuperAdmin) {
if (this.canSkipPermissionCheck) {
return true;
}
return this.isInCommitteesNonAdminCheck(...committees);
Expand All @@ -714,7 +707,7 @@ export class OperatorService {

/**
* This function checks if the operator is in one of the given groups. It is also a permission check.
* That means, if the operator is an admin or a superadmin, this function will return `true`, too.
* That means, if the operator is an admin a superadmin or an orgaadmin, this function will return `true`, too.
*
* TODO: what if no active meeting??
*
Expand All @@ -728,19 +721,19 @@ export class OperatorService {

/**
* This checks if an operator is in at least one of the given groups. It is also a permission check.
* That means, if the operator is an admin or a superadmin, this function returns `true`, too.
* That means, if the operator is an admin, a superadmin or an orgaadmin, this function returns `true`, too.
*
* TODO: what if no active meeting??
*
* @param groups The group ids to check
*
* @returns `true`, if the operator is in at least one group or they are an admin or a superadmin.
* @returns `true`, if the operator is in at least one group or they are an admin. a superadmin or a orgaadmin.
*/
public isInGroupIds(...groupIds: Id[]): boolean {
if (!this._groupIds) {
return false;
}
if (this.isSuperAdmin) {
if (this.canSkipPermissionCheck) {
return true;
}
if (!this.isInGroupIdsNonAdminCheck(...groupIds)) {
Expand All @@ -751,7 +744,7 @@ export class OperatorService {
}

public isInMeetingIds(...meetingIds: Id[]): boolean {
if (this.isSuperAdmin) {
if (this.canSkipPermissionCheck) {
return true;
}
if (!this._meetingIds) {
Expand All @@ -762,8 +755,8 @@ export class OperatorService {

/**
* Function to clear check if an operator is in at least of the given groups.
* This check is not a check for permissions and does neither include a check for an admin
* nor include a check for a superadmin.
* This check is not a check for permissions and does
* neither include a check for an admin, a superadmin, nor an orgaadmin
*
* @param groups The group ids to check
*
Expand Down
27 changes: 2 additions & 25 deletions client/src/app/ui/directives/perms/cml-perms.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ type TestConditionalType = {

@Component({
template: `
<div
*osCmlPerms="permission; committeeId: conditionals.id; nonAdminCheck: conditionals.nonAdmin"
id="normal"
></div>
<div *osCmlPerms="permission; committeeId: conditionals.id" id="normal"></div>
<div *osCmlPerms="permission; committeeId: conditionals.id; or: conditionals.or" id="or"></div>
<div *osCmlPerms="permission; committeeId: conditionals.id; and: conditionals.and" id="and"></div>
<div
Expand Down Expand Up @@ -64,11 +61,7 @@ class MockOperatorService {
}

public hasCommitteePermissions(committeeId: Id | null, ...checkPerms: CML[]): boolean {
return this._isAdmin || this.hasCommitteePermissionsNonAdminCheck(committeeId, ...checkPerms);
}

public hasCommitteePermissionsNonAdminCheck(committeeId: Id | null, ...checkPerms: CML[]): boolean {
return checkPerms.some(perm => this._permList.includes(perm));
return this._isAdmin || checkPerms.some(perm => this._permList.includes(perm));
}

public changeOperatorPermsForTest(newPermList: CML[], oml?: OML | undefined): void {
Expand Down Expand Up @@ -121,22 +114,6 @@ describe(`CmlPermsDirective`, () => {
expect(getElement(`#normal`)).toBeTruthy();
});

it(`check if element gets restricted with non-admin-check`, async () => {
fixture.componentInstance.setTestComponentData({ nonAdmin: true });
operatorService.changeOperatorPermsForTest([CML.can_manage]);
update();
expect(getElement(`#normal`)).toBeTruthy();
operatorService.changeOperatorPermsForTest([]);
update();
expect(getElement(`#normal`)).toBeFalsy();
operatorService.changeOperatorPermsForTest([CML.can_manage], OML.superadmin);
update();
expect(getElement(`#normal`)).toBeTruthy();
operatorService.changeOperatorPermsForTest([], OML.superadmin);
update();
expect(getElement(`#normal`)).toBeFalsy();
});

it(`check if or condition works`, async () => {
expect(getElement(`#or`)).toBeTruthy();
fixture.componentInstance.setTestComponentData({ or: false });
Expand Down
13 changes: 1 addition & 12 deletions client/src/app/ui/directives/perms/cml-perms.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ export class CmlPermsDirective extends BasePermsDirective<CML> {
this.setComplementCondition(value);
}

@Input()
public set osCmlPermsNonAdminCheck(value: boolean) {
this._checkNonAdmin = value;
this.updatePermission();
}

@Input()
public set osCmlPermsThen(template: TemplateRef<any>) {
this.setThenTemplate(template);
Expand All @@ -57,7 +51,6 @@ export class CmlPermsDirective extends BasePermsDirective<CML> {
}

private _committeeId: Id | undefined = undefined;
private _checkNonAdmin = false;
private _orOML: OML | undefined = undefined;

protected hasPermissions(): boolean {
Expand All @@ -67,10 +60,6 @@ export class CmlPermsDirective extends BasePermsDirective<CML> {
if (!this._committeeId) {
return false;
}
if (this._checkNonAdmin) {
return this.operator.hasCommitteePermissionsNonAdminCheck(this._committeeId, ...this.permissions);
} else {
return this.operator.hasCommitteePermissions(this._committeeId, ...this.permissions);
}
return this.operator.hasCommitteePermissions(this._committeeId, ...this.permissions);
}
}
Loading