Skip to content
Merged
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
26 changes: 26 additions & 0 deletions tests/unit/handlers/work.orders.handlers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,32 @@ test('handlers: createWorkOrder Type 2 resolves part and forwards body as info',
t.is(flow.lastPush.params[0].info.partsMoves[0].role, 'diagnosis')
})

test('handlers: createWorkOrder merges info.notes, info.remarks, info.site, info.location into thing info', async (t) => {
const flow = buildSubmitFlow({ parts: [{ id: 'part-1', code: 'PSU-1', type: 'inventory-miner_part-psu', info: { serialNum: 'SN-1' } }] })
await handlers.createWorkOrder(flow.ctx, {
...userMeta(),
body: {
type: 1,
deviceType: 'psu',
deviceModel: 'PSU-WM-CB6_V5',
deviceIdentifier: 'SN-1',
info: {
notes: 'batch registration',
remarks: 'test remark',
site: 'Ivinhema',
location: 'Site Warehouse'
}
}
})
const info = flow.lastPush.params[0].info
t.is(info.notes, 'batch registration')
t.is(info.remarks, 'test remark')
t.is(info.site, 'Ivinhema')
t.is(info.location, 'Site Warehouse')
t.is(info.deviceType, 'psu', 'top-level fields still present')
t.ok(!info.info, 'no nested info.info')
})

test('handlers: createWorkOrder rejects unknown deviceType with ERR_INVALID_DEVICE_TYPE', async (t) => {
const flow = buildSubmitFlow()
await t.exception(
Expand Down
28 changes: 28 additions & 0 deletions tests/unit/lib/auth.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
6 changes: 5 additions & 1 deletion workers/lib/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 4 additions & 2 deletions workers/lib/server/handlers/work.orders.handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ async function createWorkOrder (ctx, req) {
}

const voter = req._info.user.metadata.email
const info = { ...req.body, createdBy: voter, createdAt: Date.now() }
const { info: extraInfo, ...body } = req.body
const info = { ...body, ...extraInfo, createdBy: voter, createdAt: Date.now() }

if (type === WORK_ORDER_TYPES.REGULAR) {
const part = await _resolvePartByIdentifier(ctx, deviceIdentifier)
Expand Down Expand Up @@ -73,7 +74,8 @@ async function createWorkOrder (ctx, req) {
}

async function updateWorkOrder (ctx, req) {
return submitWorkOrderAction(ctx, req, 'updateThing', { id: req.params.id, info: { ...req.body } })
const { info: extraInfo, ...body } = req.body
return submitWorkOrderAction(ctx, req, 'updateThing', { id: req.params.id, info: { ...body, ...extraInfo } })
}

async function closeWorkOrder (ctx, req) {
Expand Down
24 changes: 22 additions & 2 deletions workers/lib/server/schemas/work.orders.schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,17 @@ const create = {
deviceIdentifier: { type: 'string', minLength: 1, maxLength: 200 },
issue: { type: 'string', minLength: 1, maxLength: 2000 },
assignedTo: { type: ['string', 'null'], maxLength: 200 },
warranty
warranty,
info: {
type: 'object',
additionalProperties: false,
properties: {
notes: { type: 'string', maxLength: 4000 },
remarks: { type: 'string', maxLength: 4000 },
site: { type: 'string', maxLength: 200 },
location: { type: 'string', maxLength: 200 }
}
}
},
if: { properties: { type: { const: 2 } } },
then: { required: ['issue'] }
Expand Down Expand Up @@ -73,7 +83,17 @@ const update = {
deviceIdentifier: { type: 'string', minLength: 1, maxLength: 200 },
assignedTo: { type: ['string', 'null'], maxLength: 200 },
finalResult: { type: ['string', 'null'], maxLength: 4000 },
warranty
warranty,
info: {
type: 'object',
additionalProperties: false,
properties: {
notes: { type: 'string', maxLength: 4000 },
remarks: { type: 'string', maxLength: 4000 },
site: { type: 'string', maxLength: 200 },
location: { type: 'string', maxLength: 200 }
}
}
}
}
}
Expand Down
Loading