UNPKG

2.13 kBJavaScriptView Raw
1const { Grant } = require('q3-core-access');
2
3class Session {
4 constructor(req) {
5 this.method = req.method;
6 this.auth = req.get('Authorization');
7 }
8
9 getToken() {
10 if (!this.auth) return '';
11 return this.auth.startsWith('Apikey') ||
12 this.auth.startsWith('Bearer')
13 ? this.auth.substr(7)
14 : this.auth;
15 }
16
17 setOperation() {
18 switch (this.method) {
19 case 'PATCH':
20 case 'PUT':
21 this.op = 'Update';
22 break;
23 case 'GET':
24 this.op = 'Read';
25 break;
26 case 'POST':
27 this.op = 'Create';
28 break;
29 case 'DELETE':
30 this.op = 'Delete';
31 break;
32 default:
33 throw new Error('Method not allowed');
34 }
35
36 return this;
37 }
38
39 getPermission(collectionName, sessionUser) {
40 const gen = (op) =>
41 new Grant(sessionUser)
42 .can(op)
43 .on(collectionName)
44 .first();
45
46 const primary = gen(this.op);
47 const secondary = gen('Read');
48
49 /**
50 * @NOTE
51 * Used to redact responses on non-read operations.
52 */
53 if (primary && secondary)
54 primary.readOnly = secondary.fields;
55
56 return primary;
57 }
58}
59
60function middleware(UserModel) {
61 if (!UserModel)
62 throw new Error(
63 'Cannot run middleware without User models',
64 );
65
66 return async (req, res, next) => {
67 const hasMethod = (method) =>
68 method in UserModel && !req.user;
69
70 const identity = new Session(req);
71 const token = identity.getToken();
72 const nonce = req.header('X-Session-Nonce');
73 const host = req.get('host');
74
75 if (hasMethod('findbyBearerToken'))
76 req.user = await UserModel.findbyBearerToken(
77 token,
78 nonce,
79 host,
80 );
81
82 if (hasMethod('findByApiKey'))
83 req.user = await UserModel.findByApiKey(
84 token,
85 nonce,
86 host,
87 );
88
89 req.authorize = (collectionName) =>
90 identity
91 .setOperation()
92 .getPermission(collectionName, req.user);
93
94 next();
95 };
96}
97
98module.exports = middleware;