diff --git a/README.md b/README.md index 4556af4..4e43dd7 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,8 @@ and if we peek inside the cookie jar: We can see that our session cookie has been saved. Now we can make other requests to the API using that session cookie: -``` - curl -b nt-session -X GET http://localhost:3000/user/4096 --header "Content-Type: application/json" | json_pp +```sh +curl -b nt-session -X GET http://localhost:3000/user/4096 --header "Content-Type: application/json" | json_pp { "group" : { "id" : 4096 diff --git a/lib/test/rrs/dnskey.json b/lib/test/rrs/dnskey.json index 67689ef..c4c8511 100644 --- a/lib/test/rrs/dnskey.json +++ b/lib/test/rrs/dnskey.json @@ -1,11 +1,11 @@ { "id": 4096, "zid": 4096, - "owner": "mail.example.com.", + "owner": "example.com.", "ttl": 86400, - "type": "CERT", - "cert type": "PGP", - "key tag": 0, - "algorithm": 0, - "certificate": "hexidecimalkeystring1" + "type": "DNSKEY", + "flags": 256, + "protocol": 3, + "algorithm": 5, + "publickey": "( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b/0PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU/TpPSEDhm2SNKLijfUppn1U aNvv4w== )" } diff --git a/lib/zone_record.js b/lib/zone_record.js index 4d67e79..0cf598f 100644 --- a/lib/zone_record.js +++ b/lib/zone_record.js @@ -215,6 +215,7 @@ function unApplyMap(obj, map) { } } +// map of NicTool 2.0 fields to RR field names function getMap(rrType) { switch (rrType) { case 'CAA': @@ -236,7 +237,7 @@ function getMap(rrType) { return { address: 'target' } case 'DNSKEY': return { - address: 'public key', + address: 'publickey', weight: 'flags', priority: 'protocol', other: 'algorithm', diff --git a/routes/index.js b/routes/index.js index af0e120..79429b3 100644 --- a/routes/index.js +++ b/routes/index.js @@ -21,6 +21,7 @@ import { User, UserRoutes } from './user.js' import { Session, SessionRoutes } from './session.js' import { PermissionRoutes } from './permission.js' import { NameserverRoutes } from './nameserver.js' +import { ZoneRoutes } from './zone.js' let server @@ -86,6 +87,7 @@ async function setup() { SessionRoutes(server) PermissionRoutes(server) NameserverRoutes(server) + ZoneRoutes(server) server.route({ method: '*', diff --git a/routes/test/zone.json b/routes/test/zone.json new file mode 100644 index 0000000..951b5d2 --- /dev/null +++ b/routes/test/zone.json @@ -0,0 +1,15 @@ +{ + "id": 4095, + "gid": 4095, + "zone": "route.example.com", + "mailaddr": "route-master.example.com.", + "description": "route test", + "serial": 20240306, + "refresh": 2, + "retry": 3, + "expire": 4, + "minimum": 5, + "ttl": 3601, + "location": "", + "last_publish": null +} \ No newline at end of file diff --git a/routes/user.test.js b/routes/user.test.js index 1602921..3e08484 100644 --- a/routes/user.test.js +++ b/routes/user.test.js @@ -107,7 +107,7 @@ describe('user routes', () => { assert.equal(res.statusCode, 200) }) - it(`GET /user/${userId2}`, async () => { + it(`GET /user/${userId2} (deleted)`, async () => { const res = await server.inject({ method: 'GET', url: `/user/${userId2}`, diff --git a/routes/zone.js b/routes/zone.js new file mode 100644 index 0000000..340e944 --- /dev/null +++ b/routes/zone.js @@ -0,0 +1,117 @@ +import validate from '@nictool/validate' + +import Zone from '../lib/zone.js' +import { meta } from '../lib/util.js' + +function ZoneRoutes(server) { + server.route([ + { + method: 'GET', + path: '/zone/{id}', + options: { + validate: { + query: validate.zone.GET_req, + }, + response: { + schema: validate.zone.GET_res, + }, + tags: ['api'], + }, + handler: async (request, h) => { + const getArgs = { + deleted: request.query.deleted === true ? 1 : 0, + id: parseInt(request.params.id, 10), + } + + const zones = await Zone.get(getArgs) + + return h + .response({ + zone: zones[0], + meta: { + api: meta.api, + msg: `here's your zone`, + }, + }) + .code(200) + }, + }, + { + method: 'POST', + path: '/zone', + options: { + validate: { + payload: validate.zone.POST, + }, + response: { + schema: validate.zone.GET_res, + }, + tags: ['api'], + }, + handler: async (request, h) => { + const id = await Zone.create(request.payload) + + const zones = await Zone.get({ id }) + + return h + .response({ + zone: zones[0], + meta: { + api: meta.api, + msg: `the zone was created`, + }, + }) + .code(201) + }, + }, + { + method: 'DELETE', + path: '/zone/{id}', + options: { + validate: { + query: validate.zone.DELETE, + }, + response: { + schema: validate.zone.GET_res, + }, + tags: ['api'], + }, + handler: async (request, h) => { + const zones = await Zone.get({ + deleted: request.query.deleted === true ? 1 : 0, + id: parseInt(request.params.id, 10), + }) + + if (zones.length === 0) { + return h + .response({ + meta: { + api: meta.api, + msg: `I couldn't find that zone`, + }, + }) + .code(404) + } + + await Zone.delete({ + id: zones[0].id, + deleted: 1, + }) + + return h + .response({ + zone: zones[0], + meta: { + api: meta.api, + msg: `I deleted that zone`, + }, + }) + .code(200) + }, + }, + ]) +} + +export default ZoneRoutes + +export { Zone, ZoneRoutes } diff --git a/routes/zone.test.js b/routes/zone.test.js new file mode 100644 index 0000000..ab0a80b --- /dev/null +++ b/routes/zone.test.js @@ -0,0 +1,150 @@ +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 Zone from '../lib/zone.js' + +import groupCase from './test/group.json' with { type: 'json' } +import userCase from './test/user.json' with { type: 'json' } +import nsCase from './test/zone.json' with { type: 'json' } + +let server +let case2Id = 4094 + +before(async () => { + await Zone.destroy({ id: case2Id }) + await Group.create(groupCase) + await User.create(userCase) + await Zone.create(nsCase) + server = await init() +}) + +after(async () => { + // await Zone.destroy({ id: case2Id }) + server.stop() +}) + +describe('zone 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 /zone/${nsCase.id}`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/zone/${nsCase.id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + assert.equal(res.result.zone.name, nsCase.name) + }) + + it(`POST /zone (${case2Id})`, async () => { + const testCase = JSON.parse(JSON.stringify(nsCase)) + testCase.id = case2Id // make it unique + testCase.gid = case2Id + testCase.zone = 'route2.example.com.' + + const res = await server.inject({ + method: 'POST', + url: '/zone', + headers: { + Cookie: sessionCookie, + }, + payload: testCase, + }) + // console.log(res.result) + assert.equal(res.statusCode, 201) + assert.ok(res.result.zone.gid) + }) + + it(`GET /zone/${case2Id}`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/zone/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + assert.ok(res.result.zone.gid) + }) + + it(`DELETE /zone/${case2Id}`, async () => { + const res = await server.inject({ + method: 'DELETE', + url: `/zone/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + }) + + it(`DELETE /zone/${case2Id}`, async () => { + const res = await server.inject({ + method: 'DELETE', + url: `/zone/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 404) + }) + + it(`GET /zone/${case2Id}`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/zone/${case2Id}`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + // assert.equal(res.statusCode, 200) + assert.equal(res.result.zone, undefined) + }) + + it(`GET /zone/${case2Id} (deleted)`, async () => { + const res = await server.inject({ + method: 'GET', + url: `/zone/${case2Id}?deleted=true`, + headers: { + Cookie: sessionCookie, + }, + }) + // console.log(res.result) + assert.equal(res.statusCode, 200) + assert.equal(res?.result?.zone, undefined) + }) + + it('DELETE /session', async () => { + const res = await server.inject({ + method: 'DELETE', + url: '/session', + headers: { + Cookie: sessionCookie, + }, + }) + assert.equal(res.statusCode, 200) + }) +}) diff --git a/test.js b/test-fixtures.js similarity index 100% rename from test.js rename to test-fixtures.js diff --git a/test.sh b/test.sh index 1feccad..3bad8fe 100755 --- a/test.sh +++ b/test.sh @@ -3,12 +3,12 @@ set -eu NODE="node --no-warnings=ExperimentalWarning" -$NODE test.js teardown -$NODE test.js setup +$NODE test-fixtures.js teardown +$NODE test-fixtures.js setup cleanup() { echo "cleaning DB objects" - $NODE test.js teardown + $NODE test-fixtures.js teardown } trap cleanup EXIT 1 2 3 6 @@ -20,7 +20,7 @@ else # npm i --no-save node-test-github-reporter # $NODE --test --test-reporter=node-test-github-reporter # else - $NODE --test --test-reporter=spec + $NODE --test --test-reporter=spec lib/*.test.js routes/*.test.js # fi fi