Skip to content

Commit 99908d7

Browse files
authored
session management progress (#2)
- feat(session.delete): added - test(session): add lifecycle tests - config(session): ttl set to 1 hour - lib/mysql: DRY - init-mysql: added 'drop' CLI arg - ci: custom publish, b/c build test has SQL setup steps - test(user): remove duplicate setup code - test(user): add invalid user & pass tests - doc(README): added install section - better align object function names with http verbs
1 parent 7555113 commit 99908d7

21 files changed

Lines changed: 366 additions & 224 deletions

File tree

.github/workflows/ci.yml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,12 @@ jobs:
5151
node-version: ${{ fromJson(needs.get-lts.outputs.active) }}
5252
fail-fast: false
5353
steps:
54-
- name: Start MySQL
55-
run: sudo /etc/init.d/mysql start
54+
- run: sudo /etc/init.d/mysql start
5655
- uses: actions/checkout@v4
5756
- uses: actions/setup-node@v4
58-
name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
5957
with:
6058
node-version: ${{ matrix.node-version }}
61-
- name: Initialize MySQL
62-
run: sh sql/init-mysql.sh
59+
- run: sh sql/init-mysql.sh
6360
- run: npm install
6461
- run: npm test
6562

@@ -81,8 +78,7 @@ jobs:
8178
name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
8279
with:
8380
node-version: ${{ matrix.node-version }}
84-
- name: Initialize MySQL
85-
run: sh sql/init-mysql.sh
81+
- run: sh sql/init-mysql.sh
8682
- run: npm install
8783
- run: npm test
8884

@@ -101,10 +97,9 @@ jobs:
10197
choco install mysql
10298
- uses: actions/checkout@v4
10399
- uses: actions/setup-node@v4
104-
name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
100+
name: Node ${{ matrix.node-version }}
105101
with:
106102
node-version: ${{ matrix.node-version }}
107-
- name: Initialize MySQL
108-
run: sh sql/init-mysql.sh
103+
- run: sh sql/init-mysql.sh
109104
- run: npm install
110105
- run: npm test

.github/workflows/publish.yml

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,53 @@ env:
1313
CI: true
1414

1515
jobs:
16-
publish:
17-
uses: NicTool/.github/.github/workflows/publish.yml@main
18-
secrets: inherit
16+
build:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- run: sudo /etc/init.d/mysql start
20+
- uses: actions/checkout@v4
21+
- uses: actions/setup-node@v4
22+
- run: sh sql/init-mysql.sh
23+
- run: npm install
24+
- run: npm test
25+
26+
publish-npm:
27+
needs: build
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/setup-node@v4
31+
name: Node ${{ env.node-version }}
32+
with:
33+
node-version: ${{ env.node-version }}
34+
registry-url: https://registry.npmjs.org/
35+
36+
- uses: actions/checkout@v4
37+
with:
38+
fetch-depth: 0
39+
# fetch-depth 0 needed by GitHub Release
40+
41+
- name: publish to NPM
42+
run: npm publish --access=public
43+
env:
44+
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
45+
46+
- name: GitHub Release
47+
uses: justincy/github-action-npm-release@2.0.1
48+
id: release
49+
50+
publish-gpr:
51+
needs: build
52+
runs-on: ubuntu-latest
53+
permissions:
54+
contents: read
55+
packages: write
56+
steps:
57+
- uses: actions/checkout@v4
58+
- uses: actions/setup-node@v4
59+
with:
60+
node-version: ${{ env.node-version }}
61+
registry-url: https://npm.pkg.github.com/
62+
scope: '@nictool'
63+
- run: npm publish
64+
env:
65+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,34 @@
33

44
# nt-api
55

6-
nictool api
6+
nictool api v3
77

88

9+
## Install
10+
11+
1. Install [Node.js](https://nodejs.org/en/download/) on your system
12+
2. Download the NicTool v3 API
13+
14+
15+
```
16+
git clone https://github.com/NicTool/api.git nictool-api
17+
cd nictool-api
18+
npm install
19+
```
20+
21+
## Configure
22+
23+
Edit the files in conf.d to reflect your local settings. Each config file has a default section which lists all available config settings. Below the `default` section are optional deployment environments such as `production`, `development`, and `test`. When a config file is loaded, the environment variable `NODE_ENV` is checked and if defined, any overrides in the matching deployment section are applied.
24+
25+
## Start the service
26+
27+
Running one of these commands:
28+
29+
`npm run start (production)`
30+
31+
or
32+
33+
`npm run develop (development)`
34+
35+
will start up the HTTP service on the port specified in conf.d/http.yml.
36+

conf.d/mysql.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
# default settings apply to EVERY deployment
22
default:
33
host: 127.0.0.1
44
port: 3306
@@ -10,14 +10,17 @@ default:
1010
- TIMESTAMP
1111
decimalNumbers: true
1212

13+
# settings below this line override default settings
1314
production:
1415
host: mysql
1516
password: "********"
1617

18+
# used for CI testing (GitHub Actions workflows)
1719
test:
1820
user: root
1921
password: root
2022

23+
# used by code coverage testing
2124
cov:
2225
user: root
2326
password: root

conf.d/session.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ default:
44
# https://hapi.dev/module/cookie/api/?v=12.0.1
55
name: sid-nictool
66
password: af1b926a5e21f535c4f5b6c42941c4cf
7-
# ttl:
7+
ttl: 3600000 # 1 hour
88
# domain:
99
path: /
10-
# clearInvalid: false
10+
clearInvalid: true
1111
isSameSite: Strict
1212
isSecure: true
1313
isHttpOnly: true
1414
keepAlive: false
1515
# redirectTo:
16+
# group: NicTool
1617

1718
production:
1819
cookie:
@@ -27,4 +28,4 @@ test:
2728
development:
2829
cookie:
2930
isSecure: false
30-
password: ^NicTool.Is,The#Best_Dns-Manager$
31+
password: ^NicTool.Is,The#Best_Dns-Manager$

lib/group.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ class Group {
66
constructor() {}
77

88
async create(args) {
9-
// console.log(`create`)
109
const { error } = validate.group.validate(args)
1110
if (error) console.error(error)
1211

13-
const g = await this.read({ nt_group_id: args.nt_group_id })
12+
const g = await this.get({ nt_group_id: args.nt_group_id })
1413
if (g.length) {
1514
// console.log(g)
1615
return g[0].nt_group_id
@@ -20,12 +19,12 @@ class Group {
2019
return groupId
2120
}
2221

23-
async read(args) {
22+
async get(args) {
2423
return await mysql.select(`SELECT * FROM nt_group WHERE`, args)
2524
}
2625

2726
async destroy(args) {
28-
const g = await this.read({ nt_group_id: args.nt_group_id })
27+
const g = await this.get({ nt_group_id: args.nt_group_id })
2928
// console.log(g)
3029
if (g.length === 1) {
3130
await mysql.execute(`DELETE FROM nt_group WHERE nt_group_id=?`, [

lib/mysql.js

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,24 @@ class MySQL {
1414
// if (this.dbh && this.dbh?.connection?.connectionId) return this.dbh;
1515

1616
const cfg = await config.get('mysql')
17-
if (config.debug) console.log(cfg)
17+
if (this._debug) console.log(cfg)
1818

1919
this.dbh = await mysql.createConnection(cfg)
20-
if (config.debug)
20+
if (this._debug)
2121
console.log(`MySQL connection id ${this.dbh.connection.connectionId}`)
2222
return this.dbh
2323
}
2424

2525
async execute(query, paramsArray) {
2626
if (!this.dbh || this.dbh?.connection?._closing) {
27-
if (config.debug) console.log(`(re)connecting to MySQL`)
27+
if (this._debug) console.log(`(re)connecting to MySQL`)
2828
this.dbh = await this.connect()
2929
}
3030

31-
// console.log(query)
32-
// console.log(paramsArray)
31+
if (this._debug) console.log(query)
32+
if (this._debug) console.log(paramsArray)
3333
const [rows, fields] = await this.dbh.execute(query, paramsArray)
34-
if (this.debug()) {
34+
if (this._debug) {
3535
if (fields) console.log(fields)
3636
console.log(rows)
3737
}
@@ -42,30 +42,11 @@ class MySQL {
4242
}
4343

4444
async insert(query, params = {}) {
45-
if (!this.dbh || this.dbh?.connection?._closing) {
46-
if (config.debug) console.log(`(re)connecting to MySQL`)
47-
this.dbh = await this.connect()
48-
}
49-
5045
query += `(${Object.keys(params).join(',')}) VALUES(${Object.keys(params).map(() => '?')})`
51-
52-
// console.log(query)
53-
// console.log(Object.values(params))
54-
const [rows, fields] = await this.dbh.execute(query, Object.values(params))
55-
if (this.debug()) {
56-
if (fields) console.log(fields)
57-
console.log(rows)
58-
}
59-
60-
return rows.insertId
46+
return await this.execute(query, Object.values(params))
6147
}
6248

6349
async select(query, params = {}) {
64-
if (!this.dbh || this.dbh?.connection?._closing) {
65-
if (config.debug) console.log(`(re)connecting to MySQL`)
66-
this.dbh = await this.connect()
67-
}
68-
6950
let paramsArray = []
7051
if (Array.isArray(params)) {
7152
paramsArray = [...params]
@@ -80,17 +61,12 @@ class MySQL {
8061
}
8162
}
8263

83-
const [rows, fields] = await this.dbh.execute(query, paramsArray)
84-
if (this.debug()) {
85-
if (fields) console.log(fields)
86-
console.log(rows)
87-
}
88-
return rows
64+
return await this.execute(query, paramsArray)
8965
}
9066

9167
async disconnect(dbh) {
9268
const d = dbh || this.dbh
93-
if (config.debug)
69+
if (this._debug)
9470
console.log(`MySQL connection id ${d.connection.connectionId}`)
9571
await d.end()
9672
}

lib/session.js

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,42 @@ class Session {
44
constructor() {}
55

66
async create(args) {
7-
const r = await this.read({ nt_user_session: args.nt_user_session })
8-
if (r) return r
7+
const r = await this.get(args)
8+
if (r) return r.nt_user_session_id
99

10-
const query = `INSERT INTO nt_user_session`
11-
12-
const id = await Mysql.insert(query, {
10+
const id = await Mysql.insert(`INSERT INTO nt_user_session`, {
1311
nt_user_id: args.nt_user_id,
1412
nt_user_session: args.nt_user_session,
1513
last_access: parseInt(Date.now() / 1000, 10),
1614
})
17-
1815
return id
1916
}
2017

21-
async read(args) {
18+
async get(args) {
2219
let query = `SELECT s.*
2320
FROM nt_user_session s
2421
LEFT JOIN nt_user u ON s.nt_user_id = u.nt_user_id
2522
WHERE u.deleted=0`
2623

2724
const params = []
28-
if (args.id) {
29-
query += ` AND s.nt_user_session_id = ?`
30-
params.push(args.id)
31-
}
32-
if (args.nt_user_session) {
33-
query += ` AND s.nt_user_session = ?`
34-
params.push(args.nt_user_session)
25+
for (const f of ['nt_user_session_id', 'nt_user_id', 'nt_user_session']) {
26+
if (args[f] !== undefined) {
27+
query += ` AND s.${f} = ?`
28+
params.push(args[f])
29+
}
3530
}
3631

3732
const sessions = await Mysql.execute(query, params)
38-
// console.log(sessions)
3933
return sessions[0]
4034
}
35+
36+
async delete(args) {
37+
const r = await Mysql.execute(
38+
`DELETE FROM nt_user_session WHERE nt_user_session_id=?`,
39+
[args.nt_user_session_id],
40+
)
41+
return r.affectedRows === 1
42+
}
4143
}
4244

4345
module.exports = new Session()

0 commit comments

Comments
 (0)