Skip to content

Commit

Permalink
permission: create,get,put,delete,destroy
Browse files Browse the repository at this point in the history
fixes #20
  • Loading branch information
msimerson committed Feb 29, 2024
1 parent 3a58c74 commit ca37ebc
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 94 deletions.
7 changes: 4 additions & 3 deletions lib/mysql.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class Mysql {
}

whereConditions(query, params) {
let newQuery = query
let paramsArray = []

if (Array.isArray(params)) {
Expand All @@ -81,13 +82,13 @@ class Mysql {
// Object to WHERE conditions
let first = true
for (const p in params) {
if (!first) query += ' AND'
query += ` ${p}=?`
if (!first) newQuery += ' AND'
newQuery += ` ${p}=?`
paramsArray.push(params[p])
first = false
}
}
return [query, paramsArray]
return [newQuery, paramsArray]
}

async delete(query, params) {
Expand Down
206 changes: 153 additions & 53 deletions lib/permission.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,64 +9,56 @@ const permDbMap = {
name: 'perm_name',
}

const boolFields = [
'group_create',
'group_delete',
'group_write',
'nameserver_create',
'nameserver_delete',
'nameserver_write',
'self_write',
'user_create',
'user_delete',
'user_write',
'zone_create',
'zone_delegate',
'zone_delete',
'zone_write',
'zonerecord_create',
'zonerecord_delegate',
'zonerecord_delete',
'zonerecord_write',
'inherit',
'deleted',
]

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

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

return await Mysql.insert(
`INSERT INTO nt_perm`,
mapToDbColumn(args, permDbMap),
mapToDbColumn(objectToDb(args), permDbMap),
)
}

async get(args) {
const rows = await Mysql.select(
`SELECT nt_perm_id AS id
, nt_user_id AS uid
, nt_group_id AS gid
, inherit_perm AS inherit
, perm_name AS name
const query = `SELECT p.nt_perm_id AS id
, p.nt_user_id AS uid
, p.nt_group_id AS gid
, p.inherit_perm AS inherit
, p.perm_name AS name
${getPermFields()}
, deleted
FROM nt_perm WHERE`,
mapToDbColumn(args, permDbMap),
)
for (const r of rows) {
for (const b of boolFields) {
r[b] = r[b] === 1
}
, p.deleted
FROM nt_perm p WHERE`
// Mysql.debug(1)
const rows = await Mysql.select(query, mapToDbColumn(args, permDbMap))
if (rows.length === 0) return
if (rows.length > 1) {
throw new Error(`permissions.get found ${rows.length} rows for uid ${args.uid}`)

Check warning on line 42 in lib/permission.js

View check run for this annotation

Codecov / codecov/patch

lib/permission.js#L42

Added line #L42 was not covered by tests
}
return rows
return dbToObject(rows[0])
}

async getGroup(args) {
const query = `SELECT p.nt_perm_id AS id
, p.nt_user_id AS uid
, p.nt_group_id AS gid
, p.inherit_perm AS inherit
, p.perm_name AS name
${getPermFields()}
, p.deleted
FROM nt_perm p
INNER JOIN nt_user u ON p.nt_group_id = u.nt_group_id
WHERE p.deleted=0
AND u.deleted=0
AND u.nt_user_id=?`;
const rows = await Mysql.select(query, [ args.uid ])
return dbToObject(rows[0])
}

async put(args) {
Expand All @@ -83,31 +75,30 @@ class Permission {
}

async delete(args, val) {
const g = await this.get(args)
if (g.length !== 1) return false
const p = await this.get(args)
if (!p) return false
await Mysql.execute(`UPDATE nt_perm SET deleted=? WHERE nt_perm_id=?`, [
val ?? 1,
g[0].id,
args.id,
])
return true
}

async destroy(args) {
const g = await this.get(args)
if (g.length === 1) {
await Mysql.delete(
`DELETE FROM nt_perm WHERE`,
mapToDbColumn(args, permDbMap),
)
}
const p = await this.get(args)
if (!p) return false
return await Mysql.delete(
`DELETE FROM nt_perm WHERE`,
mapToDbColumn(args, permDbMap),
)
}
}

export default new Permission()

function getPermFields() {
return (
`, nt_perm.` +
`, p.` +
[
'group_write',
'group_create',
Expand All @@ -133,6 +124,115 @@ function getPermFields() {

'self_write',
'usable_ns',
].join(`, nt_perm.`)
].join(`, p.`)
)
}

/* the following two functions convert to and from:
the SQL DB format:
{
"id": 4096,
"uid": 4096,
"gid": 4096,
"inherit": 1,
"name": "Test Permission",
"group_write": 0,
"group_create": 0,
"group_delete": 0,
"zone_write": 1,
"zone_create": 1,
"zone_delegate": 1,
"zone_delete": 1,
"zonerecord_write": 0,
"zonerecord_create": 0,
"zonerecord_delegate": 0,
"zonerecord_delete": 0,
"user_write": 0,
"user_create": 0,
"user_delete": 0,
"nameserver_write": 0,
"nameserver_create": 0,
"nameserver_delete": 0,
"self_write": 0,
"usable_ns": "",
"deleted": 0
}
JSON object format:
{
"id": 4096,
"inherit": true,
"name": "Test Permission",
"self_write": false,
"usable_ns": "",
"deleted": false,
"group": { "id": 4096, "create": false, "write": false, "delete": false },
"nameserver": { "create": false, "write": false, "delete": false },
"zone": { "create": true, "write": true, "delete": true, "delegate": true },
"zonerecord": {
"create": false,
"write": false,
"delete": false,
"delegate": false
},
"user": { "id": 4096, "create": false, "write": false, "delete": false }
}
*/

const boolFields = [
'self_write',
'inherit',
'deleted',
]

function dbToObject(row) {
const newRow = JSON.parse(JSON.stringify(row))
for (const f of ['group', 'nameserver', 'zone', 'zonerecord', 'user']) {
for (const p of ['create','write','delete','delegate']) {
if (newRow[`${f}_${p}`] !== undefined) {
if (newRow[f] === undefined) newRow[f] = {}
newRow[f][p] = newRow[`${f}_${p}`] === 1
delete newRow[`${f}_${p}`]
}
}
}
for (const b of boolFields) {
newRow[b] = newRow[b] === 1
}
if (newRow.uid !== undefined) {
newRow.user.id = newRow.uid
delete newRow.uid
}
if (newRow.gid !== undefined) {
newRow.group.id = newRow.gid
delete newRow.gid
}
return newRow
}

function objectToDb (row) {
const newRow = JSON.parse(JSON.stringify(row))
if (newRow?.user?.id !== undefined) {
newRow.uid = newRow.user.id
delete newRow.user.id
}
if (newRow?.group?.id !== undefined) {
newRow.gid = newRow.group.id
delete newRow.group.id
}
for (const f of ['group', 'nameserver', 'zone', 'zonerecord', 'user']) {
for (const p of ['create','write','delete','delegate']) {
if (newRow[f] === undefined) continue
if (newRow[f][p] === undefined) continue
newRow[`${f}_${p}`] = newRow[f][p] === true ? 1 : 0
delete newRow[f][p]
}
delete newRow[f]
}
for (const b of boolFields) {
newRow[b] = newRow[b] === true ? 1 : 0
}
return newRow
}
48 changes: 31 additions & 17 deletions lib/permission.test.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,62 @@
import assert from 'node:assert/strict'
import { describe, it, after } from 'node:test'
import { describe, it, after, before } from 'node:test'

import Permission from './permission.js'
import User from './user.js'
import permTestCase from './test/permission.json' with { type: 'json' }
import userTestCase from './test/user.json' with { type: 'json' }

before(async () => {
await User.create(userTestCase)
})

after(async () => {
Permission.mysql.disconnect()
await Permission.mysql.disconnect()
})

describe('permission', function () {
it('creates a permission', async () => {
assert.ok(await Permission.create(permTestCase))
})

it('gets permission by id', async () => {
const g = await Permission.get({ id: permTestCase.id })
assert.deepEqual(g[0], permTestCase)
it('get: by id', async () => {
assert.deepEqual(await Permission.get({ id: permTestCase.id }), permTestCase)
})

it('get: by user id', async () => {
assert.deepEqual(await Permission.get({ uid: permTestCase.user.id }), permTestCase)
})

it('gets permission by user id', async () => {
const g = await Permission.get({ uid: permTestCase.uid })
assert.deepEqual(g[0], permTestCase)
it('get: by group id', async () => {
assert.deepEqual(await Permission.get({ gid: permTestCase.group.id }), permTestCase)
})

it('gets permission by group id', async () => {
const g = await Permission.get({ uid: permTestCase.gid })
assert.deepEqual(g[0], permTestCase)
it('getGroup: gets group permissions', async () => {
assert.deepEqual(await Permission.getGroup({ uid: permTestCase.user.id }), permTestCase)
})

it('changes a permission', async () => {
assert.ok(await Permission.put({ id: permTestCase.id, name: 'Changed' }))
const perms = await Permission.get({ id: permTestCase.id })
assert.deepEqual(perms[0].name, 'Changed')
const perm = await Permission.get({ id: permTestCase.id })
assert.deepEqual(perm.name, 'Changed')
assert.ok(
await Permission.put({ id: permTestCase.id, name: 'Test Permission' }),
)
})

it('deletes a permission', async () => {
assert.ok(await Permission.delete({ id: permTestCase.id }))
let u = await Permission.get({ id: permTestCase.id })
assert.equal(u[0].deleted, true)
let p = await Permission.get({ id: permTestCase.id })
assert.equal(p.deleted, true)
await Permission.delete({ id: permTestCase.id }, 0) // restore
u = await Permission.get({ id: permTestCase.id })
assert.equal(u[0].deleted, false)
p = await Permission.get({ id: permTestCase.id })
assert.equal(p.deleted, false)
})

it('destroys a permission', async () => {
const r = await Permission.destroy({ id: permTestCase.id })
assert.equal(r.affectedRows, 1)
const p = await Permission.get({ id: permTestCase.id })
assert.equal(p, undefined)
})
})

0 comments on commit ca37ebc

Please sign in to comment.