Skip to content

Commit

Permalink
Release v3.0.0-alpha.4 (#29)
Browse files Browse the repository at this point in the history
* feat(lib/nameserver): added, with tests
* feat(routes/nameserver): added, with tests
* group: updated validate names (_res, _req)
* update validate version
  • Loading branch information
msimerson committed Mar 6, 2024
1 parent 28f979e commit ad0f021
Show file tree
Hide file tree
Showing 19 changed files with 588 additions and 90 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

### Unreleased


### [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

- routes/permission: added GET, POST, DELETE
Expand All @@ -14,3 +20,4 @@


[3.0.0-alpha.3]: https://github.com/NicTool/api/releases/tag/3.0.0-alpha.3
[3.0.0-alpha.4]: https://github.com/NicTool/api/releases/tag/3.0.0-alpha.4
143 changes: 143 additions & 0 deletions lib/nameserver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import Mysql from './mysql.js'
import { mapToDbColumn } from './util.js'

const nsDbMap = { id: 'nt_nameserver_id', gid: 'nt_group_id' }
const boolFields = ['deleted', 'export_serials']

class Nameserver {
constructor() {
this.mysql = Mysql
}

async create(args) {
if (args.id) {
const g = await this.get({ id: args.id })
if (g.length === 1) return g[0].id
}

if (args.export.type) {
args = JSON.parse(JSON.stringify(args))
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),
),
)
}

async get(args) {
if (args.name !== undefined) {
args['ns.name'] = args.name
delete args.name
}
const rows = await Mysql.execute(
...Mysql.select(
`SELECT ns.nt_nameserver_id AS id
, ns.nt_group_id AS gid
, ns.name
, ns.ttl
, ns.description
, ns.address
, ns.address6
, ns.remote_login
, ns.logdir
, ns.datadir
, ns.export_interval
, ns.export_serials
, ns.export_status
, ns.deleted
, t.name AS export_type
FROM nt_nameserver ns
JOIN nt_nameserver_export_type t ON ns.export_type_id=t.id`,
mapToDbColumn(args, nsDbMap),
),
)
for (const r of rows) {
for (const b of boolFields) {
r[b] = r[b] === 1
}
}
return dbToObject(rows)
}

async put(args) {
if (!args.id) return false
const id = args.id
delete args.id
// Mysql.debug(1)
const r = await Mysql.execute(
...Mysql.update(
`nt_nameserver`,
`nt_nameserver_id=${id}`,
mapToDbColumn(args, nsDbMap),
),
)
// console.log(r)
return r.changedRows === 1
}

async delete(args) {
await Mysql.execute(
`UPDATE nt_nameserver SET deleted=? WHERE nt_nameserver_id=?`,
[args.deleted ?? 1, args.id],
)
return true
}

async destroy(args) {
return await Mysql.execute(
...Mysql.delete(`nt_nameserver`, { nt_nameserver_id: args.id }),
)
}
}

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) {
if (row[f] === undefined) row[f] = {}
row[f][p] = row[`${f}_${p}`]
delete row[`${f}_${p}`]
}
}
}
}
return rows
}

function objectToDb(row) {
row = JSON.parse(JSON.stringify(row)) // don't mutate the original

for (const f of ['export']) {
for (const p of ['interval', 'serials', 'status']) {
if (row[f] === undefined) continue
if (row[f][p] === undefined) continue
row[`${f}_${p}`] = row[f][p]
delete row[f][p]
}
delete row[f]
}
return row
}
46 changes: 46 additions & 0 deletions lib/nameserver.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import assert from 'node:assert/strict'
import { describe, it, after, before } from 'node:test'

import Nameserver from './nameserver.js'

import testCase from './test/nameserver.json' with { type: 'json' }

before(async () => {
await Nameserver.destroy({ id: testCase.id })
await Nameserver.create(testCase)
})

after(async () => {
await 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)
})

it('gets nameserver by name', async () => {
const g = await Nameserver.get({ name: testCase.name })
assert.deepEqual(g[0], testCase)
})

it('changes a nameserver', async () => {
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 }))
})

it('deletes a nameserver', async () => {
assert.ok(await Nameserver.delete({ id: testCase.id }))
let g = await Nameserver.get({ id: testCase.id, deleted: 1 })
assert.equal(g[0]?.deleted, true)
await Nameserver.delete({ id: testCase.id, deleted: 0 }) // restore
g = await Nameserver.get({ id: testCase.id })
assert.equal(g[0].deleted, false)
})
})
19 changes: 19 additions & 0 deletions lib/test/nameserver.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"id": 4096,
"gid": 4096,
"name": "a.ns.example.com.",
"description": "",
"address": "1.2.3.4",
"address6": "2001:DB8::1",
"remote_login": "nsd",
"logdir": "/foo",
"datadir": "/bar",
"export": {
"interval": 0,
"serials": true,
"status": "last run:03-05 15:25<br>last cp :09-20 12:59",
"type": "NSD"
},
"ttl": 3600,
"deleted": false
}
11 changes: 5 additions & 6 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,15 @@ const meta = {
}

