diff --git a/CHANGELOG.md b/CHANGELOG.md index a04a9bb..87125d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ ### [3.0.0-alpha.4] - 2024-03-05 - feat(lib/nameserver): added, with tests - +- feat(routes/nameserver): added, with tests ### 3.0.0-alpha.3 diff --git a/lib/nameserver.js b/lib/nameserver.js index 682a044..2caa674 100644 --- a/lib/nameserver.js +++ b/lib/nameserver.js @@ -16,13 +16,20 @@ class Nameserver { } if (args.export.type) { - const rows = await Mysql.execute(...Mysql.select('SELECT id FROM nt_nameserver_export_type', { name: args.export.type })) + const rows = await Mysql.execute( + ...Mysql.select('SELECT id FROM nt_nameserver_export_type', { + name: args.export.type, + }), + ) args.export_type_id = rows[0].id delete args.export.type } return await Mysql.execute( - ...Mysql.insert(`nt_nameserver`, mapToDbColumn(objectToDb(args), nsDbMap)), + ...Mysql.insert( + `nt_nameserver`, + mapToDbColumn(objectToDb(args), nsDbMap), + ), ) } @@ -78,10 +85,10 @@ class Nameserver { } async delete(args) { - await Mysql.execute(`UPDATE nt_nameserver SET deleted=? WHERE nt_nameserver_id=?`, [ - args.deleted ?? 1, - args.id, - ]) + await Mysql.execute( + `UPDATE nt_nameserver SET deleted=? WHERE nt_nameserver_id=?`, + [args.deleted ?? 1, args.id], + ) return true } @@ -94,9 +101,11 @@ class Nameserver { export default new Nameserver() - function dbToObject(rows) { for (const row of rows) { + for (const f of ['description', 'address6', 'remote_login', 'datadir', 'logdir', 'export_status']) { + if ([undefined, null].includes(row[f])) row[f] = '' + } for (const f of ['export']) { for (const p of ['type', 'interval', 'serials', 'status']) { if (row[`${f}_${p}`] !== undefined) { diff --git a/lib/nameserver.test.js b/lib/nameserver.test.js index 8e91b1e..eea61ac 100644 --- a/lib/nameserver.test.js +++ b/lib/nameserver.test.js @@ -10,12 +10,11 @@ before(async () => { }) after(async () => { - // Nameserver.destroy({ id: testCase.id }) + Nameserver.destroy({ id: testCase.id }) Nameserver.mysql.disconnect() }) describe('nameserver', function () { - it('gets nameserver by id', async () => { const g = await Nameserver.get({ id: testCase.id }) assert.deepEqual(g[0], testCase) @@ -27,7 +26,9 @@ describe('nameserver', function () { }) it('changes a nameserver', async () => { - assert.ok(await Nameserver.put({ id: testCase.id, name: 'b.ns.example.com.' })) + assert.ok( + await Nameserver.put({ id: testCase.id, name: 'b.ns.example.com.' }), + ) const ns = await Nameserver.get({ id: testCase.id }) assert.deepEqual(ns[0].name, 'b.ns.example.com.') assert.ok(await Nameserver.put({ id: testCase.id, name: testCase.name })) diff --git a/routes/index.js b/routes/index.js index 9cdcc08..af0e120 100644 --- a/routes/index.js +++ b/routes/index.js @@ -20,6 +20,7 @@ import GroupRoutes from './group.js' import { User, UserRoutes } from './user.js' import { Session, SessionRoutes } from './session.js' import { PermissionRoutes } from './permission.js' +import { NameserverRoutes } from './nameserver.js' let server @@ -84,6 +85,7 @@ async function setup() { UserRoutes(server) SessionRoutes(server) PermissionRoutes(server) + NameserverRoutes(server) server.route({ method: '*', diff --git a/routes/nameserver.js b/routes/nameserver.js new file mode 100644 index 0000000..fe306a2 --- /dev/null +++ b/routes/nameserver.js @@ -0,0 +1,117 @@ +import validate from '@nictool/validate' + +import Nameserver from '../lib/nameserver.js' +import { meta } from '../lib/util.js' + +function NameserverRoutes(server) { + server.route([ + { + method: 'GET', + path: '/nameserver/{id}', + options: { + validate: { + query: validate.nameserver.v3, + }, + response: { + schema: validate.nameserver.GET, + }, + tags: ['api'], + }, + handler: async (request, h) => { + const getArgs = { + deleted: request.query.deleted === true ? 1 : 0, + id: parseInt(request.params.id, 10), + } + + const nameservers = await Nameserver.get(getArgs) + + return h + .response({ + nameserver: nameservers[0], + meta: { + api: meta.api, + msg: `here's your nameserver`, + }, + }) + .code(200) + }, + }, + { + method: 'POST', + path: '/nameserver', + options: { + validate: { + payload: validate.nameserver.POST, + }, + response: { + schema: validate.nameserver.GET, + }, + tags: ['api'], + }, + handler: async (request, h) => { + const id = await Nameserver.create(request.payload) + + const nameservers = await Nameserver.get({ id }) + + return h + .response({ + nameserver: nameservers[0], + meta: { + api: meta.api, + msg: `the nameserver was created`, + }, + }) + .code(201) + }, + }, + { + method: 'DELETE', + path: '/nameserver/{id}', + options: { + validate: { + query: validate.nameserver.DELETE, + }, + response: { + schema: validate.nameserver.GET, + }, + tags: ['api'], + }, + handler: async (request, h) => { + const nameservers = await Nameserver.get({ + deleted: request.query.deleted === true ? 1 : 0, + id: parseInt(request.params.id, 10), + }) + + if (!nameservers) { + return h + .response({ + meta: { + api: meta.api, + msg: `I couldn't find that nameserver`, + }, + }) + .code(404) + } + + await Nameserver.delete({ + id: nameservers[0].id, + deleted: 1, + }) + + return h + .response({ + nameserver: nameservers[0], + meta: { + api: meta.api, + msg: `I deleted that nameserver`, + }, + }) + .code(200) + }, + }, + ]) +} + +export default NameserverRoutes + +export { Nameserver, NameserverRoutes } diff --git a/routes/nameserver.test.js b/routes/nameserver.test.js new file mode 100644 index 0000000..34c38ce --- /dev/null +++ b/routes/nameserver.test.js @@ -0,0 +1,138 @@ +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 Nameserver from '../lib/nameserver.js' + +import groupCase from './test/group.json' with { type: 'json' } +import userCase from './test/user.json' with { type: 'json' } +import nsCase from './test/nameserver.json' with { type: 'json' } + +let server +let case2Id = 4094 + +before(async () => { + await Nameserver.destroy({ id: case2Id }) + await Group.create(groupCase) + await User.create(userCase) + await Nameserver.create(nsCase) + server = await init() +}) + + +after(async () => { + await server.stop() +}) + +describe('nameserver 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 /nameserver/${nsCase.id}`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/nameserver/${nsCase.id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + assert.equal(res.result.nameserver.name, nsCase.name) + }) + + it(`POST /nameserver (${case2Id})`, async () => { + const testCase = JSON.parse(JSON.stringify(nsCase)) + testCase.id = case2Id // make it unique + testCase.gid = case2Id + testCase.name = 'c.ns.example.com.' + + const res = await server.inject({ + method: 'POST', + url: '/nameserver', + headers: { + Cookie: sessionCookie, + }, + payload: testCase, + }) + // console.log(res.result) + assert.equal(res.statusCode, 201) + assert.ok(res.result.nameserver.gid) + }) + + it(`GET /nameserver/${case2Id}`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/nameserver/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + assert.ok(res.result.nameserver.gid) + }) + + it(`DELETE /nameserver/${case2Id}`, async () => { + const res = await server.inject({ + method: 'DELETE', + url: `/nameserver/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + }) + + it(`GET /nameserver/${case2Id}`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/nameserver/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + // assert.equal(res.statusCode, 200) + assert.equal(res.result.nameserver, undefined) + }) + + it(`GET /nameserver/${case2Id} (deleted)`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/nameserver/${case2Id}?deleted=true`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + assert.ok(res.result.nameserver) + }) + + 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/test/nameserver.json b/routes/test/nameserver.json new file mode 100644 index 0000000..ee6237d --- /dev/null +++ b/routes/test/nameserver.json @@ -0,0 +1,19 @@ +{ + "id": 4095, + "gid": 4095, + "name": "b.ns.example.com.", + "description": "", + "address": "2.3.4.5", + "address6": "2001:DB8::2", + "remote_login": "nsd", + "logdir": "/foo", + "datadir": "/bar", + "export": { + "interval": 0, + "serials": true, + "status": "last run:03-05 15:25
last cp :09-20 12:59", + "type": "NSD" + }, + "ttl": 3600, + "deleted": false +}