@nymphjs/tilmeld 1.0.0-alpha.2 → 1.0.0-alpha.23

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/src/User.test.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { SQLite3Driver } from '@nymphjs/driver-sqlite3';
2
- import nymph from '@nymphjs/nymph';
2
+ import { Nymph } from '@nymphjs/nymph';
3
3
 
4
4
  import Tilmeld from './Tilmeld';
5
5
  import defaults from './conf/defaults';
@@ -16,7 +16,7 @@ const tilmeld = new Tilmeld({
16
16
  cancelChangeRedirect: 'http://localhost:8080',
17
17
  jwtSecret: 'shhhhh',
18
18
  });
19
- nymph.init(
19
+ const _nymph = new Nymph(
20
20
  {},
21
21
  new SQLite3Driver({
22
22
  filename: ':memory:',
@@ -40,6 +40,14 @@ describe('User', () => {
40
40
  return newUser;
41
41
  }
42
42
 
43
+ it('new user passes validation', async () => {
44
+ const validUser = await makeNewUser();
45
+
46
+ expect(() => {
47
+ defaults.validatorUser(validUser);
48
+ }).not.toThrow();
49
+ });
50
+
43
51
  it("doesn't allow unknown keys", async () => {
44
52
  const invalidUser = await makeNewUser();
45
53
 
package/src/User.ts CHANGED
@@ -14,9 +14,9 @@ import sha256 from 'crypto-js/sha256';
14
14
  import md5 from 'crypto-js/md5';
15
15
  import { difference } from 'lodash';
16
16
 
17
+ import type Tilmeld from './Tilmeld';
17
18
  import AbleObject from './AbleObject';
18
19
  import Group, { GroupData } from './Group';
19
- import Tilmeld from './Tilmeld';
20
20
  import {
21
21
  BadDataError,
22
22
  BadEmailError,
@@ -126,11 +126,20 @@ export type UserData = {
126
126
  passwordTemp?: string;
127
127
  };
128
128
 
129
+ /**
130
+ * A user data model.
131
+ *
132
+ * Written by Hunter Perrin for SciActive.
133
+ *
134
+ * @author Hunter Perrin <hperrin@gmail.com>
135
+ * @copyright SciActive Inc
136
+ * @see http://nymph.io/
137
+ */
129
138
  export default class User extends AbleObject<UserData> {
130
139
  /**
131
140
  * The instance of Tilmeld to use for queries.
132
141
  */
133
- public static tilmeld: Tilmeld;
142
+ static tilmeld: Tilmeld;
134
143
  static ETYPE = 'tilmeld_user';
135
144
  static class = 'User';
136
145
 
@@ -162,7 +171,7 @@ export default class User extends AbleObject<UserData> {
162
171
  ];
163
172
  private static DEFAULT_ALLOWLIST_DATA: string[] = [];
164
173
 
165
- protected $clientEnabledMethods = User.DEFAULT_CLIENT_ENABLED_METHODS;
174
+ protected $clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
166
175
  public static clientEnabledStaticMethods = [
167
176
  'current',
168
177
  'loginUser',
@@ -170,9 +179,9 @@ export default class User extends AbleObject<UserData> {
170
179
  'recover',
171
180
  'getClientConfig',
172
181
  ];
173
- protected $privateData = User.DEFAULT_PRIVATE_DATA;
174
- public static searchRestrictedData = User.DEFAULT_PRIVATE_DATA;
175
- protected $allowlistData? = User.DEFAULT_ALLOWLIST_DATA;
182
+ protected $privateData = [...User.DEFAULT_PRIVATE_DATA];
183
+ public static searchRestrictedData = [...User.DEFAULT_PRIVATE_DATA];
184
+ protected $allowlistData? = [...User.DEFAULT_ALLOWLIST_DATA];
176
185
  protected $allowlistTags?: string[] = [];
177
186
 
178
187
  /**
@@ -570,9 +579,9 @@ export default class User extends AbleObject<UserData> {
570
579
  const tilmeld = this.$nymph.tilmeld as Tilmeld;
571
580
  let user = givenUser ?? tilmeld.User.current();
572
581
 
573
- this.$clientEnabledMethods = User.DEFAULT_CLIENT_ENABLED_METHODS;
574
- this.$privateData = User.DEFAULT_PRIVATE_DATA;
575
- this.$allowlistData = User.DEFAULT_ALLOWLIST_DATA;
582
+ this.$clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
583
+ this.$privateData = [...User.DEFAULT_PRIVATE_DATA];
584
+ this.$allowlistData = [...User.DEFAULT_ALLOWLIST_DATA];
576
585
 
577
586
  if (tilmeld.config.emailUsernames) {
578
587
  this.$privateData.push('username');
@@ -1158,7 +1167,9 @@ export default class User extends AbleObject<UserData> {
1158
1167
 
1159
1168
  // Start transaction.
1160
1169
  const transaction = 'tilmeld-register-' + nanoid();
1170
+ const nymph = this.$nymph;
1161
1171
  const tnymph = await this.$nymph.startTransaction(transaction);
1172
+ this.$nymph = tnymph;
1162
1173
 
1163
1174
  try {
1164
1175
  // Add primary group.
@@ -1182,6 +1193,7 @@ export default class User extends AbleObject<UserData> {
1182
1193
  }
1183
1194
  if (!(await generatedPrimaryGroup.$saveSkipAC())) {
1184
1195
  await tnymph.rollback(transaction);
1196
+ this.$nymph = nymph;
1185
1197
  return {
1186
1198
  result: false,
1187
1199
  loggedin: false,
@@ -1282,6 +1294,7 @@ export default class User extends AbleObject<UserData> {
1282
1294
  generatedPrimaryGroup.user = this;
1283
1295
  if (!(await generatedPrimaryGroup.$saveSkipAC())) {
1284
1296
  await tnymph.rollback(transaction);
1297
+ this.$nymph = nymph;
1285
1298
  return {
1286
1299
  result: false,
1287
1300
  loggedin: false,
@@ -1317,6 +1330,7 @@ export default class User extends AbleObject<UserData> {
1317
1330
  loggedin = true;
1318
1331
  }
1319
1332
  await tnymph.commit(transaction);
1333
+ this.$nymph = nymph;
1320
1334
  return {
1321
1335
  result: true,
1322
1336
  loggedin,
@@ -1324,6 +1338,7 @@ export default class User extends AbleObject<UserData> {
1324
1338
  };
1325
1339
  } else {
1326
1340
  await tnymph.rollback(transaction);
1341
+ this.$nymph = nymph;
1327
1342
  return {
1328
1343
  result: false,
1329
1344
  loggedin: false,
@@ -1332,6 +1347,7 @@ export default class User extends AbleObject<UserData> {
1332
1347
  }
1333
1348
  } catch (e: any) {
1334
1349
  await tnymph.rollback(transaction);
1350
+ this.$nymph = nymph;
1335
1351
  throw e;
1336
1352
  }
1337
1353
  }
@@ -1532,7 +1548,9 @@ export default class User extends AbleObject<UserData> {
1532
1548
 
1533
1549
  // Start transaction.
1534
1550
  const transaction = 'tilmeld-save-' + nanoid();
1551
+ const nymph = this.$nymph;
1535
1552
  const tnymph = await this.$nymph.startTransaction(transaction);
1553
+ this.$nymph = tnymph;
1536
1554
 
1537
1555
  if (
1538
1556
  this.$data.group != null &&
@@ -1549,6 +1567,7 @@ export default class User extends AbleObject<UserData> {
1549
1567
  await this.$data.group.$saveSkipAC();
1550
1568
  } catch (e: any) {
1551
1569
  await tnymph.rollback(transaction);
1570
+ this.$nymph = nymph;
1552
1571
  throw e;
1553
1572
  }
1554
1573
  }
@@ -1562,6 +1581,7 @@ export default class User extends AbleObject<UserData> {
1562
1581
  ret = await super.$save();
1563
1582
  } catch (e: any) {
1564
1583
  await tnymph.rollback(transaction);
1584
+ this.$nymph = nymph;
1565
1585
  throw e;
1566
1586
  }
1567
1587
  if (ret) {
@@ -1572,6 +1592,7 @@ export default class User extends AbleObject<UserData> {
1572
1592
  this.guid = preGuid;
1573
1593
  this.cdate = preCdate;
1574
1594
  this.mdate = preMdate;
1595
+ this.$nymph = nymph;
1575
1596
  throw new Error("Couldn't send verification email.");
1576
1597
  }
1577
1598
  }
@@ -1587,6 +1608,7 @@ export default class User extends AbleObject<UserData> {
1587
1608
  } else {
1588
1609
  await tnymph.rollback(transaction);
1589
1610
  }
1611
+ this.$nymph = nymph;
1590
1612
  return ret;
1591
1613
  }
1592
1614
 
package/src/conf/d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { EmailOptions } from 'email-templates';
2
+
2
3
  import type Tilmeld from '../Tilmeld';
3
4
  import Group, { GroupData } from '../Group';
4
5
  import User, { UserData } from '../User';
@@ -64,6 +65,35 @@ export interface Config {
64
65
  * a concern. Same risks as user search if generatePrimary is true.)
65
66
  */
66
67
  enableGroupSearch: boolean;
68
+ /**
69
+ * A list of UIDs that can be read from the client by anyone. (getUID)
70
+ *
71
+ * Note: If you'd like to limit the access to logged in users, give them an
72
+ * ability like "uid/get/nameofuid".
73
+ */
74
+ clientReadableUIDs: string[];
75
+ /**
76
+ * A list of UIDs that can be created from the client by anyone. (newUID)
77
+ *
78
+ * Inclusion in this list implies inclusion in clientReadableUIDs.
79
+ *
80
+ * Note: If you'd like to limit the access to logged in users, give them an
81
+ * ability like "uid/new/nameofuid".
82
+ */
83
+ clientEnabledUIDs: string[];
84
+ /**
85
+ * A list of UIDs that can be set from the client by anyone. (setUID,
86
+ * renameUID)
87
+ *
88
+ * Inclusion in this list implies inclusion in clientReadableUIDs and
89
+ * clientEnabledUIDs.
90
+ *
91
+ * Note: There is no way to run renameUID from the client.
92
+ *
93
+ * Note: If you'd like to limit the access to logged in users, give them an
94
+ * ability like "uid/set/nameofuid".
95
+ */
96
+ clientSetabledUIDs: string[];
67
97
  /**
68
98
  * These will be the available fields for users. (Some fields, like username,
69
99
  * can't be excluded.)
@@ -1,12 +1,12 @@
1
+ import { nymphJoiProps } from '@nymphjs/nymph';
1
2
  import path from 'path';
2
3
  import jwt from 'jsonwebtoken';
3
4
  import { nanoid } from 'nanoid';
4
- import Email, { EmailOptions } from 'email-templates';
5
+ import Email from 'email-templates';
5
6
  import Joi from 'joi';
6
7
 
7
- import Tilmeld from '../Tilmeld';
8
8
  import { Config } from './d';
9
- import User, { UserData } from '../User';
9
+ import User from '../User';
10
10
  import Group from '../Group';
11
11
 
12
12
  export default {
@@ -21,6 +21,9 @@ export default {
21
21
  allowUsernameChange: true,
22
22
  enableUserSearch: false,
23
23
  enableGroupSearch: false,
24
+ clientReadableUIDs: [],
25
+ clientEnabledUIDs: [],
26
+ clientSetabledUIDs: [],
24
27
  userFields: ['name', 'email', 'phone'],
25
28
  regFields: ['name', 'email'],
26
29
  verifyEmail: true,
@@ -155,29 +158,8 @@ export default {
155
158
  Joi.attempt(
156
159
  group.$getValidatable(),
157
160
  Joi.object().keys({
158
- guid: Joi.alternatives()
159
- .try(
160
- Joi.any().only().allow(null),
161
- Joi.string().trim(false).length(24).hex()
162
- )
163
- .required(),
164
- cdate: Joi.alternatives()
165
- .try(Joi.any().only().allow(null), Joi.number())
166
- .required(),
167
- mdate: Joi.alternatives()
168
- .try(Joi.any().only().allow(null), Joi.number())
169
- .required(),
170
- tags: Joi.array()
171
- .items(
172
- Joi.string()
173
- .pattern(/[\x01-\x1F\x7F]/, {
174
- name: 'control characters',
175
- invert: true,
176
- })
177
- .min(1)
178
- )
179
- .required(),
180
- groupname: Joi.string().trim(false).min(1).required(),
161
+ ...nymphJoiProps,
162
+ groupname: Joi.string().trim(false).required(),
181
163
  enabled: Joi.boolean().required(),
182
164
  email: Joi.string()
183
165
  .trim(false)
@@ -189,7 +171,6 @@ export default {
189
171
  name: 'control characters',
190
172
  invert: true,
191
173
  })
192
- .min(1)
193
174
  .max(512)
194
175
  .required(),
195
176
  avatar: Joi.string()
@@ -199,7 +180,6 @@ export default {
199
180
  name: 'control characters',
200
181
  invert: true,
201
182
  })
202
- .min(1)
203
183
  .max(1024),
204
184
  phone: Joi.string()
205
185
  .trim(false)
@@ -212,7 +192,6 @@ export default {
212
192
  name: 'control characters',
213
193
  invert: true,
214
194
  })
215
- .min(1)
216
195
  .max(256)
217
196
  ),
218
197
  defaultPrimary: Joi.boolean(),
@@ -226,29 +205,8 @@ export default {
226
205
  Joi.attempt(
227
206
  user.$getValidatable(),
228
207
  Joi.object().keys({
229
- guid: Joi.alternatives()
230
- .try(
231
- Joi.any().only().allow(null),
232
- Joi.string().trim(false).length(24).hex()
233
- )
234
- .required(),
235
- cdate: Joi.alternatives()
236
- .try(Joi.any().only().allow(null), Joi.number())
237
- .required(),
238
- mdate: Joi.alternatives()
239
- .try(Joi.any().only().allow(null), Joi.number())
240
- .required(),
241
- tags: Joi.array()
242
- .items(
243
- Joi.string()
244
- .pattern(/[\x01-\x1F\x7F]/, {
245
- name: 'control characters',
246
- invert: true,
247
- })
248
- .min(1)
249
- )
250
- .required(),
251
- username: Joi.string().trim(false).min(1).required(),
208
+ ...nymphJoiProps,
209
+ username: Joi.string().trim(false).required(),
252
210
  enabled: Joi.boolean().required(),
253
211
  email: Joi.string()
254
212
  .trim(false)
@@ -260,7 +218,6 @@ export default {
260
218
  name: 'control characters',
261
219
  invert: true,
262
220
  })
263
- .min(1)
264
221
  .max(512)
265
222
  .required(),
266
223
  nameMiddle: Joi.string()
@@ -269,7 +226,6 @@ export default {
269
226
  name: 'control characters',
270
227
  invert: true,
271
228
  })
272
- .min(1)
273
229
  .max(512),
274
230
  nameLast: Joi.string()
275
231
  .trim(false)
@@ -277,7 +233,6 @@ export default {
277
233
  name: 'control characters',
278
234
  invert: true,
279
235
  })
280
- .min(1)
281
236
  .max(512),
282
237
  name: Joi.string()
283
238
  .trim(false)
@@ -285,7 +240,6 @@ export default {
285
240
  name: 'control characters',
286
241
  invert: true,
287
242
  })
288
- .min(1)
289
243
  .max(512)
290
244
  .required(),
291
245
  avatar: Joi.string()
@@ -295,7 +249,6 @@ export default {
295
249
  name: 'control characters',
296
250
  invert: true,
297
251
  })
298
- .min(1)
299
252
  .max(1024),
300
253
  phone: Joi.string()
301
254
  .trim(false)
@@ -308,7 +261,6 @@ export default {
308
261
  name: 'control characters',
309
262
  invert: true,
310
263
  })
311
- .min(1)
312
264
  .max(256)
313
265
  ),
314
266
  inheritAbilities: Joi.boolean(),
@@ -348,8 +300,8 @@ export default {
348
300
  })
349
301
  .length(10),
350
302
  recoverSecretDate: Joi.number(),
351
- salt: Joi.string().trim(false).min(1),
352
- password: Joi.string().trim(false).min(1).required(),
303
+ salt: Joi.string().trim(false),
304
+ password: Joi.string().trim(false).required(),
353
305
  }),
354
306
  'Invalid User: '
355
307
  );
package/src/index.ts CHANGED
@@ -11,10 +11,12 @@ export { Group };
11
11
 
12
12
  import Tilmeld from './Tilmeld';
13
13
  export { Tilmeld };
14
- export default Tilmeld;
15
14
 
16
15
  export * from './Tilmeld.types';
17
16
 
17
+ import tilmeldJoiProps from './tilmeldJoiProps';
18
+ export { tilmeldJoiProps };
19
+
18
20
  export * from './User';
19
21
  import User from './User';
20
22
  export { User };
@@ -0,0 +1,46 @@
1
+ import { TilmeldAccessLevels } from '@nymphjs/nymph';
2
+ import Joi from 'joi';
3
+
4
+ import User from './User';
5
+ import Group from './Group';
6
+
7
+ export default {
8
+ user: Joi.object().instance(User),
9
+ group: Joi.object().instance(Group),
10
+ acUser: Joi.number().valid(
11
+ TilmeldAccessLevels.NO_ACCESS,
12
+ TilmeldAccessLevels.READ_ACCESS,
13
+ TilmeldAccessLevels.WRITE_ACCESS,
14
+ TilmeldAccessLevels.FULL_ACCESS
15
+ ),
16
+ acGroup: Joi.number().valid(
17
+ TilmeldAccessLevels.NO_ACCESS,
18
+ TilmeldAccessLevels.READ_ACCESS,
19
+ TilmeldAccessLevels.WRITE_ACCESS,
20
+ TilmeldAccessLevels.FULL_ACCESS
21
+ ),
22
+ acOther: Joi.number().valid(
23
+ TilmeldAccessLevels.NO_ACCESS,
24
+ TilmeldAccessLevels.READ_ACCESS,
25
+ TilmeldAccessLevels.WRITE_ACCESS,
26
+ TilmeldAccessLevels.FULL_ACCESS
27
+ ),
28
+ acRead: Joi.array().items(
29
+ Joi.alternatives().try(
30
+ Joi.object().instance(User),
31
+ Joi.object().instance(Group)
32
+ )
33
+ ),
34
+ acWrite: Joi.array().items(
35
+ Joi.alternatives().try(
36
+ Joi.object().instance(User),
37
+ Joi.object().instance(Group)
38
+ )
39
+ ),
40
+ acFull: Joi.array().items(
41
+ Joi.alternatives().try(
42
+ Joi.object().instance(User),
43
+ Joi.object().instance(Group)
44
+ )
45
+ ),
46
+ };