@hitchy/plugin-auth 0.2.0 → 0.3.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.
Files changed (66) hide show
  1. package/.gitlab-ci.yml +42 -21
  2. package/LICENSE +21 -0
  3. package/api/controller/user.js +2 -29
  4. package/api/model/authorization/rule.js +0 -27
  5. package/api/model/role.js +0 -28
  6. package/api/model/user-to-role.js +0 -28
  7. package/api/model/user.js +2 -30
  8. package/api/policy/authentication.js +127 -70
  9. package/api/policy/authorization.js +0 -28
  10. package/api/policy/user.js +0 -28
  11. package/api/service/auth/manager.js +45 -32
  12. package/api/service/authentication/passport.js +7 -34
  13. package/api/service/authentication/strategies.js +230 -58
  14. package/api/service/authorization/node.js +0 -28
  15. package/api/service/authorization/policy-generator.js +0 -28
  16. package/api/service/authorization/tree.js +8 -36
  17. package/config/auth.js +5 -0
  18. package/coverage/base.css +224 -0
  19. package/coverage/block-navigation.js +79 -0
  20. package/coverage/favicon.png +0 -0
  21. package/coverage/index.html +231 -0
  22. package/coverage/plugin-auth/api/controller/index.html +111 -0
  23. package/coverage/plugin-auth/api/controller/user.js.html +368 -0
  24. package/coverage/plugin-auth/api/model/authorization/index.html +111 -0
  25. package/coverage/plugin-auth/api/model/authorization/rule.js.html +227 -0
  26. package/coverage/plugin-auth/api/model/index.html +141 -0
  27. package/coverage/plugin-auth/api/model/role.js.html +200 -0
  28. package/coverage/plugin-auth/api/model/user-to-role.js.html +167 -0
  29. package/coverage/plugin-auth/api/model/user.js.html +752 -0
  30. package/coverage/plugin-auth/api/policy/authentication.js.html +782 -0
  31. package/coverage/plugin-auth/api/policy/authorization.js.html +182 -0
  32. package/coverage/plugin-auth/api/policy/index.html +141 -0
  33. package/coverage/plugin-auth/api/policy/user.js.html +479 -0
  34. package/coverage/plugin-auth/api/service/auth/index.html +111 -0
  35. package/coverage/plugin-auth/api/service/auth/manager.js.html +959 -0
  36. package/coverage/plugin-auth/api/service/authentication/index.html +126 -0
  37. package/coverage/plugin-auth/api/service/authentication/passport.js.html +293 -0
  38. package/coverage/plugin-auth/api/service/authentication/strategies.js.html +929 -0
  39. package/coverage/plugin-auth/api/service/authorization/index.html +141 -0
  40. package/coverage/plugin-auth/api/service/authorization/node.js.html +944 -0
  41. package/coverage/plugin-auth/api/service/authorization/policy-generator.js.html +386 -0
  42. package/coverage/plugin-auth/api/service/authorization/tree.js.html +983 -0
  43. package/coverage/plugin-auth/config/auth.js.html +140 -0
  44. package/coverage/plugin-auth/config/index.html +111 -0
  45. package/coverage/plugin-auth/index.html +111 -0
  46. package/coverage/plugin-auth/index.js.html +344 -0
  47. package/coverage/prettify.css +1 -0
  48. package/coverage/prettify.js +2 -0
  49. package/coverage/sort-arrow-sprite.png +0 -0
  50. package/coverage/sorter.js +170 -0
  51. package/coverage/tmp/coverage-8472-1648414315419-0.json +1 -0
  52. package/docs/.vuepress/config.js +5 -2
  53. package/docs/api/config.md +14 -2
  54. package/docs/api/model/authorization-rule.md +1 -1
  55. package/docs/api/model/user.md +2 -2
  56. package/docs/api/service/authentication-passport.md +1 -1
  57. package/docs/guides/getting-started.md +2 -2
  58. package/docs/guides/idp-login.png +0 -0
  59. package/docs/guides/idp-saml-cert.png +0 -0
  60. package/docs/guides/openid-connect.md +164 -0
  61. package/docs/guides/readme.md +2 -0
  62. package/docs/guides/saml.md +161 -0
  63. package/docs/introduction.md +5 -5
  64. package/index.js +31 -51
  65. package/package.json +18 -13
  66. package/readme.md +11 -43
