@nymphjs/tilmeld 1.0.0-beta.11 → 1.0.0-beta.111

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 (83) hide show
  1. package/CHANGELOG.md +504 -0
  2. package/README.md +15 -2
  3. package/dist/AbleObject.d.ts +15 -0
  4. package/dist/AbleObject.js +18 -6
  5. package/dist/AbleObject.js.map +1 -1
  6. package/dist/Group.d.ts +182 -15
  7. package/dist/Group.js +571 -191
  8. package/dist/Group.js.map +1 -1
  9. package/dist/Group.test.js +86 -13
  10. package/dist/Group.test.js.map +1 -1
  11. package/dist/Tilmeld.d.ts +241 -12
  12. package/dist/Tilmeld.js +657 -257
  13. package/dist/Tilmeld.js.map +1 -1
  14. package/dist/Tilmeld.types.d.ts +5 -5
  15. package/dist/Tilmeld.types.js +1 -2
  16. package/dist/User.d.ts +396 -22
  17. package/dist/User.js +1386 -367
  18. package/dist/User.js.map +1 -1
  19. package/dist/User.test.js +133 -13
  20. package/dist/User.test.js.map +1 -1
  21. package/dist/conf/d.d.ts +306 -7
  22. package/dist/conf/d.js +1 -2
  23. package/dist/conf/defaults.d.ts +1 -1
  24. package/dist/conf/defaults.js +196 -141
  25. package/dist/conf/defaults.js.map +1 -1
  26. package/dist/conf/index.d.ts +2 -2
  27. package/dist/conf/index.js +2 -8
  28. package/dist/conf/index.js.map +1 -1
  29. package/dist/enforceTilmeld.d.ts +3 -0
  30. package/dist/enforceTilmeld.js +18 -0
  31. package/dist/enforceTilmeld.js.map +1 -0
  32. package/dist/errors/AccessControlError.d.ts +2 -1
  33. package/dist/errors/AccessControlError.js +3 -6
  34. package/dist/errors/AccessControlError.js.map +1 -1
  35. package/dist/errors/BadDataError.d.ts +2 -1
  36. package/dist/errors/BadDataError.js +3 -6
  37. package/dist/errors/BadDataError.js.map +1 -1
  38. package/dist/errors/BadEmailError.d.ts +2 -1
  39. package/dist/errors/BadEmailError.js +3 -6
  40. package/dist/errors/BadEmailError.js.map +1 -1
  41. package/dist/errors/BadUsernameError.d.ts +2 -1
  42. package/dist/errors/BadUsernameError.js +3 -6
  43. package/dist/errors/BadUsernameError.js.map +1 -1
  44. package/dist/errors/CouldNotChangeDefaultPrimaryGroupError.js +1 -5
  45. package/dist/errors/CouldNotChangeDefaultPrimaryGroupError.js.map +1 -1
  46. package/dist/errors/EmailChangeRateLimitExceededError.js +1 -5
  47. package/dist/errors/EmailChangeRateLimitExceededError.js.map +1 -1
  48. package/dist/errors/index.d.ts +6 -6
  49. package/dist/errors/index.js +6 -22
  50. package/dist/errors/index.js.map +1 -1
  51. package/dist/index.d.ts +12 -10
  52. package/dist/index.js +17 -35
  53. package/dist/index.js.map +1 -1
  54. package/dist/testArtifacts.d.ts +19 -0
  55. package/dist/testArtifacts.js +920 -0
  56. package/dist/testArtifacts.js.map +1 -0
  57. package/dist/tilmeldJoiProps.d.ts +3 -3
  58. package/dist/tilmeldJoiProps.js +13 -18
  59. package/dist/tilmeldJoiProps.js.map +1 -1
  60. package/jest.config.js +11 -2
  61. package/package.json +32 -31
  62. package/src/AbleObject.ts +2 -2
  63. package/src/Group.test.ts +107 -6
  64. package/src/Group.ts +683 -224
  65. package/src/Tilmeld.ts +450 -262
  66. package/src/Tilmeld.types.ts +5 -5
  67. package/src/User.test.ts +163 -7
  68. package/src/User.ts +1628 -454
  69. package/src/conf/d.ts +83 -17
  70. package/src/conf/defaults.ts +172 -109
  71. package/src/conf/index.ts +2 -2
  72. package/src/enforceTilmeld.ts +20 -0
  73. package/src/errors/AccessControlError.ts +4 -2
  74. package/src/errors/BadDataError.ts +4 -2
  75. package/src/errors/BadEmailError.ts +4 -2
  76. package/src/errors/BadUsernameError.ts +4 -2
  77. package/src/errors/index.ts +6 -6
  78. package/src/index.ts +14 -10
  79. package/src/testArtifacts.ts +1485 -0
  80. package/src/tilmeldJoiProps.ts +8 -23
  81. package/src/type/locutus.d.ts +3 -0
  82. package/tsconfig.json +5 -3
  83. package/typedoc.json +4 -0
