core: delegated group member management (#9254)

* fix API permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix group member remove notification label

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* consistent naming assign vs grant

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* only set table search query when searching is enabled

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix hidden object permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* replace checkmark/cross with fa icons

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update website

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix tests and fix permission bug

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix migrations

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* reword

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L
2024-04-15 14:14:26 +02:00
committed by GitHub
parent bcc8d5e76c
commit 4a9c95b44e
18 changed files with 160 additions and 53 deletions

View File

@ -134,6 +134,12 @@ export class DeleteBulkForm<T> extends ModalButton {
@property()
buttonLabel = msg("Delete");
/**
* Action shown in messages, for example `deleted` or `removed`
*/
@property()
action = msg("deleted");
@property({ attribute: false })
metadata: (item: T) => BulkDeleteMetadata = (item: T) => {
const rec = item as Record<string, unknown>;

View File

@ -67,7 +67,7 @@ export class PermissionSelectModal extends TableModal<Permission> {
renderModalInner(): TemplateResult {
return html`<section class="pf-c-modal-box__header pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1 class="pf-c-title pf-m-2xl">${msg("Select permissions to grant")}</h1>
<h1 class="pf-c-title pf-m-2xl">${msg("Select permissions to assign")}</h1>
</div>
</section>
<section class="pf-c-modal-box__body pf-m-light">${this.renderTable()}</section>

View File

@ -113,9 +113,9 @@ export class RoleAssignedObjectPermissionTable extends Table<RoleAssignedObjectP
baseRow.push(
html`${granted
? html`<pf-tooltip position="top" content=${msg("Directly assigned")}
>✓</pf-tooltip
>`
: html`X`} `,
><i class="fas fa-check pf-m-success"></i
></pf-tooltip>`
: html`<i class="fas fa-times pf-m-danger"></i>`} `,
);
});
return baseRow;

View File

@ -93,19 +93,24 @@ export class UserObjectPermissionForm extends ModelForm<UserAssignData, number>
>
</ak-search-select>
</ak-form-element-horizontal>
${this.modelPermissions?.results.map((perm) => {
return html` <ak-form-element-horizontal name="permissions.${perm.codename}">
<label class="pf-c-switch">
<input class="pf-c-switch__input" type="checkbox" />
<span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon">
<i class="fas fa-check" aria-hidden="true"></i>
${this.modelPermissions?.results
.filter((perm) => {
const [_app, model] = this.model?.split(".") || "";
return perm.codename !== `add_${model}`;
})
.map((perm) => {
return html` <ak-form-element-horizontal name="permissions.${perm.codename}">
<label class="pf-c-switch">
<input class="pf-c-switch__input" type="checkbox" />
<span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon">
<i class="fas fa-check" aria-hidden="true"></i>
</span>
</span>
</span>
<span class="pf-c-switch__label">${perm.name}</span>
</label>
</ak-form-element-horizontal>`;
})}
<span class="pf-c-switch__label">${perm.name}</span>
</label>
</ak-form-element-horizontal>`;
})}
</form>`;
}
}

View File

@ -45,7 +45,7 @@ export class UserAssignedObjectPermissionTable extends Table<UserAssignedObjectP
ordering: "codename",
});
modelPermissions.results = modelPermissions.results.filter((value) => {
return !value.codename.startsWith("add_");
return value.codename !== `add_${this.model?.split(".")[1]}`;
});
this.modelPermissions = modelPermissions;
return perms;
@ -113,13 +113,15 @@ export class UserAssignedObjectPermissionTable extends Table<UserAssignedObjectP
row(item: UserAssignedObjectPermission): TemplateResult[] {
const baseRow = [html` <a href="#/identity/users/${item.pk}"> ${item.username} </a> `];
this.modelPermissions?.results.forEach((perm) => {
let cell = html`X`;
let cell = html`<i class="fas fa-times pf-m-danger"></i>`;
if (item.permissions.filter((uperm) => uperm.codename === perm.codename).length > 0) {
cell = html`<pf-tooltip position="top" content=${msg("Directly assigned")}
>✓</pf-tooltip
>`;
><i class="fas fa-check pf-m-success"></i
></pf-tooltip>`;
} else if (item.isSuperuser) {
cell = html`<pf-tooltip position="top" content=${msg("Superuser")}>✓</pf-tooltip>`;
cell = html`<pf-tooltip position="top" content=${msg("Superuser")}
><i class="fas fa-check pf-m-success"></i
></pf-tooltip>`;
}
baseRow.push(cell);
});

View File

@ -131,7 +131,7 @@ export abstract class Table<T> extends AKElement implements TableLike {
order?: string;
@property({ type: String })
search: string = getURLParam("search", "");
search: string = "";
@property({ type: Boolean })
checkbox = false;
@ -198,6 +198,9 @@ export abstract class Table<T> extends AKElement implements TableLike {
this.selectedElements = [];
}
});
if (this.searchEnabled()) {
this.search = getURLParam("search", "");
}
}
public groupBy(items: T[]): [string, T[]][] {