Skip to content

Commit

Permalink
feat: support for user linked project permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
tomwwinter committed May 21, 2024
1 parent 35ec4e6 commit 81361ee
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 8 deletions.
25 changes: 18 additions & 7 deletions src/app/core/permissions/ability/ability.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { LoggingService } from "../../logging/logging.service";
import { get } from "lodash-es";
import { LatestEntityLoader } from "../../entity/latest-entity-loader";
import { SessionInfo, SessionSubject } from "../../session/auth/session-info";
import { User } from "../../user/user";

/**
* This service sets up the `EntityAbility` injectable with the JSON defined rules for the currently logged in user.
Expand Down Expand Up @@ -41,10 +42,10 @@ export class AbilityService extends LatestEntityLoader<Config<DatabaseRules>> {
);
}

private updateAbilityWithUserRules(rules: DatabaseRules): Promise<any> {
private async updateAbilityWithUserRules(rules: DatabaseRules): Promise<any> {
// If rules object is empty, everything is allowed
const userRules: DatabaseRule[] = rules
? this.getRulesForUser(rules)
? await this.getRulesForUser(rules)
: [{ action: "manage", subject: "all" }];

if (userRules.length === 0) {
Expand All @@ -58,7 +59,7 @@ export class AbilityService extends LatestEntityLoader<Config<DatabaseRules>> {
return this.permissionEnforcer.enforcePermissionsOnLocalData(userRules);
}

private getRulesForUser(rules: DatabaseRules): DatabaseRule[] {
private async getRulesForUser(rules: DatabaseRules): Promise<DatabaseRule[]> {
const sessionInfo = this.sessionInfo.value;
if (!sessionInfo) {
return rules.public ?? [];
Expand All @@ -74,10 +75,20 @@ export class AbilityService extends LatestEntityLoader<Config<DatabaseRules>> {
return this.interpolateUser(rawUserRules, sessionInfo);
}

private interpolateUser(
private async interpolateUser(
rules: DatabaseRule[],
user: SessionInfo,
): DatabaseRule[] {
sessionInfo: SessionInfo,
): Promise<DatabaseRule[]> {
const user = await this.entityMapper
.load(User, sessionInfo.entityId)
.catch(() => {});

if (user && user["projects"]) {
sessionInfo.projects = user["projects"];
} else {
sessionInfo.projects = [];
}

return JSON.parse(JSON.stringify(rules), (_that, rawValue) => {
if (rawValue[0] !== "$") {
return rawValue;
Expand All @@ -89,7 +100,7 @@ export class AbilityService extends LatestEntityLoader<Config<DatabaseRules>> {
// mapping the previously valid ${user.name} here for backwards compatibility
name = "user.entityId";
}
const value = get({ user }, name);
const value = get({ user: sessionInfo }, name);

if (typeof value === "undefined") {
throw new ReferenceError(`Variable ${name} is not defined`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ export class PermissionEnforcerService {
private configService: ConfigService,
) {}

async enforcePermissionsOnLocalData(userRules: DatabaseRule[]) {
async enforcePermissionsOnLocalData(
userRules: DatabaseRule[],
): Promise<void> {
const userRulesString = JSON.stringify(userRules);
if (!this.sessionInfo.value || !this.userRulesChanged(userRulesString)) {
return;
Expand Down
5 changes: 5 additions & 0 deletions src/app/core/session/auth/session-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ export interface SessionInfo {
*/
roles: string[];

/**
* List of linked projects
*/
projects?: string[];

/**
* ID of the entity which is connected with the user account.
*
Expand Down

0 comments on commit 81361ee

Please sign in to comment.