function mapToDbColumn(args, maps) {
// create an instance, so we don't mangle the original args
const newArgs = JSON.parse(JSON.stringify(args))
args = JSON.parse(JSON.stringify(args)) // don't mutate the original

for (const [key, val] of Object.entries(maps)) {
if (newArgs[key] !== undefined) {
newArgs[val] = newArgs[key]
delete newArgs[key]
if (args[key] !== undefined) {
args[val] = args[key]
delete args[key]
}
}
return newArgs
return args
}

export { setEnv, meta, mapToDbColumn }
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nictool/api",
"version": "3.0.0-alpha.3",
"version": "3.0.0-alpha.4",
"description": "NicTool API",
"main": "index.js",
"type": "module",
Expand Down Expand Up @@ -43,7 +43,7 @@
"@hapi/hoek": "^11.0.4",
"@hapi/inert": "^7.1.0",
"@hapi/vision": "^7.0.3",
"@nictool/validate": "^0.7.4",
"@nictool/validate": "^0.8.0",
"hapi-swagger": "^17.2.1",
"mysql2": "^3.9.2",
"qs": "^6.11.2",
Expand Down
20 changes: 11 additions & 9 deletions routes/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ function GroupRoutes(server) {
method: 'GET',
path: '/group/{id}',
options: {
validate: {
query: validate.group.GET_req,
},
response: {
schema: validate.group.GET,
schema: validate.group.GET_res,
},
tags: ['api'],
},
Expand Down Expand Up @@ -50,15 +53,12 @@ function GroupRoutes(server) {
payload: validate.group.POST,
},
response: {
schema: validate.group.GET,
schema: validate.group.GET_res,
},
tags: ['api'],
},
handler: async (request, h) => {
const gid = await Group.create(request.payload)
if (!gid) {
console.log(`POST /group oops`) // TODO
}

const groups = await Group.get({ id: gid })

Expand All @@ -77,13 +77,16 @@ function GroupRoutes(server) {
method: 'DELETE',
path: '/group/{id}',
options: {
validate: {
query: validate.group.DELETE,
},
response: {
schema: validate.group.GET,
schema: validate.group.GET_res,
},
tags: ['api'],
},
handler: async (request, h) => {
const groups = await Group.get(request.params)
const groups = await Group.get({ id: parseInt(request.params.id, 10) })
/* c8 ignore next 10 */
if (groups.length !== 1) {
return h
Expand All @@ -96,8 +99,7 @@ function GroupRoutes(server) {
.code(204)
}

const action = request.query.destroy === 'true' ? 'destroy' : 'delete'
await Group[action]({ id: groups[0].id })
await Group.delete({ id: groups[0].id })
delete groups[0].gid

return h
Expand Down
26 changes: 7 additions & 19 deletions routes/group.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import groupCase from './test/group.json' with { type: 'json' }
import userCase from './test/user.json' with { type: 'json' }

let server
const case2Id = 4094

before(async () => {
server = await init()
Expand All @@ -17,7 +18,8 @@ before(async () => {
})

after(async () => {
await server.stop()
await Group.destroy({ id: case2Id })
server.stop()
})

describe('group routes', () => {
Expand Down Expand Up @@ -45,11 +47,9 @@ describe('group routes', () => {
},
})
// console.log(res.result)
assert.equal(res.statusCode, 200)
assert.ok([200, 204].includes(res.statusCode))
})

const case2Id = 4094

it('POST /group', async () => {
const testCase = JSON.parse(JSON.stringify(groupCase))
testCase.id = case2Id // make it unique
Expand Down Expand Up @@ -78,7 +78,7 @@ describe('group routes', () => {
},
})
// console.log(res.result)
assert.equal(res.statusCode, 200)
assert.ok([200, 204].includes(res.statusCode))
})

it(`DELETE /group/${case2Id}`, async () => {
Expand Down Expand Up @@ -108,25 +108,13 @@ describe('group routes', () => {
it(`GET /group/${case2Id} (deleted)`, async () => {
const res = await server.inject({
method: 'GET',
url: `/group/${case2Id}?deleted=1`,
url: `/group/${case2Id}?deleted=true`,
headers: {
Cookie: sessionCookie,
},
})
// console.log(res.result)
assert.equal(res.statusCode, 200)
})

it(`DELETE /group/${case2Id}`, async () => {
const res = await server.inject({
method: 'DELETE',
url: `/group/${case2Id}?destroy=true`,
headers: {
Cookie: sessionCookie,
},
})
// console.log(res.result)
assert.equal(res.statusCode, 200)
assert.ok([200, 204].includes(res.statusCode))
})

it('DELETE /session', async () => {
Expand Down
Loading

0 comments on commit ad0f021

Please sign in to comment.