@@ -1,38 +1,10 @@
1
- /**
2
- * (c) 2021 cepharum GmbH, Berlin, http://cepharum.de
3
- *
4
- * The MIT License (MIT)
5
- *
6
- * Copyright (c) 2021 cepharum GmbH
7
- *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
14
- *
15
- * The above copyright notice and this permission notice shall be included in all
16
- * copies or substantial portions of the Software.
17
- *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
- * SOFTWARE.
25
- *
26
- * @author: cepharum
27
- */
28
-
29
1
  "use strict";
30
2
 
31
3
  module.exports = function() {
32
4
  const api = this;
33
- const { models } = api.runtime;
5
+ const { models, services } = api.runtime;
34
6
 
35
- const DebugLog = api.log( "hitchy:plugin:auth:debug" );
7
+ const logDebug = api.log( "hitchy:plugin:auth:debug" );
36
8
 
37
9
  /**
38
10
  * Implements several helper methods meant to simplify user/role management.
@@ -89,6 +61,15 @@ module.exports = function() {
89
61
  }
90
62
 
91
63
  const { Role } = models;
64
+
65
+ if ( !( role instanceof Role ) ) {
66
+ role = String( role ); // eslint-disable-line no-param-reassign
67
+
68
+ if ( !/^[a-z_]/i.test( role ) || /\s/.test( role ) ) {
69
+ throw new TypeError( "missing role information" );
70
+ }
71
+ }
72
+
92
73
  const roles = role instanceof Role ? [role] : await Role.find( {
93
74
  eq: { name: "name", value: role.name || role },
94
75
  } );
@@ -246,7 +227,7 @@ module.exports = function() {
246
227
  const users = await this.listUsersOfRole( role );
247
228
 
248
229
  if ( users.length > 0 ) {
249
- DebugLog( "admin user found" );
230
+ logDebug( "admin user found" );
250
231
 
251
232
  return users;
252
233
  }
@@ -260,7 +241,7 @@ module.exports = function() {
260
241
  } else {
261
242
  const config = api.config.auth.admin;
262
243
 
263
- DebugLog( "creating admin user" );
244
+ logDebug( "creating admin user" );
264
245
 
265
246
  user = new models.User();
266
247
 
@@ -274,6 +255,38 @@ module.exports = function() {
274
255
 
275
256
  return [user];
276
257
  }
258
+
259
+ /**
260
+ * Checks if named user can be authenticated locally using provided
261
+ * password.
262
+ *
263
+ * @param {string} username name of user to authenticate
264
+ * @param {string} password password of named to user
265
+ * @return {Promise<User>} promises successfully authenticated user
266
+ */
267
+ static async checkAuthentication( username, password ) {
268
+ const candidates = ( await models.User
269
+ .find( { eq: { name: username } }, {}, { loadRecords: true } ) )
270
+ .filter( user => !user.strategy || user.strategy === "local" );
271
+
272
+ switch ( candidates.length ) {
273
+ case 0 :
274
+ throw new services.HttpException( 400, `no such local user: ${username}` );
275
+
276
+ case 1 : {
277
+ const [user] = candidates;
278
+
279
+ if ( await user.verifyPassword( password ) ) {
280
+ return user;
281
+ }
282
+
283
+ throw new services.HttpException( 403, "invalid password" );
284
+ }
285
+
286
+ default :
287
+ throw new services.HttpException( 400, "ambiguous username" );
288
+ }
289
+ }
277
290
  }
278
291
 
