@semapps/auth 0.7.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
package/mixins/auth.js CHANGED
@@ -19,21 +19,23 @@ const AuthMixin = {
19
19
  accountsDataset: 'settings',
20
20
  podProvider: false
21
21
  },
22
- dependencies: ['api', 'webid'],
22
+ dependencies: ['api'],
23
23
  async created() {
24
24
  const { jwtPath, reservedUsernames, accountsDataset, podProvider } = this.settings;
25
25
 
26
- this.broker.createService(AuthJWTService, {
26
+ this.broker.createService({
27
+ mixins: [AuthJWTService],
27
28
  settings: { jwtPath }
28
29
  });
29
30
 
30
- this.broker.createService(AuthAccountService, {
31
+ this.broker.createService({
32
+ mixins: [AuthAccountService],
31
33
  settings: { reservedUsernames },
32
34
  adapter: new TripleStoreAdapter({ type: 'AuthAccount', dataset: accountsDataset })
33
35
  });
34
36
 
35
37
  if (podProvider) {
36
- this.broker.createService(CapabilitiesService, { settings: { path: this.settings.capabilitiesPath } });
38
+ this.broker.createService({ mixins: [CapabilitiesService], settings: { path: this.settings.capabilitiesPath } });
37
39
  }
38
40
  },
39
41
  async started() {
@@ -51,7 +53,9 @@ const AuthMixin = {
51
53
 
52
54
  this.passport.use(this.passportId, this.strategy);
53
55
 
54
- for (const route of this.getApiRoutes()) {
56
+ const { pathname: basePath } = new URL(this.settings.baseUrl);
57
+
58
+ for (const route of this.getApiRoutes(basePath)) {
55
59
  await this.broker.call('api.addRoute', { route });
56
60
  }
57
61
  },
@@ -1,3 +1,4 @@
1
+ const path = require('path');
1
2
  const session = require('express-session');
2
3
  const AuthMixin = require('./auth');
3
4
  const saveRedirectUrl = require('../middlewares/saveRedirectUrl');
@@ -33,8 +34,7 @@ const AuthSSOMixin = {
33
34
  webId = accountData.webId;
34
35
  newUser = false;
35
36
 
36
- // TODO update account with recent information
37
- // await ctx.call('webid.edit', profileData, { meta: { webId } });
37
+ // TODO update account with recent profileData information
38
38
 
39
39
  ctx.emit('auth.connected', { webId, accountData, ssoData }, { meta: { webId: null, dataset: null } });
40
40
  } else {
@@ -47,7 +47,7 @@ const AuthSSOMixin = {
47
47
  email: profileData.email,
48
48
  username: profileData.username
49
49
  });
50
- webId = await ctx.call('webid.create', this.pickWebIdData({ nick: accountData.username, ...profileData }));
50
+ webId = await ctx.call('webid.createWebId', this.pickWebIdData({ nick: accountData.username, ...profileData }));
51
51
  newUser = true;
52
52
 
53
53
  // Link the webId with the account
@@ -66,11 +66,11 @@ const AuthSSOMixin = {
66
66
  }
67
67
  },
68
68
  methods: {
69
- getApiRoutes() {
69
+ getApiRoutes(basePath) {
70
70
  const sessionMiddleware = session({ secret: this.settings.sessionSecret, maxAge: null });
71
71
  return [
72
72
  {
73
- path: '/auth',
73
+ path: path.join(basePath, '/auth'),
74
74
  name: 'auth',
75
75
  use: [sessionMiddleware, this.passport.initialize(), this.passport.session()],
76
76
  aliases: {
@@ -78,7 +78,7 @@ const AuthSSOMixin = {
78
78
  }
79
79
  },
80
80
  {
81
- path: '/auth/logout',
81
+ path: path.join(basePath, '/auth/logout'),
82
82
  name: 'auth-logout',
83
83
  use: [sessionMiddleware, this.passport.initialize(), this.passport.session()],
84
84
  aliases: {
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@semapps/auth",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "Authentification module for SemApps",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Virtual Assembly",
7
7
  "dependencies": {
8
- "@semapps/ldp": "0.7.0",
9
- "@semapps/middlewares": "0.7.0",
10
- "@semapps/mime-types": "0.7.0",
11
- "@semapps/triplestore": "0.7.0",
8
+ "@semapps/ldp": "0.8.1",
9
+ "@semapps/middlewares": "0.8.1",
10
+ "@semapps/mime-types": "0.8.1",
11
+ "@semapps/triplestore": "0.8.1",
12
12
  "bcrypt": "^5.0.1",
13
13
  "express-session": "^1.17.0",
14
14
  "jsonwebtoken": "^8.5.1",
@@ -29,5 +29,5 @@
29
29
  "engines": {
30
30
  "node": ">=14"
31
31
  },
32
- "gitHead": "793f935c61e5f4e87ac17ee1dd41a968f12678b4"
32
+ "gitHead": "c056166a50822060e229c20efd2eb6ee666fc743"
33
33
  }
@@ -88,6 +88,12 @@ module.exports = {
88
88
  const accounts = await this._find(ctx, { query: { email } });
89
89
  return accounts.length > 0;
90
90
  },
91
+ /** Overwrite find method, to filter accounts with tombstone. */
92
+ async find(ctx) {
93
+ /** @type {object[]} */
94
+ const accounts = await this._find(ctx, ctx.params);
95
+ return accounts.filter(account => !account.deletedAt);
96
+ },
91
97
  async findByUsername(ctx) {
92
98
  const { username } = ctx.params;
93
99
  const accounts = await this._find(ctx, { query: { username } });
@@ -184,6 +190,34 @@ module.exports = {
184
190
  '@id': account['@id'],
185
191
  ...params
186
192
  });
193
+ },
194
+ async deleteByWebId(ctx) {
195
+ const { webId } = ctx.params;
196
+ const account = await ctx.call('auth.account.findByWebId', { webId });
197
+
198
+ if (account) {
199
+ await this._remove(ctx, { id: account['@id'] });
200
+ return true;
201
+ }
202
+
203
+ return false;
204
+ },
205
+ // Remove email and password from an account, set deletedAt timestamp.
206
+ async setTombstone(ctx) {
207
+ const { webId } = ctx.params;
208
+ const account = await ctx.call('auth.account.findByWebId', { webId });
209
+
210
+ return await this._update(ctx, {
211
+ // Set all values to undefined...
212
+ ...Object.fromEntries(Object.keys(account).map(key => [key, null])),
213
+ '@id': account['@id'],
214
+ // ...except for
215
+ webId: account.webId,
216
+ username: account.username,
217
+ podUri: account.podUri,
218
+ // And add a deletedAt date.
219
+ deletedAt: new Date().toISOString()
220
+ });
187
221
  }
188
222
  },
189
223
  methods: {
@@ -1,9 +1,11 @@
1
+ const path = require('path');
1
2
  const { Strategy } = require('passport-local');
2
3
  const AuthMixin = require('../mixins/auth');
3
4
  const sendToken = require('../middlewares/sendToken');
4
5
  const { MoleculerError } = require('moleculer').Errors;
5
6
  const AuthMailService = require('./mail');
6
7
 
8
+ /** @type {import('moleculer').ServiceSchema} */
7
9
  const AuthLocalService = {
8
10
  name: 'auth',
9
11
  mixins: [AuthMixin],
@@ -27,13 +29,15 @@ const AuthLocalService = {
27
29
  }
28
30
  }
29
31
  },
32
+ dependencies: ['webid'],
30
33
  async created() {
31
34
  const { mail } = this.settings;
32
35
 
33
36
  this.passportId = 'local';
34
37
 
35
38
  if (mail !== false) {
36
- await this.broker.createService(AuthMailService, {
39
+ this.broker.createService({
40
+ mixins: [AuthMailService],
37
41
  settings: {
38
42
  ...mail
39
43
  }
@@ -43,6 +47,8 @@ const AuthLocalService = {
43
47
  actions: {
44
48
  async signup(ctx) {
45
49
  const { username, email, password, interactionId, ...rest } = ctx.params;
50
+ // This is going to get in our way otherwise when waiting for completions.
51
+ ctx.meta.skipObjectsWatcher = true;
46
52
 
47
53
  if (username && username.length < 2) {
48
54
  throw new Error('The username must be at least 2 characters long');
@@ -56,7 +62,7 @@ const AuthLocalService = {
56
62
  });
57
63
 
58
64
  const profileData = { nick: username, email, ...rest };
59
- const webId = await ctx.call('webid.create', this.pickWebIdData(profileData));
65
+ const webId = await ctx.call('webid.createWebId', this.pickWebIdData(profileData));
60
66
 
61
67
  // Link the webId with the account
62
68
  accountData = await ctx.call('auth.account.attachWebId', { accountUri: accountData['@id'], webId });
@@ -148,9 +154,9 @@ const AuthLocalService = {
148
154
  }
149
155
  );
150
156
  },
151
- getApiRoutes() {
157
+ getApiRoutes(basePath) {
152
158
  const loginRoute = {
153
- path: '/auth/login',
159
+ path: path.join(basePath, '/auth/login'),
154
160
  name: 'auth-login',
155
161
  use: [this.passport.initialize()],
156
162
  aliases: {
@@ -159,7 +165,7 @@ const AuthLocalService = {
159
165
  };
160
166
 
161
167
  const logoutRoute = {
162
- path: '/auth/logout',
168
+ path: path.join(basePath, '/auth/logout'),
163
169
  name: 'auth-logout',
164
170
  aliases: {
165
171
  'GET /': 'auth.logout'
@@ -167,7 +173,7 @@ const AuthLocalService = {
167
173
  };
168
174
 
169
175
  const signupRoute = {
170
- path: '/auth/signup',
176
+ path: path.join(basePath, '/auth/signup'),
171
177
  name: 'auth-signup',
172
178
  aliases: {
173
179
  'POST /': 'auth.signup'
@@ -175,7 +181,7 @@ const AuthLocalService = {
175
181
  };
176
182
 
177
183
  const formRoute = {
178
- path: '/auth',
184
+ path: path.join(basePath, '/auth'),
179
185
  name: 'auth',
180
186
  aliases: {
181
187
  'GET /': 'auth.redirectToForm'
@@ -183,14 +189,14 @@ const AuthLocalService = {
183
189
  };
184
190
 
185
191
  const resetPasswordRoute = {
186
- path: '/auth/reset_password',
192
+ path: path.join(basePath, '/auth/reset_password'),
187
193
  name: 'auth-reset-password',
188
194
  aliases: {
189
195
  'POST /': 'auth.resetPassword'
190
196
  }
191
197
  };
192
198
  const setNewPasswordRoute = {
193
- path: '/auth/new_password',
199
+ path: path.join(basePath, '/auth/new_password'),
194
200
  name: 'auth-new-password',
195
201
  aliases: {
196
202
  'POST /': 'auth.setNewPassword'
@@ -198,7 +204,7 @@ const AuthLocalService = {
198
204
  };
199
205
 
200
206
  const accountSettingsRoute = {
201
- path: '/auth/account',
207
+ path: path.join(basePath, '/auth/account'),
202
208
  name: 'auth-account',
203
209
  aliases: {
204
210
  'GET /': 'auth.account.findSettingsByWebId',