Skip to content
This repository has been archived by the owner on Sep 12, 2023. It is now read-only.

Commit

Permalink
intrn(policy): allow setting permission combinations that can bypass
Browse files Browse the repository at this point in the history
  • Loading branch information
KennethTrecy committed Sep 11, 2022
1 parent bbc20dc commit 667b350
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 10 deletions.
10 changes: 5 additions & 5 deletions server/policies/belongs_to_current_user.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ describe("Policy: Belongs to current user", () => {
const otherUser = await userFactory.attach(adminRole).serializedOne(true)
const pageGuard = new BelongsToCurrentUserPolicy(UserManager, {
"bypassNecessarilyWith": {
"group": permissions,
"combinations": [
[ "readDepartmentScope" ]
]
],
"group": permissions
}
})
requester.customizeRequest({
Expand All @@ -64,12 +64,12 @@ describe("Policy: Belongs to current user", () => {
const role = await new RoleFactory().userFlags(permissions.generateMask("view")).insertOne()
const user = await userFactory.attach(role).serializedOne(true)
const otherUser = await userFactory.serializedOne(true)
const pageGuard = new BelongsToCurrentUserPolicy(UserManager,, {
const pageGuard = new BelongsToCurrentUserPolicy(UserManager, {
"bypassNecessarilyWith": {
"group": permissions,
"combinations": [
[ "readDepartmentScope" ]
]
],
"group": permissions
}
})
requester.customizeRequest({
Expand Down
51 changes: 46 additions & 5 deletions server/policies/belongs_to_current_user.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { GeneralObject } from "$/types/general"
import type { BaseManagerClass } from "!/types/independent"
import type { AuthenticatedRequest } from "!/types/dependent"
import type { DeserializedUserProfile } from "$/types/documents/user"

import isUndefined from "$/type_guards/is_undefined"
import deserialize from "$/object/deserialize"
import PermissionGroup from "$/permissions/base"
import isUndefined from "$/type_guards/is_undefined"
import AuthorizationError from "$!/errors/authorization"
import AuthenticationBasedPolicy from "!/policies/authentication-based"

Expand All @@ -15,16 +17,41 @@ import AuthenticationBasedPolicy from "!/policies/authentication-based"
* Hint: If the resource can be processed by other users through advance permissions, do not use
* the policy.
*/
export default class extends AuthenticationBasedPolicy {
export default class <
T extends GeneralObject<number>,
U,
V extends AuthenticatedRequest = AuthenticatedRequest
> extends AuthenticationBasedPolicy {
private readonly Class: BaseManagerClass
private permissionGroup: PermissionGroup<T, U>|undefined
private permissionCombinations: U[][]|undefined
private checkOthers: (request: V) => Promise<void>

constructor(managerClass: BaseManagerClass) {
constructor(
managerClass: BaseManagerClass,
{
bypassNecessarilyWith,
checkOthers = (): Promise<void> => {
const promise = Promise.resolve()
return promise
}
}: Partial<{
bypassNecessarilyWith: {
group: PermissionGroup<T, U>,
combinations: U[][]
},
checkOthers: (request: V) => Promise<void>
}> = {}
) {
super(true)

this.Class = managerClass
this.permissionGroup = bypassNecessarilyWith?.group
this.permissionCombinations = bypassNecessarilyWith?.combinations
this.checkOthers = checkOthers
}

async authorize(request: AuthenticatedRequest): Promise<void> {
async authorize(request: V): Promise<void> {
await super.authorize(request)

if (isUndefined(request.params.id)) {
Expand All @@ -38,7 +65,21 @@ export default class extends AuthenticationBasedPolicy {
Number(user.data.id),
manager.modelChainToUser
)) {
throw new AuthorizationError("Only the owner of the resource can do the operation.")
let isPermitted = false

if (!isUndefined(this.permissionGroup) && !isUndefined(this.permissionCombinations)) {
const roles = user.data.roles.data as unknown as T[]
isPermitted = this.permissionGroup.hasOneRoleAllowed(
roles,
this.permissionCombinations
)
}

if (!isPermitted) {
throw new AuthorizationError("Only the owner of the resource can do the operation.")
}
}

await this.checkOthers(request)
}
}

0 comments on commit 667b350

Please sign in to comment.