From d3d14e5657df0e64cf6262bd4619bb7e318c6986 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Mon, 4 Mar 2024 10:40:19 -0800 Subject: [PATCH] routes/permission: added GET, POST, DELETE --- CHANGELOG.md | 3 +- lib/session.js | 24 ++++++ routes/group.js | 1 + routes/group.test.js | 2 +- routes/index.js | 4 +- routes/permission.js | 122 ++++++++++++++++++++++++++++ routes/permission.test.js | 154 ++++++++++++++++++++++++++++++++++++ routes/session.js | 31 +++++--- routes/session.test.js | 6 +- routes/test/permission.json | 2 +- 10 files changed, 333 insertions(+), 16 deletions(-) create mode 100644 routes/permission.js create mode 100644 routes/permission.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 321b6b2..c0417fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ ### 3.0.0-alpha.3 -- +- permission.get: default search with deleted=0 + [3.0.0-alpha.3]: https://github.com/NicTool/api/releases/tag/3.0.0-alpha.3 diff --git a/lib/session.js b/lib/session.js index 51f0366..c426e09 100644 --- a/lib/session.js +++ b/lib/session.js @@ -49,6 +49,30 @@ class Session { return sessions[0] } + async put(args) { + if (!args.id) return false + + if (args.last_access) { + const p = await this.get({ id: args.id }) + // if less than 60 seconds old, do nothing + const now = parseInt(Date.now()/1000, 10) + const oneMinuteAgo = now - 60 + // update only when +1 minute old (save DB writes) + if (p.last_access > oneMinuteAgo) return true + args.last_access = now + } + + const id = args.id + delete args.id + const r = await Mysql.update( + `UPDATE nt_user_session SET`, + `WHERE nt_user_session_id=${id}`, + mapToDbColumn(args, sessionDbMap), + ) + // console.log(r) + return r.changedRows === 1 + } + async delete(args) { const r = await Mysql.select( `DELETE FROM nt_user_session WHERE`, diff --git a/routes/group.js b/routes/group.js index ddd1ead..ffdbbaf 100644 --- a/routes/group.js +++ b/routes/group.js @@ -19,6 +19,7 @@ function GroupRoutes(server) { deleted: request.query.deleted ?? 0, id: parseInt(request.params.id, 10), }) + if (groups.length !== 1) { return h .response({ diff --git a/routes/group.test.js b/routes/group.test.js index d2668be..2f69a17 100644 --- a/routes/group.test.js +++ b/routes/group.test.js @@ -69,7 +69,7 @@ describe('group routes', () => { assert.equal(res.statusCode, 201) }) - it('GET /group', async () => { + it(`GET /group/${case2Id}`, async () => { const res = await server.inject({ method: 'GET', url: `/group/${case2Id}`, diff --git a/routes/index.js b/routes/index.js index 66abeed..9cdcc08 100644 --- a/routes/index.js +++ b/routes/index.js @@ -19,6 +19,7 @@ import pkgJson from '../package.json' with { type: 'json' } import GroupRoutes from './group.js' import { User, UserRoutes } from './user.js' import { Session, SessionRoutes } from './session.js' +import { PermissionRoutes } from './permission.js' let server @@ -61,7 +62,7 @@ async function setup() { cookie: httpCfg.cookie, validate: async (request, session) => { - const s = await Session.get({ id: session.nt_user_session_id }) + const s = await Session.get({ id: session.id }) if (!s) return { isValid: false } // invalid cookie // const account = await User.get({ id: s.nt_user_id }) @@ -82,6 +83,7 @@ async function setup() { GroupRoutes(server) UserRoutes(server) SessionRoutes(server) + PermissionRoutes(server) server.route({ method: '*', diff --git a/routes/permission.js b/routes/permission.js new file mode 100644 index 0000000..b080abe --- /dev/null +++ b/routes/permission.js @@ -0,0 +1,122 @@ +import validate from '@nictool/validate' + +import Permission from '../lib/permission.js' +import { meta } from '../lib/util.js' + +function PermissionRoutes(server) { + server.route([ + { + method: 'GET', + path: '/permission/{id}', + options: { + validate: { + // params: ??, + query: validate.permission.GET, + }, + response: { + schema: validate.permission.GET, + }, + tags: ['api'], + }, + handler: async (request, h) => { + // console.log(request.params) + + const permission = await Permission.get({ + deleted: request.query.deleted ?? 0, + id: parseInt(request.params.id, 10), + }) + + return h + .response({ + permission, + meta: { + api: meta.api, + msg: `here's your permission`, + }, + }) + .code(200) + }, + }, + { + method: 'POST', + path: '/permission', + options: { + validate: { + payload: validate.permission.POST, + }, + response: { + schema: validate.permission.GET, + }, + tags: ['api'], + }, + handler: async (request, h) => { + const pid = await Permission.create(request.payload) + if (!pid) { + console.log(`POST /permission oops`) // TODO + } + + const permission = await Permission.get({ id: pid }) + + return h + .response({ + permission, + meta: { + api: meta.api, + msg: `the permission was created`, + }, + }) + .code(201) + }, + }, + { + method: 'DELETE', + path: '/permission/{id}', + options: { + // response: { + // schema: validate.permission.GET, + // }, + tags: ['api'], + }, + handler: async (request, h) => { + + const permission = await Permission.get({ + deleted: parseInt(request.query.deleted ?? 0), + id: parseInt(request.params.id, 10), + }) + + if (!permission) { + return h + .response({ + meta: { + api: meta.api, + msg: `I couldn't find that permission`, + }, + }) + .code(404) + } + + const action = request.query.destroy === 'true' ? 'destroy' : 'delete' + // console.log(`action: ${action}`) + await Permission[action]({ + id: permission.id, + deleted: permission.deleted, + }) + delete permission.gid + + return h + .response({ + permission, + meta: { + api: meta.api, + msg: `I deleted that permission`, + }, + }) + .code(200) + }, + }, + ]) +} + +export default PermissionRoutes + +export { Permission, PermissionRoutes } \ No newline at end of file diff --git a/routes/permission.test.js b/routes/permission.test.js new file mode 100644 index 0000000..0b81794 --- /dev/null +++ b/routes/permission.test.js @@ -0,0 +1,154 @@ +import assert from 'node:assert/strict' +import { describe, it, before, after } from 'node:test' + +import { init } from './index.js' +import Group from '../lib/group.js' +import User from '../lib/user.js' +import Permission from '../lib/permission.js' + +import groupCase from './test/group.json' with { type: 'json' } +import userCase from './test/user.json' with { type: 'json' } +import permCase from './test/permission.json' with { type: 'json' } + +let server + +before(async () => { + server = await init() + await Group.create(groupCase) + await User.create(userCase) + await Permission.create(permCase) +}) + +after(async () => { + await server.stop() +}) + +describe('permission routes', () => { + let sessionCookie + + it('POST /session establishes a session', async () => { + const res = await server.inject({ + method: 'POST', + url: '/session', + payload: { + username: `${userCase.username}@${groupCase.name}`, + password: userCase.password, + }, + }) + assert.ok(res.headers['set-cookie'][0]) + sessionCookie = res.headers['set-cookie'][0].split(';')[0] + }) + + it(`GET /permission/${userCase.id}`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/permission/${userCase.id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + assert.equal(res.result.permission.zone.create, true) + assert.equal(res.result.permission.nameserver.create, false) + }) + + let case2Id = 4094 + + it('POST /permission', async () => { + const testCase = JSON.parse(JSON.stringify(permCase)) + testCase.id = case2Id // make it unique + testCase.uid = case2Id + testCase.gid = case2Id + testCase.name = `Route Test Permission 2` + delete testCase.deleted + // console.log(testCase) + + const res = await server.inject({ + method: 'POST', + url: '/permission', + headers: { + Cookie: sessionCookie, + }, + payload: testCase, + }) + // console.log(res.result) + assert.equal(res.statusCode, 201) + assert.equal(res.result.permission.zone.create, true) + assert.equal(res.result.permission.nameserver.create, false) + }) + + it(`GET /permission/${case2Id}`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/permission/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + assert.equal(res.result.permission.zone.create, true) + assert.equal(res.result.permission.nameserver.create, false) + }) + + it(`DELETE /permission/${case2Id}`, async () => { + const res = await server.inject({ + method: 'DELETE', + url: `/permission/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + }) + + it(`GET /permission/${case2Id}`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/permission/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + // assert.equal(res.statusCode, 200) + assert.equal(res.result.permission, undefined) + }) + + it(`GET /permission/${case2Id} (deleted)`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/permission/${case2Id}?deleted=1`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + }) + + it(`DELETE /permission/${case2Id}`, async () => { + const res = await server.inject({ + method: 'DELETE', + url: `/permission/${case2Id}?deleted=1&destroy=true`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + }) + + it('DELETE /session', async () => { + const res = await server.inject({ + method: 'DELETE', + url: '/session', + headers: { + Cookie: sessionCookie, + }, + }) + assert.equal(res.statusCode, 200) + }) +}) diff --git a/routes/session.js b/routes/session.js index 6030a8f..46e1abd 100644 --- a/routes/session.js +++ b/routes/session.js @@ -3,6 +3,7 @@ import validate from '@nictool/validate' import Group from '../lib/group.js' import User from '../lib/user.js' import Session from '../lib/session.js' +import Permission from '../lib/permission.js' import { meta } from '../lib/util.js' function SessionRoutes(server) { @@ -17,15 +18,22 @@ function SessionRoutes(server) { tags: ['api'], }, handler: async (request, h) => { - const { nt_user_id, nt_user_session_id } = request.state['sid-nictool'] - const users = await User.get({ id: nt_user_id }) - const groups = await Group.get({ id: users[0].gid }) - delete users[0].gid + const { user, group, session } = request.state['sid-nictool'] + + // const users = await User.get({ id: user.id }) + // const groups = await Group.get({ id: users[0].gid }) + // delete users[0].gid + + // const userPerm = await Permission.get({ uid: user.id }) + // const groupPerm = await Permission.getGroup({ uid: user.id }) + + Session.put({ id: session.id, last_access: true }) + return h .response({ - user: users[0], - group: groups[0], - session: { id: nt_user_session_id }, + user: user, + group: group, + session: { id: session.id }, meta: { api: meta.api, msg: `working on it`, @@ -54,14 +62,15 @@ function SessionRoutes(server) { } const sessId = await Session.create({ - nt_user_id: account.user.id, - nt_user_session: '3.0.0', + uid: account.user.id, + session: '3.0.0', last_access: parseInt(Date.now() / 1000, 10), }) request.cookieAuth.set({ - nt_user_id: account.user.id, - nt_user_session_id: sessId, + user: account.user, + group: account.group, + session: { id: sessId }, }) return h diff --git a/routes/session.test.js b/routes/session.test.js index 311ec69..1034b3c 100644 --- a/routes/session.test.js +++ b/routes/session.test.js @@ -1,18 +1,22 @@ import assert from 'node:assert/strict' import { describe, it, before, after } from 'node:test' +import util from 'node:util' import { init } from './index.js' import userCase from './test/user.json' with { type: 'json' } import groupCase from './test/group.json' with { type: 'json' } +import permCase from './test/permission.json' with { type: 'json' } import User from '../lib/user.js' import Group from '../lib/group.js' +import Permission from '../lib/permission.js' let server before(async () => { await Group.create(groupCase) await User.create(userCase) + await Permission.create(permCase) server = await init() }) @@ -84,9 +88,9 @@ describe('session routes', () => { Cookie: sessionCookie, }, }) + // console.log(util.inspect(res.result, { depth: null })) assert.equal(res.request.auth.isAuthenticated, true) assert.equal(res.statusCode, 200) - // console.log(res.result) }) } }) diff --git a/routes/test/permission.json b/routes/test/permission.json index 52db656..9a5dcd1 100644 --- a/routes/test/permission.json +++ b/routes/test/permission.json @@ -21,7 +21,7 @@ "nameserver_write": false, "nameserver_create": false, "nameserver_delete": false, - "self_write": false, + "self_write": true, "usable_ns": "", "deleted": false }