From 5e2686712a483a6383144e8b78f27e27b53a9a4f Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Thu, 4 Jun 2026 13:22:51 +0300 Subject: [PATCH] fix: auto-qualify bare permission names in tokenHasPerms tokenHasPerms received bare resource names (e.g. 'work_order') from route perms, but _permsMatch expects 'resource:level' format. Splitting a bare name by ':' left `required` as undefined, crashing on spread. --- tests/unit/lib/auth.test.js | 28 ++++++++++++++++++++++++++++ workers/lib/auth.js | 6 +++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/tests/unit/lib/auth.test.js b/tests/unit/lib/auth.test.js index 8ed56c4..c77b573 100644 --- a/tests/unit/lib/auth.test.js +++ b/tests/unit/lib/auth.test.js @@ -348,6 +348,34 @@ test('AuthLib - tokenHasPerms with matchAll=false', async (t) => { t.pass() }) +test('AuthLib - tokenHasPerms auto-qualifies bare perm names', async (t) => { + const mockAuth = { + getTokenPerms: function () { + return { superadmin: false, perms: ['work_order:rw', 'actions:rw'] } + }, + conf: { + superAdminPerms: [] + } + } + const authLib = new AuthLib({ + httpc: {}, + httpd: {}, + userService: {}, + auth: mockAuth + }) + + const resultWrite = await authLib.tokenHasPerms('token', true, ['work_order']) + t.is(resultWrite, true, 'bare perm with write=true should resolve to work_order:rw') + + const resultRead = await authLib.tokenHasPerms('token', false, ['work_order']) + t.is(resultRead, true, 'bare perm with write=false should resolve to work_order:r') + + const resultMissing = await authLib.tokenHasPerms('token', true, ['inventory']) + t.is(resultMissing, false, 'bare perm not in user perms should return false') + + t.pass() +}) + test('AuthLib - cleanupTokens', async (t) => { let cleanupTokensCalled = false const mockAuth = { diff --git a/workers/lib/auth.js b/workers/lib/auth.js index 626efc8..aa14975 100644 --- a/workers/lib/auth.js +++ b/workers/lib/auth.js @@ -88,7 +88,11 @@ class AuthLib { return false } - const resolved = requestedPerms.map(perm => this._permsMatch(perms.permissions, perm)) + const level = write ? 'rw' : 'r' + const resolved = requestedPerms.map(perm => { + const qualified = perm.includes(':') ? perm : `${perm}:${level}` + return this._permsMatch(perms.permissions, qualified) + }) return matchAll ? resolved.every(res => res)