@@ -1,5 +1,5 @@
1
- import Group, { GroupData } from './Group';
2
- import User, { UserData } from './User';
1
+ import Group, { GroupData } from './Group.js';
2
+ import User, { UserData } from './User.js';
3
3
 
4
4
  export type AccessControlData = {
5
5
  user?: User & UserData;
@@ -7,7 +7,7 @@ export type AccessControlData = {
7
7
  acUser?: number;
8
8
  acGroup?: number;
9
9
  acOther?: number;
10
- acFull?: ((User & UserData) | (Group & GroupData))[];
11
- acWrite?: ((User & UserData) | (Group & GroupData))[];
12
- acRead?: ((User & UserData) | (Group & GroupData))[];
10
+ acFull?: string[];
11
+ acWrite?: string[];
12
+ acRead?: string[];
13
13
  };
package/src/User.test.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { SQLite3Driver } from '@nymphjs/driver-sqlite3';
2
- import { Nymph } from '@nymphjs/nymph';
2
+ import { Nymph, EntityUniqueConstraintError } from '@nymphjs/nymph';
3
3
 
4
- import Tilmeld from './Tilmeld';
5
- import defaults from './conf/defaults';
4
+ import Tilmeld from './Tilmeld.js';
5
+ import defaults from './conf/defaults.js';
6
+ import { AccessControlError } from './errors/index.js';
6
7
 
7
8
  const tilmeld = new Tilmeld({
8
9
  appName: 'My App',
@@ -11,17 +12,21 @@ const tilmeld = new Tilmeld({
11
12
  cookiePath: '/',
12
13
  setupPath: '/user',
13
14
  emailUsernames: false,
15
+ domainSupport: true,
14
16
  verifyRedirect: 'http://localhost:8080',
15
17
  verifyChangeRedirect: 'http://localhost:8080',
16
18
  cancelChangeRedirect: 'http://localhost:8080',
17
19
  jwtSecret: 'shhhhh',
20
+ sendEmail: async (_tilmeld, _options, _user) => {
21
+ return true;
22
+ },
18
23
  });
19
- const _nymph = new Nymph(
24
+ const nymph = new Nymph(
20
25
  {},
21
26
  new SQLite3Driver({
22
27
  filename: ':memory:',
23
28
  }),
24
- tilmeld
29
+ tilmeld,
25
30
  );
26
31
 
27
32
  const User = tilmeld.User;
@@ -44,7 +49,7 @@ describe('User', () => {
44
49
  const validUser = await makeNewUser();
45
50
 
46
51
  expect(() => {
47
- defaults.validatorUser(validUser);
52
+ defaults.validatorUser({ config: defaults } as Tilmeld, validUser);
48
53
  }).not.toThrow();
49
54
  });
50
55
 
@@ -55,7 +60,158 @@ describe('User', () => {
55
60
  invalidUser.unknown = 'I should cause an error.';
56
61
 
57
62
  expect(() => {
58
- defaults.validatorUser(invalidUser);
63
+ defaults.validatorUser({ config: defaults } as Tilmeld, invalidUser);
59
64
  }).toThrow('Invalid User: "unknown" is not allowed');
60
65
  });
66
+
67
+ it("doesn't allow duplicate usernames", async () => {
68
+ const transaction = 'duplicate-usernames';
69
+ const tnymph = await nymph.startTransaction(transaction);
70
+ const TUser = tnymph.getEntityClass(User.class) as typeof User;
71
+ const newUserA = await TUser.factory();
72
+
73
+ newUserA.username = 'new-user';
74
+ newUserA.email = 'newusera@localhost';
75
+ newUserA.nameFirst = 'New';
76
+ newUserA.nameLast = 'User';
77
+ newUserA.name = 'New User';
78
+ newUserA.$password('password');
79
+
80
+ const newUserB = await TUser.factory();
81
+
82
+ newUserB.username = 'new-user';
83
+ newUserB.email = 'newuserb@localhost';
84
+ newUserB.nameFirst = 'New';
85
+ newUserB.nameLast = 'User';
86
+ newUserB.name = 'New User';
87
+ newUserB.$password('password');
88
+
89
+ const promises = [newUserA.$saveSkipAC(), newUserB.$saveSkipAC()];
90
+
91
+ try {
92
+ await Promise.all(promises);
93
+
94
+ throw new Error("Shouldn't get here because of unique constraint.");
95
+ } catch (e: any) {
96
+ expect(e).toBeInstanceOf(EntityUniqueConstraintError);
97
+ }
98
+
99
+ await Promise.allSettled(promises);
100
+ await tnymph.rollback(transaction);
101
+ });
102
+
103
+ it("doesn't allow duplicate emails", async () => {
104
+ const transaction = 'duplicate-usernames';
105
+ const tnymph = await nymph.startTransaction(transaction);
106
+ const TUser = tnymph.getEntityClass(User.class) as typeof User;
107
+ const newUserA = await TUser.factory();
108
+
109
+ newUserA.username = 'new-user-a';
110
+ newUserA.email = 'newuser@localhost';
111
+ newUserA.nameFirst = 'New';
112
+ newUserA.nameLast = 'User';
113
+ newUserA.name = 'New User';
114
+ newUserA.$password('password');
115
+
116
+ const newUserB = await TUser.factory();
117
+
118
+ newUserB.username = 'new-user-b';
119
+ newUserB.email = 'newuser@localhost';
120
+ newUserB.nameFirst = 'New';
121
+ newUserB.nameLast = 'User';
122
+ newUserB.name = 'New User';
123
+ newUserB.$password('password');
124
+
125
+ const promises = [newUserA.$saveSkipAC(), newUserB.$saveSkipAC()];
126
+
127
+ try {
128
+ await Promise.all(promises);
129
+
130
+ throw new Error("Shouldn't get here because of unique constraint.");
131
+ } catch (e: any) {
132
+ expect(e).toBeInstanceOf(EntityUniqueConstraintError);
133
+ }
134
+
135
+ await Promise.allSettled(promises);
136
+ await tnymph.rollback(transaction);
137
+ });
138
+
139
+ it('allows a domain user', async () => {
140
+ const domainAdmin = await User.factory();
141
+
142
+ domainAdmin.username = 'admin';
143
+ domainAdmin.email = 'admin@localhost';
144
+ domainAdmin.nameFirst = 'Admin';
145
+ domainAdmin.nameLast = 'User';
146
+ domainAdmin.name = 'Admin User';
147
+ domainAdmin.$password('password');
148
+ domainAdmin.$grant('tilmeld/domain/example.com/admin');
149
+
150
+ expect(await domainAdmin.$saveSkipAC()).toEqual(true);
151
+
152
+ // Log in the domain admin.
153
+ await tilmeld.fillSession(domainAdmin);
154
+
155
+ const domainUser = await User.factory();
156
+
157
+ domainUser.username = 'new-user@example.com';
158
+ domainUser.email = 'newuser@localhost';
159
+ domainUser.nameFirst = 'New';
160
+ domainUser.nameLast = 'User';
161
+ domainUser.name = 'New User';
162
+ domainUser.$password('password');
163
+
164
+ expect(await domainUser.$save()).toEqual(true);
165
+
166
+ tilmeld.clearSession();
167
+
168
+ for (const user of [domainAdmin, domainUser]) {
169
+ if (user.guid != null) {
170
+ expect(await user.$deleteSkipAC()).toEqual(true);
171
+ }
172
+ }
173
+ });
174
+
175
+ it('disallows a domain user with no admin permission', async () => {
176
+ const domainAdmin = await User.factory();
177
+
178
+ domainAdmin.username = 'admin';
179
+ domainAdmin.email = 'admin@localhost';
180
+ domainAdmin.nameFirst = 'Admin';
181
+ domainAdmin.nameLast = 'User';
182
+ domainAdmin.name = 'Admin User';
183
+ domainAdmin.$password('password');
184
+ domainAdmin.$grant('tilmeld/domain/example.com/admin');
185
+
186
+ expect(await domainAdmin.$saveSkipAC()).toEqual(true);
187
+
188
+ // Log in the domain admin.
189
+ await tilmeld.fillSession(domainAdmin);
190
+
191
+ const domainUser = await User.factory();
192
+
193
+ // The wrong domain name.
194
+ domainUser.username = 'new-user@example.net';
195
+ domainUser.email = 'newuser@localhost';
196
+ domainUser.nameFirst = 'New';
197
+ domainUser.nameLast = 'User';
198
+ domainUser.name = 'New User';
199
+ domainUser.$password('password');
200
+
201
+ try {
202
+ await domainUser.$save();
203
+
204
+ throw new Error("Shouldn't get here because of access control.");
205
+ } catch (e: any) {
206
+ expect(e).toBeInstanceOf(AccessControlError);
207
+ }
208
+
209
+ tilmeld.clearSession();
210
+
211
+ for (const user of [domainAdmin, domainUser]) {
212
+ if (user.guid != null) {
213
+ expect(await user.$deleteSkipAC()).toEqual(true);
214
+ }
215
+ }
216
+ });
61
217
  });