vestauth 0.18.0 → 0.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -1
- package/package.json +2 -4
- package/src/cli/actions/server/start.js +1 -0
- package/src/cli/commands/server.js +1 -4
- package/src/lib/helpers/dbMigrate.js +1 -1
- package/src/lib/helpers/resolvePortAndHostname.js +34 -0
- package/src/lib/helpers/serverStart.js +2 -2
- package/src/lib/helpers/subdomainBaseHost.js +18 -0
- package/src/server/index.js +38 -47
- package/src/server/models/agent.js +59 -34
- package/src/server/models/index.js +10 -20
- package/src/server/models/publicJwk.js +87 -32
- package/src/server/serializers/registerSerializer.js +20 -0
- package/src/server/services/registerService.js +49 -0
- package/src/db/migrations/.gitkeep +0 -0
- package/src/server/services/register.js +0 -13
- /package/src/{db/migrations → server/db/migration}/20260223204000_create_agents_table.js +0 -0
- /package/src/{db/migrations → server/db/migration}/20260223205500_create_public_jwks_table.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
-
[Unreleased](https://github.com/vestauth/vestauth/compare/v0.18.
|
|
5
|
+
[Unreleased](https://github.com/vestauth/vestauth/compare/v0.18.2...main)
|
|
6
|
+
|
|
7
|
+
## [0.18.2](https://github.com/vestauth/vestauth/compare/v0.18.1...v0.18.2) (2026-02-24)
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
* Pass `--hostname` ([#35](https://github.com/vestauth/vestauth/pull/35))
|
|
12
|
+
|
|
13
|
+
## [0.18.1](https://github.com/vestauth/vestauth/compare/v0.18.0...v0.18.1) (2026-02-24)
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
* Move register logic to service ([#34](https://github.com/vestauth/vestauth/pull/34))
|
|
6
18
|
|
|
7
19
|
## [0.18.0](https://github.com/vestauth/vestauth/compare/v0.17.0...v0.18.0) (2026-02-24)
|
|
8
20
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vestauth",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.2",
|
|
4
4
|
"description": "auth for agents–from the creator of dotenvx",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vestauth",
|
|
@@ -52,10 +52,8 @@
|
|
|
52
52
|
"express": "^4.21.2",
|
|
53
53
|
"knex": "^3.1.0",
|
|
54
54
|
"pg": "^8.18.0",
|
|
55
|
-
"sails-postgresql": "^5.0.1",
|
|
56
55
|
"structured-headers": "^2.0.2",
|
|
57
|
-
"undici": "7.11.0"
|
|
58
|
-
"waterline": "^0.15.2"
|
|
56
|
+
"undici": "7.11.0"
|
|
59
57
|
},
|
|
60
58
|
"devDependencies": {
|
|
61
59
|
"@yao-pkg/pkg": "^5.14.2",
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
const { Command } = require('commander')
|
|
2
2
|
const env = require('./../../lib/helpers/env')
|
|
3
3
|
const databaseUrl = require('./../../lib/helpers/databaseUrl')
|
|
4
|
-
const protocol = require('./../../lib/helpers/protocol')
|
|
5
|
-
const hostname = require('./../../lib/helpers/hostname')
|
|
6
4
|
|
|
7
5
|
const server = new Command('server')
|
|
8
6
|
|
|
@@ -15,8 +13,7 @@ const startAction = require('./../actions/server/start')
|
|
|
15
13
|
server.command('start')
|
|
16
14
|
.description('start vestauth server')
|
|
17
15
|
.option('--port <port>', 'port', env('PORT'))
|
|
18
|
-
.option('--
|
|
19
|
-
.option('--hostname <hostname>', 'localhost:3000', hostname())
|
|
16
|
+
.option('--hostname <hostname>', 'HOSTNAME', env('HOSTNAME'))
|
|
20
17
|
.option('--database-url <databaseUrl>', 'DATABASE_URL', databaseUrl())
|
|
21
18
|
.action(startAction)
|
|
22
19
|
|
|
@@ -31,7 +31,7 @@ async function dbMigrate ({ databaseUrl } = {}) {
|
|
|
31
31
|
connection,
|
|
32
32
|
ssl: { rejectUnauthorized: false },
|
|
33
33
|
migrations: {
|
|
34
|
-
directory: path.resolve(__dirname, '../../db/
|
|
34
|
+
directory: path.resolve(__dirname, '../../server/db/migration')
|
|
35
35
|
}
|
|
36
36
|
})
|
|
37
37
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
function resolvePortAndHostname ({ port, hostname } = {}) {
|
|
2
|
+
const hasPort = port !== undefined && port !== null && String(port).trim() !== ''
|
|
3
|
+
const inputPort = hasPort ? String(port).trim() : null
|
|
4
|
+
const inputHostname = typeof hostname === 'string' ? hostname.trim() : ''
|
|
5
|
+
|
|
6
|
+
if (!inputHostname) {
|
|
7
|
+
const PORT = inputPort || '3000'
|
|
8
|
+
return {
|
|
9
|
+
PORT,
|
|
10
|
+
HOSTNAME: `http://localhost:${PORT}`
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const hasScheme = /^https?:\/\//i.test(inputHostname)
|
|
15
|
+
const bareHostname = hasScheme ? new URL(inputHostname).host : inputHostname
|
|
16
|
+
const bareHostNoPort = bareHostname.split(':')[0].toLowerCase()
|
|
17
|
+
const localHostnames = new Set(['localhost', '127.0.0.1'])
|
|
18
|
+
const defaultScheme = localHostnames.has(bareHostNoPort) ? 'http' : 'https'
|
|
19
|
+
|
|
20
|
+
const url = new URL(hasScheme ? inputHostname : `${defaultScheme}://${inputHostname}`)
|
|
21
|
+
|
|
22
|
+
const PORT = inputPort || url.port || '3000'
|
|
23
|
+
|
|
24
|
+
if (!url.port && localHostnames.has(url.hostname.toLowerCase())) {
|
|
25
|
+
url.port = PORT
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
PORT,
|
|
30
|
+
HOSTNAME: url.toString().replace(/\/$/, '')
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = resolvePortAndHostname
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const serverIndex = require('./../../server/index')
|
|
2
2
|
|
|
3
|
-
function serverStart ({ port, databaseUrl }) {
|
|
4
|
-
return serverIndex.start({ port, databaseUrl })
|
|
3
|
+
function serverStart ({ port, hostname, databaseUrl }) {
|
|
4
|
+
return serverIndex.start({ port, hostname, databaseUrl })
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
module.exports = serverStart
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function subdomainBaseHost (hostname) {
|
|
2
|
+
if (!hostname) return null
|
|
3
|
+
|
|
4
|
+
const value = String(hostname).trim().toLowerCase()
|
|
5
|
+
if (!value) return null
|
|
6
|
+
|
|
7
|
+
if (value.startsWith('http://') || value.startsWith('https://')) {
|
|
8
|
+
try {
|
|
9
|
+
return new URL(value).hostname.toLowerCase()
|
|
10
|
+
} catch {
|
|
11
|
+
return null
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return value.split('/')[0].split(':')[0]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = subdomainBaseHost
|
package/src/server/index.js
CHANGED
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
const { logger } = require('./../shared/logger')
|
|
2
2
|
const tool = require('./../lib/tool')
|
|
3
|
-
const
|
|
3
|
+
const resolvePortAndHostname = require('./../lib/helpers/resolvePortAndHostname')
|
|
4
|
+
const subdomainBaseHost = require('./../lib/helpers/subdomainBaseHost')
|
|
4
5
|
const { connectOrm } = require('./models/index')
|
|
6
|
+
const RegisterService = require('./services/registerService')
|
|
7
|
+
const RegisterSerializer = require('./serializers/registerSerializer')
|
|
5
8
|
|
|
6
9
|
const express = require('express')
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
let ORM = null
|
|
11
|
+
let DB = null
|
|
10
12
|
let HTTP_SERVER = null
|
|
11
13
|
let CLOSE_PROMISE = null
|
|
12
14
|
let SIGNAL_HANDLERS_INSTALLED = false
|
|
13
15
|
let SIGNAL_HANDLERS = null
|
|
16
|
+
let PORT = null
|
|
17
|
+
let HOSTNAME = null
|
|
18
|
+
|
|
19
|
+
const app = express()
|
|
14
20
|
app.use(express.json())
|
|
15
21
|
|
|
16
22
|
app.use((req, res, next) => {
|
|
17
23
|
const hostNoPort = (req.headers.host || '').split(':')[0].toLowerCase()
|
|
24
|
+
const baseHost = subdomainBaseHost(HOSTNAME)
|
|
18
25
|
|
|
19
|
-
// agent-c235... .localhost
|
|
20
|
-
if (hostNoPort.endsWith(
|
|
21
|
-
let sub = hostNoPort.slice(0,
|
|
26
|
+
// agent-c235... .localhost or agent-c235... .example.com
|
|
27
|
+
if (baseHost && hostNoPort.endsWith(`.${baseHost}`)) {
|
|
28
|
+
let sub = hostNoPort.slice(0, -`.${baseHost}`.length) // "agent-c235..."
|
|
22
29
|
|
|
23
30
|
// remove "agent-" prefix if present
|
|
24
31
|
if (sub.startsWith('agent-')) {
|
|
@@ -44,24 +51,21 @@ app.get('/', (req, res) => {
|
|
|
44
51
|
app.post('/register', async (req, res) => {
|
|
45
52
|
try {
|
|
46
53
|
const url = `${req.protocol}://${req.get('host')}${req.originalUrl}`
|
|
47
|
-
const verified = await primitives.verify(req.method, url, req.headers, req.body.public_jwk)
|
|
48
|
-
|
|
49
|
-
const agent = await app.models.agent.create().fetch()
|
|
50
54
|
|
|
51
|
-
const
|
|
52
|
-
agent
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
const {
|
|
56
|
+
agent,
|
|
57
|
+
publicJwk,
|
|
58
|
+
isNew
|
|
59
|
+
} = await new RegisterService({
|
|
60
|
+
models: app.models,
|
|
61
|
+
httpMethod: req.method,
|
|
62
|
+
uri: url,
|
|
63
|
+
headers: req.headers,
|
|
64
|
+
publicJwk: req.body.public_jwk
|
|
65
|
+
}).run()
|
|
66
|
+
|
|
67
|
+
const json = new RegisterSerializer({ agent, publicJwk, isNew }).run()
|
|
68
|
+
res.json(json)
|
|
65
69
|
} catch (err) {
|
|
66
70
|
logger.error(err)
|
|
67
71
|
res.status(401).json({ error: { status: 401, code: 401, message: err.message } })
|
|
@@ -92,28 +96,19 @@ app.get('/whoami', async (req, res) => {
|
|
|
92
96
|
}
|
|
93
97
|
})
|
|
94
98
|
|
|
95
|
-
async function start ({ port, databaseUrl } = {}) {
|
|
96
|
-
|
|
99
|
+
async function start ({ port, hostname, databaseUrl } = {}) {
|
|
100
|
+
({ PORT, HOSTNAME } = resolvePortAndHostname({ port, hostname }))
|
|
97
101
|
|
|
98
102
|
if (HTTP_SERVER) return HTTP_SERVER
|
|
99
103
|
|
|
100
104
|
try {
|
|
101
|
-
const {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const db = await new Promise((resolve, reject) => {
|
|
105
|
-
orm.initialize(config, (err, ontology) => {
|
|
106
|
-
if (err) return reject(err)
|
|
107
|
-
resolve(ontology)
|
|
108
|
-
})
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
ORM = orm
|
|
112
|
-
app.models = db.collections
|
|
105
|
+
const { db, models } = connectOrm({ databaseUrl })
|
|
106
|
+
DB = db
|
|
107
|
+
app.models = models
|
|
113
108
|
|
|
114
109
|
HTTP_SERVER = await new Promise((resolve, reject) => {
|
|
115
110
|
const server = app.listen(PORT, () => {
|
|
116
|
-
logger.success(`vestauth server listening on
|
|
111
|
+
logger.success(`vestauth server listening on ${HOSTNAME}`)
|
|
117
112
|
resolve(server)
|
|
118
113
|
})
|
|
119
114
|
|
|
@@ -145,14 +140,9 @@ async function close () {
|
|
|
145
140
|
HTTP_SERVER = null
|
|
146
141
|
}
|
|
147
142
|
|
|
148
|
-
if (
|
|
149
|
-
await
|
|
150
|
-
|
|
151
|
-
if (err) return reject(err)
|
|
152
|
-
resolve()
|
|
153
|
-
})
|
|
154
|
-
})
|
|
155
|
-
ORM = null
|
|
143
|
+
if (DB) {
|
|
144
|
+
await DB.destroy()
|
|
145
|
+
DB = null
|
|
156
146
|
}
|
|
157
147
|
|
|
158
148
|
delete app.models
|
|
@@ -199,5 +189,6 @@ function removeSignalHandlers () {
|
|
|
199
189
|
module.exports = {
|
|
200
190
|
app,
|
|
201
191
|
start,
|
|
202
|
-
close
|
|
192
|
+
close,
|
|
193
|
+
resolvePortAndHostname
|
|
203
194
|
}
|
|
@@ -1,47 +1,72 @@
|
|
|
1
1
|
const crypto = require('crypto')
|
|
2
|
-
const Waterline = require('waterline')
|
|
3
2
|
|
|
4
3
|
const protocol = require('./../../lib/helpers/protocol')
|
|
5
4
|
const hostname = require('./../../lib/helpers/hostname')
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
attributes: {
|
|
15
|
-
id: { type: 'number', autoMigrations: { autoIncrement: true } },
|
|
16
|
-
uid: { type: 'string', required: false },
|
|
17
|
-
createdAt: { columnName: 'created_at', type: 'ref', autoCreatedAt: true },
|
|
18
|
-
updatedAt: { columnName: 'updated_at', type: 'ref', autoUpdatedAt: true },
|
|
19
|
-
|
|
20
|
-
// relationships
|
|
21
|
-
publicJwks: {
|
|
22
|
-
collection: 'public_jwk',
|
|
23
|
-
via: 'agent'
|
|
24
|
-
}
|
|
25
|
-
},
|
|
6
|
+
class AgentRecord {
|
|
7
|
+
constructor (attrs = {}) {
|
|
8
|
+
this.id = attrs.id
|
|
9
|
+
this.uid = attrs.uid
|
|
10
|
+
this.createdAt = attrs.createdAt
|
|
11
|
+
this.updatedAt = attrs.updatedAt
|
|
12
|
+
}
|
|
26
13
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
toJSON () {
|
|
15
|
+
return {
|
|
16
|
+
id: this.id,
|
|
17
|
+
uid: this.uid,
|
|
18
|
+
createdAt: this.createdAt,
|
|
19
|
+
updatedAt: this.updatedAt,
|
|
20
|
+
uidFormatted: `agent-${this.uid}`,
|
|
21
|
+
wellKnownUrl: `${protocol()}://agent-${this.uid}.${hostname()}/.well-known/http-message-signatures-directory`
|
|
31
22
|
}
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class Agent {
|
|
27
|
+
constructor ({ db }) {
|
|
28
|
+
this.db = db
|
|
29
|
+
this.tableName = 'agents'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async create (attrs = {}) {
|
|
33
|
+
const now = new Date()
|
|
34
|
+
const uid = attrs.uid || crypto.randomBytes(12).toString('hex')
|
|
35
|
+
|
|
36
|
+
const [row] = await this.db(this.tableName)
|
|
37
|
+
.insert({
|
|
38
|
+
uid,
|
|
39
|
+
created_at: now,
|
|
40
|
+
updated_at: now
|
|
41
|
+
})
|
|
42
|
+
.returning(['id', 'uid', 'created_at', 'updated_at'])
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
return this._fromRow(row)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async findOne (criteria = {}) {
|
|
48
|
+
const query = this.db(this.tableName)
|
|
49
|
+
|
|
50
|
+
if (criteria.id !== undefined) query.where({ id: criteria.id })
|
|
51
|
+
if (criteria.uid !== undefined) query.where({ uid: criteria.uid })
|
|
52
|
+
|
|
53
|
+
const row = await query.select(['id', 'uid', 'created_at', 'updated_at']).first()
|
|
54
|
+
|
|
55
|
+
if (!row) return null
|
|
56
|
+
|
|
57
|
+
return this._fromRow(row)
|
|
58
|
+
}
|
|
37
59
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// remove fields if needed
|
|
41
|
-
// delete self.privateKey
|
|
60
|
+
_fromRow (row) {
|
|
61
|
+
if (!row) return null
|
|
42
62
|
|
|
43
|
-
return
|
|
63
|
+
return new AgentRecord({
|
|
64
|
+
id: Number(row.id),
|
|
65
|
+
uid: row.uid,
|
|
66
|
+
createdAt: row.created_at,
|
|
67
|
+
updatedAt: row.updated_at
|
|
68
|
+
})
|
|
44
69
|
}
|
|
45
|
-
}
|
|
70
|
+
}
|
|
46
71
|
|
|
47
72
|
module.exports = Agent
|
|
@@ -1,31 +1,21 @@
|
|
|
1
|
-
const
|
|
2
|
-
const sailsPostgresAdapter = require('sails-postgresql')
|
|
1
|
+
const knex = require('knex')
|
|
3
2
|
|
|
4
3
|
const Agent = require('./agent')
|
|
5
4
|
const PublicJwk = require('./publicJwk')
|
|
6
5
|
|
|
7
6
|
function connectOrm ({ databaseUrl }) {
|
|
8
|
-
const
|
|
7
|
+
const db = knex({
|
|
8
|
+
client: 'pg',
|
|
9
|
+
connection: databaseUrl
|
|
10
|
+
})
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const config = {
|
|
16
|
-
adapters: {
|
|
17
|
-
postgres: sailsPostgresAdapter
|
|
18
|
-
},
|
|
19
|
-
datastores: {
|
|
20
|
-
default: {
|
|
21
|
-
adapter: 'postgres',
|
|
22
|
-
url: databaseUrl,
|
|
23
|
-
migrate: 'safe' // IMPORTANT. instead managed by knex
|
|
24
|
-
}
|
|
12
|
+
return {
|
|
13
|
+
db,
|
|
14
|
+
models: {
|
|
15
|
+
agent: new Agent({ db }),
|
|
16
|
+
public_jwk: new PublicJwk({ db })
|
|
25
17
|
}
|
|
26
18
|
}
|
|
27
|
-
|
|
28
|
-
return { orm, config }
|
|
29
19
|
}
|
|
30
20
|
|
|
31
21
|
module.exports = { connectOrm }
|
|
@@ -1,39 +1,94 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
class PublicJwkRecord {
|
|
2
|
+
constructor (attrs = {}) {
|
|
3
|
+
this.id = attrs.id
|
|
4
|
+
this.agent = attrs.agent
|
|
5
|
+
this.kid = attrs.kid
|
|
6
|
+
this.value = attrs.value
|
|
7
|
+
this.state = attrs.state
|
|
8
|
+
this.createdAt = attrs.createdAt
|
|
9
|
+
this.updatedAt = attrs.updatedAt
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
toJSON () {
|
|
13
|
+
return {
|
|
14
|
+
id: this.id,
|
|
15
|
+
agent: this.agent,
|
|
16
|
+
kid: this.kid,
|
|
17
|
+
value: this.value,
|
|
18
|
+
state: this.state,
|
|
19
|
+
createdAt: this.createdAt,
|
|
20
|
+
updatedAt: this.updatedAt
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class PublicJwk {
|
|
26
|
+
constructor ({ db }) {
|
|
27
|
+
this.db = db
|
|
28
|
+
this.tableName = 'public_jwks'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async create (attrs = {}) {
|
|
32
|
+
const now = new Date()
|
|
33
|
+
const rowToInsert = {
|
|
34
|
+
agent_id: attrs.agent,
|
|
35
|
+
kid: attrs.kid,
|
|
36
|
+
value: attrs.value,
|
|
37
|
+
state: attrs.state || 'active',
|
|
38
|
+
created_at: now,
|
|
39
|
+
updated_at: now
|
|
23
40
|
}
|
|
24
|
-
|
|
41
|
+
|
|
42
|
+
const [row] = await this.db(this.tableName)
|
|
43
|
+
.insert(rowToInsert)
|
|
44
|
+
.returning(['id', 'agent_id', 'kid', 'value', 'state', 'created_at', 'updated_at'])
|
|
45
|
+
|
|
46
|
+
return this._fromRow(row)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async find (criteria = {}) {
|
|
50
|
+
const query = this.db(this.tableName)
|
|
51
|
+
|
|
52
|
+
if (criteria.id !== undefined) query.where({ id: criteria.id })
|
|
53
|
+
if (criteria.agent !== undefined) query.where({ agent_id: criteria.agent })
|
|
54
|
+
if (criteria.kid !== undefined) query.where({ kid: criteria.kid })
|
|
55
|
+
if (criteria.state !== undefined) query.where({ state: criteria.state })
|
|
56
|
+
|
|
57
|
+
const rows = await query.select(['id', 'agent_id', 'kid', 'value', 'state', 'created_at', 'updated_at'])
|
|
58
|
+
|
|
59
|
+
return rows.map((row) => this._fromRow(row))
|
|
25
60
|
}
|
|
26
61
|
|
|
27
|
-
|
|
28
|
-
|
|
62
|
+
async findOne (criteria = {}) {
|
|
63
|
+
const query = this.db(this.tableName)
|
|
64
|
+
|
|
65
|
+
if (criteria.id !== undefined) query.where({ id: criteria.id })
|
|
66
|
+
if (criteria.agent !== undefined) query.where({ agent_id: criteria.agent })
|
|
67
|
+
if (criteria.kid !== undefined) query.where({ kid: criteria.kid })
|
|
68
|
+
if (criteria.state !== undefined) query.where({ state: criteria.state })
|
|
29
69
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// // delete self.privateKey
|
|
70
|
+
const row = await query
|
|
71
|
+
.select(['id', 'agent_id', 'kid', 'value', 'state', 'created_at', 'updated_at'])
|
|
72
|
+
.first()
|
|
34
73
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
74
|
+
if (!row) return null
|
|
75
|
+
|
|
76
|
+
return this._fromRow(row)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
_fromRow (row) {
|
|
80
|
+
if (!row) return null
|
|
81
|
+
|
|
82
|
+
return new PublicJwkRecord({
|
|
83
|
+
id: Number(row.id),
|
|
84
|
+
agent: Number(row.agent_id),
|
|
85
|
+
kid: row.kid,
|
|
86
|
+
value: row.value,
|
|
87
|
+
state: row.state,
|
|
88
|
+
createdAt: row.created_at,
|
|
89
|
+
updatedAt: row.updated_at
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
}
|
|
38
93
|
|
|
39
94
|
module.exports = PublicJwk
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class RegisterSerializer {
|
|
2
|
+
constructor ({ agent, publicJwk, isNew }) {
|
|
3
|
+
this.agent = agent
|
|
4
|
+
this.publicJwk = publicJwk
|
|
5
|
+
this.isNew = isNew
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
run () {
|
|
9
|
+
const agentFormatted = this.agent.toJSON()
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
uid: agentFormatted.uidFormatted,
|
|
13
|
+
kid: this.publicJwk.kid,
|
|
14
|
+
public_jwk: this.publicJwk,
|
|
15
|
+
is_new: Boolean(this.isNew)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = RegisterSerializer
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const primitives = require('./../../lib/primitives')
|
|
2
|
+
|
|
3
|
+
class RegisterService {
|
|
4
|
+
constructor ({ models, httpMethod, uri, headers, publicJwk }) {
|
|
5
|
+
this.models = models
|
|
6
|
+
this.httpMethod = httpMethod
|
|
7
|
+
this.uri = uri
|
|
8
|
+
this.headers = headers
|
|
9
|
+
this.publicJwk = publicJwk
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async run () {
|
|
13
|
+
this.verified = await primitives.verify(
|
|
14
|
+
this.httpMethod,
|
|
15
|
+
this.uri,
|
|
16
|
+
this.headers,
|
|
17
|
+
this.publicJwk
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
const existingPublicJwk = await this.models.public_jwk.findOne({ kid: this.verified.kid })
|
|
21
|
+
if (existingPublicJwk) {
|
|
22
|
+
const agent = await this.models.agent.findOne({ id: existingPublicJwk.agent })
|
|
23
|
+
if (!agent) {
|
|
24
|
+
throw new Error('agent not found for public_jwk')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
agent,
|
|
29
|
+
publicJwk: existingPublicJwk.value,
|
|
30
|
+
isNew: false
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const agent = await this.models.agent.create()
|
|
35
|
+
const createdPublicJwk = await this.models.public_jwk.create({
|
|
36
|
+
agent: agent.id,
|
|
37
|
+
kid: this.verified.kid,
|
|
38
|
+
value: this.verified.public_jwk
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
agent,
|
|
43
|
+
publicJwk: createdPublicJwk.value,
|
|
44
|
+
isNew: true
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = RegisterService
|
|
File without changes
|
|
File without changes
|
/package/src/{db/migrations → server/db/migration}/20260223205500_create_public_jwks_table.js
RENAMED
|
File without changes
|