279
292
  return AuthManager;
@@ -1,39 +1,12 @@
1
- /**
2
- * (c) 2021 cepharum GmbH, Berlin, http://cepharum.de
3
- *
4
- * The MIT License (MIT)
5
- *
6
- * Copyright (c) 2021 cepharum GmbH
7
- *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
14
- *
15
- * The above copyright notice and this permission notice shall be included in all
16
- * copies or substantial portions of the Software.
17
- *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
- * SOFTWARE.
25
- *
26
- * @author: cepharum
27
- */
28
-
29
1
  "use strict";
30
2
 
31
3
  const PassportLib = require( "passport" );
32
4
 
33
5
  module.exports = function() {
34
6
  const api = this;
35
- const AlertLog = api.log( "hitchy:plugin:auth:alert" );
36
- const DebugLog = api.log( "hitchy:plugin:auth:debug" );
7
+
8
+ const logAlert = api.log( "hitchy:plugin:auth:alert" );
9
+ const logDebug = api.log( "hitchy:plugin:auth:debug" );
37
10
 
38
11
  const passport = new PassportLib.Passport();
39
12
 
@@ -49,7 +22,7 @@ module.exports = function() {
49
22
 
50
23
  // set up passport to persist current user in server-side session
51
24
  passport.serializeUser( ( user, done ) => {
52
- DebugLog( `serializeUser: { name: ${user.name}, uuid: ${user.uuid} }` );
25
+ logDebug( `serializeUser: { name: ${user.name}, uuid: ${user.uuid} }` );
53
26
 
54
27
  done( null, user.uuid );
55
28
  } );
@@ -68,7 +41,7 @@ module.exports = function() {
68
41
  .then( roles => {
69
42
  user.roles = roles;
70
43
 
71
- DebugLog( `still authenticated user: name: ${user.name}, uuid: ${user.uuid}, roles: ${roles.join( "," )}` );
44
+ logDebug( `still authenticated user: name: ${user.name}, uuid: ${user.uuid}, roles: ${roles.join( "," )}` );
72
45
 
73
46
  done( null, user );
74
47
  } )
@@ -86,9 +59,9 @@ module.exports = function() {
86
59
 
87
60
  if ( strategy ) {
88
61
  try {
89
- passport.use( strategy.name, strategy );
62
+ passport.use( name, strategy );
90
63
  } catch ( error ) {
91
- AlertLog( `using passport strategy ${name} failed:`, error );
64
+ logAlert( `using passport strategy ${name} failed:`, error );
92
65
  }
93
66
  }
94
67
  }
@@ -1,45 +1,107 @@
1
+ "use strict";
2
+
3
+ const LocalStrategy = require( "passport-local" ).Strategy;
4
+
1
5
  /**
2
- * (c) 2021 cepharum GmbH, Berlin, http://cepharum.de
3
- *
4
- * The MIT License (MIT)
6
+ * Temporarily tracks additional session data per remotely authenticated user.
5
7
  *
6
- * Copyright (c) 2021 cepharum GmbH
8
+ * Some strategies (such as passport-saml) expect certain strategy-related data
9
+ * per authenticated user to be present on `req.user` prior to accepting request
10
+ * for logging out. In hitchy, `req.user` is fetched from database on every
11
+ * request and thus no temporary data is available. Hence, this local map is
12
+ * used instead to track any additional data for those strategies.
7
13
  *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
14
- *
15
- * The above copyright notice and this permission notice shall be included in all
16
- * copies or substantial portions of the Software.
17
- *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
- * SOFTWARE.
25
- *
26
- * @author: cepharum
14
+ * @type {Map<any, any>}
27
15
  */
28
-
29
- "use strict";
30
-
31
- const LocalStrategy = require( "passport-local" ).Strategy;
16
+ const RemoteAuthCustomData = new Map();
32
17
 
33
18
  module.exports = function() {
34
19
  const api = this;
35
- const { models } = api.runtime;
20
+ const { models, services } = api.runtime;
21
+
22
+ const logAlert = api.log( "hitchy:plugin:auth:alert" );
23
+
24
+ /**
25
+ * Fetches named user's local profile.
26
+ *
27
+ * @param {string} strategyName name of strategy used to authenticate user
28
+ * @param {string} username name of user to search locally for related profile
29
+ * @param {boolean} createIfMissing set true to create user's profile if it's missing currenly
30
+ * @param {function(Error?, object):void} doneFn callback invoked with encountered error or user's profile
31
+ * @returns {void}
32
+ */
33
+ function getLocalProfile( strategyName, username, createIfMissing, doneFn ) {
34
+ models.User.find( { eq: { name: username } } )
35
+ .then( candidates => candidates.find( user => user.strategy === strategyName ) )
36
+ .then( match => {
37
+ if ( match ) {
38
+ return match;
39
+ }
40
+
41
+ if ( createIfMissing ) {
42
+ const newUser = new models.User();
43
+ newUser.name = username;
44
+ newUser.strategy = strategyName;
36
45
 
37
- const AlertLog = api.log( "hitchy:plugin:auth:alert" );
46
+ return newUser.save();
47
+ }
48
+
49
+ throw new TypeError( "selected user does not exist" );
50
+ } )
51
+ .then( profile => doneFn( null, profile ) )
52
+ .catch( doneFn );
53
+ }
38
54
 
39
55
  /**
40
56
  * Implements helpers for generating strategies for passport.js.
41
57
  */
42
58
  class AuthenticationStrategies {
59
+ /**
60
+ * Picks user based on provided name and checks if provided password is
61
+ * matching or not.
62
+ *
63
+ * @param {string} username name of user to authenticate
64
+ * @param {string} password named user's password for authentication
65
+ * @param {function(Error?, object, object)} done invoked with optional error, authenticated user or some message as feedback
66
+ * @returns {void}
67
+ */
68
+ static checkAuthentication( username, password, done ) {
69
+ models.User
70
+ .find( { eq: { username } }, {}, { loadRecords: true } )
71
+ .then( matches => {
72
+ switch ( matches.length ) {
73
+ case 0 :
74
+ done( null, false, { message: "Incorrect username." } );
75
+ return undefined;
76
+
77
+ case 1 : {
78
+ const [user] = matches;
79
+
80
+ if ( user.strategy && user.strategy !== "local" ) {
81
+ done( null, false, { message: "Authenticating this user requires different strategy." } );
82
+ return undefined;
83
+ }
84
+
85
+ return user.verifyPassword( password ).then( result => {
86
+ if ( result ) {
87
+ done( null, user );
88
+ } else {
89
+ done( null, false, { message: "Incorrect password." } );
90
+ }
91
+ } );
92
+ }
93
+
94
+ default :
95
+ done( null, false, { message: "Ambiguous username." } );
96
+ return undefined;
97
+ }
98
+ } )
99
+ .catch( err => {
100
+ logAlert( err );
101
+ done( err );
102
+ } );
103
+ }
104
+
43
105
  /**
44
106
  * Generates local strategy authenticating user based on local user
45
107
  * model managed in local ODM.
@@ -48,43 +110,153 @@ module.exports = function() {
48
110
  */
49
111
  static generateLocal() {
50
112
  const strategy = new LocalStrategy( ( name, password, done ) => {
51
- models.User
52
- .find( { eq: { name } }, {}, { loadRecords: true } )
53
- .then( matches => {
54
- switch ( matches.length ) {
55
- case 0 :
56
- done( null, false, { message: "Incorrect username." } );
57
- return undefined;
113
+ services.AuthManager.checkAuthentication( name, password, done )
114
+ .then( user => {
115
+ done( null, user );
116
+ } )
117
+ .catch( error => {
118
+ if ( error instanceof services.HttpException && Math.floor( error.statusCode / 100 ) === 4 ) {
119
+ done( null, false, { message: error.message } );
120
+ } else {
121
+ done( error );
122
+ }
123
+ } );
124
+ } );
125
+
126
+ strategy.passwordRequried = true;
127
+
128
+ return strategy;
129
+ }
130
+
131
+ /**
132
+ * Generates SAML strategy authenticating user against some remote IdP
133
+ * based on SAML v2.0 protocol.
134
+ *
135
+ * @param {string} strategyName name of resulting strategy in context of your application
136
+ * @param {Hitchy.Plugin.Auth.SamlConfig} config SAML protocol configuration
137
+ * @returns {Strategy} generated strategy for use with passport.js
138
+ */
139
+ static generateSaml( strategyName, config ) {
140
+ const verifyLocalProfileOnLogin = ( req, userInfo, done ) => {
141
+ RemoteAuthCustomData.set( `${strategyName}:${userInfo.nameID}`, { ...userInfo } );
142
+
143
+ getLocalProfile( strategyName, userInfo.nameID, true, done );
144
+ };
145
+
146
+ const verifyLocalProfileOnLogout = ( req, userInfo, done ) => {
147
+ getLocalProfile( strategyName, userInfo.nameID, false, done );
148
+ };
149
+
150
+ const { Strategy } = require( "passport-saml" );
151
+ const strategy = new Strategy( {
152
+ ...config,
153
+ passReqToCallback: true,
154
+ }, verifyLocalProfileOnLogin, verifyLocalProfileOnLogout );
58
155
 
59
- case 1 : {
60
- const [user] = matches;
156
+ /**
157
+ * Triggers requesting user being logged out remotely.
158
+ *
159
+ * @param {Hitchy.Core.IncomingMessage} req request descriptor
160
+ * @returns {Promise<boolean>} promises indicator if request was redirected to come back after remote logout succeeded
161
+ */
162
+ strategy.logOutRemotely = req => {
163
+ if ( req.query.SAMLResponse ) {
164
+ return Promise.resolve( false );
165
+ }
61
166
 
62
- if ( user.strategy && user.strategy !== "local" ) {
63
- done( null, false, { message: "Authenticating this user requires different strategy." } );
64
- return undefined;
167
+ const res = req.context.response;
168
+
169
+ return new Promise( ( resolve, reject ) => {
170
+ const { user } = req;
171
+
172
+ const remoteSessionKey = `${strategyName}:${user.name}`;
173
+
174
+ if ( !user || user.strategy !== strategyName || !RemoteAuthCustomData.has( remoteSessionKey ) ) {
175
+ resolve( {} );
176
+ } else {
177
+ // inject custom auth data into `req.user` as expected by passport-saml strategy
178
+ const data = RemoteAuthCustomData.get( remoteSessionKey );
179
+
180
+ for ( const name of Object.keys( data ) ) {
181
+ user[name] = data[name];
182
+ }
183
+
184
+ user.nameID = user.name;
185
+
186
+ if ( !user.nameID || !user.nameIDFormat ) {
187
+ reject( new Error( "missing nameID and nameIDFormat of user required for requesting logout at IdP" ) );
188
+ } else {
189
+ // ask strategy for generating logout URL for redirecting client to
190
+ strategy.logout( req, ( error, logoutUrl ) => {
191
+ if ( error ) {
192
+ reject( error );
193
+ } else {
194
+ resolve( { name: remoteSessionKey, url: logoutUrl } );
65
195
  }
196
+ } );
197
+ }
198
+ }
199
+ } )
200
+ .then( ( { name, url } ) => {
201
+ if ( url ) {
202
+ // first pass -> redirect to IdP
203
+ res.redirect( 302, url );
204
+ return true;
205
+ }
66
206
 
67
- return user.verifyPassword( password ).then( result => {
68
- if ( result ) {
69
- done( null, user );
70
- } else {
71
- done( null, false, { message: "Incorrect password." } );
72
- }
73
- } );
74
- }
207
+ // second pass -> returned from IdP
75
208
 
76
- default :
77
- done( null, false, { message: "Ambiguous username." } );
78
- return undefined;
209
+ if ( name ) {
210
+ RemoteAuthCustomData.delete( name );
79
211
  }
80
- } )
81
- .catch( err => {
82
- AlertLog( err );
83
- done( err );
212
+
213
+ return false;
84
214
  } );
85
- } );
215
+ };
86
216
 
87
- strategy.passwordRequried = true;
217
+ Object.defineProperty( strategy, "$$doNotSeal$$", { value: true } );
218
+
219
+ return strategy;
220
+ }
221
+
222
+ /**
223
+ * Creates strategy for illustrating and testing integration with remote IdP
224
+ * supporting OpenID Connect with Authorization Code Flow.
225
+ *
226
+ * @param {string} strategyName name of resulting strategy in context of your application
227
+ * @param {ClientMetaData} config OpenID Connect client configuration
228
+ * @returns {Promise<Strategy>} promises generated strategy for use with passport.js
229
+ */
230
+ static async generateOpenIdConnect( strategyName, config ) { // eslint-disable-line consistent-this
231
+ const verifyLocalProfileOnLogin = ( req, tokens, userInfo, done ) => {
232
+ getLocalProfile( strategyName, userInfo.preferred_username, true, done );
233
+ };
234
+
235
+ const { Issuer, Strategy } = require( "openid-client" );
236
+ const issuer = await Issuer.discover( config.discovery_url );
237
+ const client = new issuer.Client( config );
238
+
239
+ const strategy = new Strategy( {
240
+ client,
241
+ passReqToCallback: true,
242
+ }, verifyLocalProfileOnLogin );
243
+
244
+ strategy.logOutRemotely = req => {
245
+ const key = `${strategyName}:logout_state`;
246
+
247
+ if ( req.session[key] && req.query.state === req.session[key] ) {
248
+ return Promise.resolve( false );
249
+ }
250
+
251
+ const state = req.session[key] = require( "crypto" ).randomBytes( 32 ).toString( "base64" ); // eslint-disable-line no-param-reassign
252
+
253
+ // redirect user to discovered end_session_url of IdP
254
+ req.context.response.redirect( 302, client.endSessionUrl( { state } ) );
255
+
256
+ return Promise.resolve( true );
257
+ };
258
+
259
+ Object.defineProperty( strategy, "$$doNotSeal$$", { value: true } );
88
260
 
89
261
  return strategy;
90
262
  }
@@ -1,31 +1,3 @@
1
- /**
2
- * (c) 2021 cepharum GmbH, Berlin, http://cepharum.de
3
- *
4
- * The MIT License (MIT)
5
- *
6
- * Copyright (c) 2021 cepharum GmbH
7
- *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
14
- *
15
- * The above copyright notice and this permission notice shall be included in all
16
- * copies or substantial portions of the Software.
17
- *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
- * SOFTWARE.
25
- *
26
- * @author: cepharum
27
- */
28
-
29
1
  "use strict";
30
2
 
31
3
  module.exports = function() {
@@ -1,31 +1,3 @@
1
- /**
2
- * (c) 2021 cepharum GmbH, Berlin, http://cepharum.de
3
- *
4
- * The MIT License (MIT)
5
- *
6
- * Copyright (c) 2021 cepharum GmbH
7
- *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
14
- *
15
- * The above copyright notice and this permission notice shall be included in all
16
- * copies or substantial portions of the Software.
17
- *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
- * SOFTWARE.
25
- *
26
- * @author: cepharum
27
- */
28
-
29
1
  "use strict";
30
2
 
31
3
  module.exports = function() {
@@ -1,39 +1,11 @@
1
- /**
2
- * (c) 2021 cepharum GmbH, Berlin, http://cepharum.de
3
- *
4
- * The MIT License (MIT)
5
- *
6
- * Copyright (c) 2021 cepharum GmbH
7
- *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
14
- *
15
- * The above copyright notice and this permission notice shall be included in all
16
- * copies or substantial portions of the Software.
17
- *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
- * SOFTWARE.
25
- *
26
- * @author: cepharum
27
- */
28
-
29
1
  "use strict";
30
2
 
31
3
  module.exports = function() {
32
4
  const api = this;
33
5
  const { services, models } = api.runtime;
34
6
 
35
- const AlertLog = api.log( "hitchy:plugin:auth:alert" );
36
- const DebugLog = api.log( "hitchy:plugin:auth:debug" );
7
+ const logAlert = api.log( "hitchy:plugin:auth:alert" );
8
+ const logDebug = api.log( "hitchy:plugin:auth:debug" );
37
9
 
38
10
  let cachedTree;
39
11
 
@@ -130,7 +102,7 @@ module.exports = function() {
130
102
  addRule( rule ) {
131
103
  const { selector, role, user, accept } = rule;
132
104
 
133
- DebugLog( "adding authorization rule", { selector, role, user, accept } );
105
+ logDebug( "adding authorization rule", { selector, role, user, accept } );
134
106
 
135
107
  const node = this.selectNode( selector );
136
108
 
@@ -154,7 +126,7 @@ module.exports = function() {
154
126
  removeRule( rule ) {
155
127
  const { selector, role, user, accept } = rule;
156
128
 
157
- DebugLog( "removing authorization rule", { selector, role, user, accept } );
129
+ logDebug( "removing authorization rule", { selector, role, user, accept } );
158
130
 
159
131
  const node = this.selectNode( selector, false );
160
132
 
@@ -197,7 +169,7 @@ module.exports = function() {
197
169
  }
198
170
  } );
199
171
  } catch ( cause ) {
200
- AlertLog( cause.message );
172
+ logAlert( cause.message );
201
173
  return false;
202
174
  }
203
175
 
@@ -241,7 +213,7 @@ module.exports = function() {
241
213
  const users = {};
242
214
  const roles = {};
243
215
 
244
- DebugLog( `restoring ${entries.length} authorization rule(s) from database` );
216
+ logDebug( `restoring ${entries.length} authorization rule(s) from database` );
245
217
 
246
218
  for ( const entry of entries ) {
247
219
  const userKey = entry.user ? entry.user.toString( "hex" ) : undefined;
@@ -279,7 +251,7 @@ module.exports = function() {
279
251
  loadFromConfiguration( configuration ) {
280
252
  const { authorizations = {} } = configuration || {};
281
253
 
282
- DebugLog( `loading authorization(s) from configuration` );
254
+ logDebug( `loading authorization(s) from configuration` );
283
255
 
284
256
  const processLevel = ( source, prefix ) => {
285
257
  const names = Object.keys( source );
@@ -310,7 +282,7 @@ module.exports = function() {
310
282
  [isRole ? "role" : "user"]: id,
311
283
  } );
312
284
  } else {
313
- AlertLog( `invalid user/role selector in ${key || "rule"} on ${name}` );
285
+ logAlert( `invalid user/role selector in ${key || "rule"} on ${name}` );
314
286
  }
315
287
  }
316
288
  }
package/config/auth.js CHANGED
@@ -3,6 +3,7 @@
3
3
  module.exports = function() {
4
4
  return {
5
5
  auth: {
6
+ prefix: "/api/auth",
6
7
  strategies: {
7
8
  // local: this.runtime.services.AuthStrategies.generateLocal()
8
9
  },
@@ -10,6 +11,10 @@ module.exports = function() {
10
11
  // "feature.export.pdf": "@customers"
11
12
  // "feature.export.text": "@customers,@testers"
12
13
  },
14
+ roles: [
15
+ // "customers",
16
+ // "testers",
17
+ ],
13
18
  }
14
19
  };
15
20
  };