expressa 2.0.12 → 2.0.13

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/.eslintrc.json CHANGED
@@ -20,7 +20,7 @@
20
20
  "xdescribe": true
21
21
  },
22
22
  "parserOptions": {
23
- "ecmaVersion": 2022
23
+ "ecmaVersion": 12
24
24
  },
25
25
  "env": {
26
26
  "es6": true,
package/auth/index.js CHANGED
@@ -17,6 +17,32 @@ exports.isValidPassword = function (password, hashedPassword) {
17
17
  exports.doLogin = handler.doLogin
18
18
 
19
19
  exports.middleware = async function authMiddleware(req, res, next) {
20
+ const key = req.query['access_key'] || req.headers['x-access-key']
21
+ if (key) {
22
+ if (typeof key == 'string' && req.db['access_keys']) {
23
+ const accessKeys = await req.db['access_keys'].find({ key: { $eq: key } }, 0, 1)
24
+ if (accessKeys && accessKeys.length > 0) {
25
+ const accessKey = accessKeys[0]
26
+ // check if access key is still valid
27
+ if (accessKey.expires_at >= new Date().toISOString()) {
28
+ let user
29
+ try {
30
+ user = await req.db[accessKey.user_collection].get(accessKey.user_id)
31
+ } catch (e) {
32
+ req.uerror = 'user no longer exists'
33
+ }
34
+ if (user && !req.uerror) {
35
+ req.uid = user._id
36
+ req.ucollection = 'users'
37
+ req.user = user
38
+ }
39
+ }
40
+ }
41
+ } else {
42
+ console.error('Non-string access key sent')
43
+ }
44
+ }
45
+
20
46
  req.query = req.query || {}
21
47
  const token = req.query['token'] || req.headers['x-access-token']
22
48
  delete req.query['token']
package/index.js CHANGED
@@ -183,7 +183,7 @@ module.exports.api = function (settings) {
183
183
  (async function setup() {
184
184
  await initCollections(router.db, router)
185
185
 
186
- const modules = ['collections', 'core', 'logging', 'permissions']
186
+ const modules = ['collections', 'core', 'logging', 'permissions', 'access_keys']
187
187
  router.modules = {}
188
188
  for (const module of modules) {
189
189
  router.modules[module] = require(`./modules/${module}/${module}`)
@@ -0,0 +1,33 @@
1
+ exports.collections = function () {
2
+ const access_keys = {
3
+ _id: 'access_keys',
4
+ schema: {
5
+ type: 'object',
6
+ additionalProperties: false,
7
+ properties: {
8
+ user_collection: {
9
+ type: 'string'
10
+ },
11
+ user_id: {
12
+ type: 'string'
13
+ },
14
+ key: {
15
+ type: 'string',
16
+ description: 'randomly generated secret'
17
+ },
18
+ expires_at: {
19
+ type: 'string'
20
+ },
21
+ },
22
+ required: [
23
+ 'user_id',
24
+ 'key',
25
+ 'expires_at',
26
+ ]
27
+ },
28
+ storage: 'file',
29
+ documentsHaveOwners: true
30
+ }
31
+
32
+ return [access_keys]
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expressa",
3
- "version": "2.0.12",
3
+ "version": "2.0.13",
4
4
  "description": "API framework using JSON schemas",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/thomas4019/expressa",
@@ -17,7 +17,7 @@
17
17
  "jfs": "^0.3.0",
18
18
  "jsonwebtoken": "^9.0.0",
19
19
  "mongo-query": "^0.5.7",
20
- "mongo-query-to-postgres-jsonb": "^0.2.16",
20
+ "mongo-query-to-postgres-jsonb": "^0.2.17",
21
21
  "mongo-querystring": "4.1.1",
22
22
  "mongodb": "^3.5.7",
23
23
  "on-finished": "^2.3.0",
package/test/0-install.js CHANGED
@@ -21,7 +21,7 @@ describe('install flow', function () {
21
21
  await request(app)
22
22
  .post('/install')
23
23
  .send({
24
- modules: ['collections', 'core', 'logging', 'permissions'],
24
+ modules: ['collections', 'core', 'logging', 'permissions', 'access_keys'],
25
25
  settings: {
26
26
  jwt_secret: 'testing 123',
27
27
  jwt_expire_on_password_change: true,
package/test/test.js CHANGED
@@ -54,6 +54,20 @@ describe('General Tests:', () => {
54
54
  .expect(200)
55
55
  })
56
56
 
57
+ it('returns collections using a key', async function () {
58
+ const badKey = '123'
59
+ await request(app)
60
+ .get('/collection')
61
+ .set('x-access-key', badKey)
62
+ .expect(401)
63
+
64
+ const key = await testutils.getAccessKeyForUserWithPermissions(api, ['collection: view'])
65
+ await request(app)
66
+ .get('/collection')
67
+ .set('x-access-key', key)
68
+ .expect(200)
69
+ })
70
+
57
71
  it('Sets headers', async function () {
58
72
  const token = await testutils.getUserWithPermissions(api, ['collection: view'])
59
73
  const res = await request(app)
package/test/testutils.js CHANGED
@@ -81,6 +81,54 @@ exports.getUserWithPermissions = async function(api, permissions) {
81
81
  user._id = loginRes.body.uid
82
82
  return loginRes.body.token
83
83
  }
84
+
85
+ exports.getAccessKeyForUserWithPermissions = async function(api, permissions) {
86
+ const service = request(exports.app)
87
+ if (typeof permissions === 'string') {
88
+ permissions = [permissions]
89
+ }
90
+ permissions = permissions || []
91
+ const permissionsMap = {}
92
+ permissions.forEach(function (permission) {
93
+ permissionsMap[permission] = true
94
+ })
95
+
96
+ const randId = randomstring.generate(12)
97
+ const roleName = 'role' + randId
98
+ const role = {
99
+ _id: roleName,
100
+ permissions: permissionsMap
101
+ }
102
+
103
+ const roleRes = await service.post('/role')
104
+ .set('x-access-token', tokens.admin)
105
+ .send(role)
106
+ .expect(200)
107
+
108
+ const user = {
109
+ email: 'test' + randId + '@example.com',
110
+ password: '123',
111
+ }
112
+ const registerRes = await service.post('/users/register')
113
+ .send(user)
114
+ .expect(200)
115
+
116
+ const updateRes = await service.post(`/users/${registerRes.body.id}/update`)
117
+ .send({ $push: { roles: roleName } })
118
+ .set('x-access-token', tokens.admin)
119
+ .expect(200)
120
+
121
+ let accessKey = randomstring.generate(8)
122
+ await exports.api.db.access_keys.create({
123
+ user_collection: 'users',
124
+ user_id: registerRes.body.id,
125
+ key: accessKey,
126
+ expires_at: '2032-01-01T00:00:00'
127
+ })
128
+
129
+ return accessKey
130
+ }
131
+
84
132
  exports.clone = util.clone
85
133
  exports.sleep = function sleep(ms) {
86
134
  return new Promise(resolve => setTimeout(resolve, ms))