@nymphjs/tilmeld 1.0.0-beta.9 → 1.0.0-beta.90

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 (78) hide show
  1. package/CHANGELOG.md +408 -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 +140 -15
  7. package/dist/Group.js +466 -191
  8. package/dist/Group.js.map +1 -1
  9. package/dist/Group.test.js +83 -13
  10. package/dist/Group.test.js.map +1 -1
  11. package/dist/Tilmeld.d.ts +239 -12
  12. package/dist/Tilmeld.js +634 -254
  13. package/dist/Tilmeld.js.map +1 -1
  14. package/dist/Tilmeld.types.d.ts +2 -2
  15. package/dist/Tilmeld.types.js +1 -2
  16. package/dist/User.d.ts +365 -22
  17. package/dist/User.js +1265 -364
  18. package/dist/User.js.map +1 -1
  19. package/dist/User.test.js +132 -13
  20. package/dist/User.test.js.map +1 -1
  21. package/dist/conf/d.d.ts +287 -7
  22. package/dist/conf/d.js +1 -2
  23. package/dist/conf/defaults.d.ts +1 -1
  24. package/dist/conf/defaults.js +188 -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 +11 -10
  52. package/dist/index.js +16 -35
  53. package/dist/index.js.map +1 -1
  54. package/dist/tilmeldJoiProps.js +13 -18
  55. package/dist/tilmeldJoiProps.js.map +1 -1
  56. package/jest.config.js +11 -2
  57. package/package.json +34 -31
  58. package/src/AbleObject.ts +2 -2
  59. package/src/Group.test.ts +104 -6
  60. package/src/Group.ts +478 -226
  61. package/src/Tilmeld.ts +418 -254
  62. package/src/Tilmeld.types.ts +2 -2
  63. package/src/User.test.ts +163 -6
  64. package/src/User.ts +1428 -444
  65. package/src/conf/d.ts +63 -17
  66. package/src/conf/defaults.ts +162 -109
  67. package/src/conf/index.ts +2 -2
  68. package/src/enforceTilmeld.ts +20 -0
  69. package/src/errors/AccessControlError.ts +4 -2
  70. package/src/errors/BadDataError.ts +4 -2
  71. package/src/errors/BadEmailError.ts +4 -2
  72. package/src/errors/BadUsernameError.ts +4 -2
  73. package/src/errors/index.ts +6 -6
  74. package/src/index.ts +12 -10
  75. package/src/tilmeldJoiProps.ts +11 -11
  76. package/src/type/locutus.d.ts +3 -0
  77. package/tsconfig.json +5 -3
  78. 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;
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,6 +12,7 @@ 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',
@@ -21,7 +23,7 @@ const _nymph = new Nymph(
21
23
  new SQLite3Driver({
22
24
  filename: ':memory:',
23
25
  }),
24
- tilmeld
26
+ tilmeld,
25
27
  );
26
28
 
27
29
  const User = tilmeld.User;
@@ -44,7 +46,7 @@ describe('User', () => {
44
46
  const validUser = await makeNewUser();
45
47
 
46
48
  expect(() => {
47
- defaults.validatorUser(validUser);
49
+ defaults.validatorUser({ config: defaults } as Tilmeld, validUser);
48
50
  }).not.toThrow();
49
51
  });
50
52
 
@@ -55,7 +57,162 @@ describe('User', () => {
55
57
  invalidUser.unknown = 'I should cause an error.';
56
58
 
57
59
  expect(() => {
58
- defaults.validatorUser(invalidUser);
60
+ defaults.validatorUser({ config: defaults } as Tilmeld, invalidUser);
59
61
  }).toThrow('Invalid User: "unknown" is not allowed');
60
62
  });
63
+
64
+ it("doesn't allow duplicate usernames", async () => {
65
+ const newUserA = await User.factory();
66
+
67
+ newUserA.username = 'new-user';
68
+ newUserA.email = 'newusera@localhost';
69
+ newUserA.nameFirst = 'New';
70
+ newUserA.nameLast = 'User';
71
+ newUserA.name = 'New User';
72
+ newUserA.$password('password');
73
+
74
+ const newUserB = await User.factory();
75
+
76
+ newUserB.username = 'new-user';
77
+ newUserB.email = 'newuserb@localhost';
78
+ newUserB.nameFirst = 'New';
79
+ newUserB.nameLast = 'User';
80
+ newUserB.name = 'New User';
81
+ newUserB.$password('password');
82
+
83
+ const promises = [newUserA.$saveSkipAC(), newUserB.$saveSkipAC()];
84
+
85
+ try {
86
+ await Promise.all(promises);
87
+
88
+ throw new Error("Shouldn't get here because of unique constraint.");
89
+ } catch (e: any) {
90
+ expect(e).toBeInstanceOf(EntityUniqueConstraintError);
91
+ }
92
+
93
+ await Promise.allSettled(promises);
94
+
95
+ for (const user of [newUserA, newUserB]) {
96
+ if (user.guid != null) {
97
+ expect(await user.$deleteSkipAC()).toEqual(true);
98
+ }
99
+ }
100
+ });
101
+
102
+ it("doesn't allow duplicate emails", async () => {
103
+ const newUserA = await User.factory();
104
+
105
+ newUserA.username = 'new-user-a';
106
+ newUserA.email = 'newuser@localhost';
107
+ newUserA.nameFirst = 'New';
108
+ newUserA.nameLast = 'User';
109
+ newUserA.name = 'New User';
110
+ newUserA.$password('password');
111
+
112
+ const newUserB = await User.factory();
113
+
114
+ newUserB.username = 'new-user-b';
115
+ newUserB.email = 'newuser@localhost';
116
+ newUserB.nameFirst = 'New';
117
+ newUserB.nameLast = 'User';
118
+ newUserB.name = 'New User';
119
+ newUserB.$password('password');
120
+
121
+ const promises = [newUserA.$saveSkipAC(), newUserB.$saveSkipAC()];
122
+
123
+ try {
124
+ await Promise.all(promises);
125
+
126
+ throw new Error("Shouldn't get here because of unique constraint.");
127
+ } catch (e: any) {
128
+ expect(e).toBeInstanceOf(EntityUniqueConstraintError);
129
+ }
130
+
131
+ await Promise.allSettled(promises);
132
+
133
+ for (const user of [newUserA, newUserB]) {
134
+ if (user.guid != null) {
135
+ expect(await user.$deleteSkipAC()).toEqual(true);
136
+ }
137
+ }
138
+ });
139
+
140
+ it('allows a domain user', async () => {
141
+ const domainAdmin = await User.factory();
142
+
143
+ domainAdmin.username = 'admin';
144
+ domainAdmin.email = 'admin@localhost';
145
+ domainAdmin.nameFirst = 'Admin';
146
+ domainAdmin.nameLast = 'User';
147
+ domainAdmin.name = 'Admin User';
148
+ domainAdmin.$password('password');
149
+ domainAdmin.$grant('tilmeld/domain/example.com/admin');
150
+
151
+ expect(await domainAdmin.$saveSkipAC()).toEqual(true);
152
+
153
+ // Log in the domain admin.
154
+ await tilmeld.fillSession(domainAdmin);
155
+
156
+ const domainUser = await User.factory();
157
+
158
+ domainUser.username = 'new-user@example.com';
159
+ domainUser.email = 'newuser@localhost';
160
+ domainUser.nameFirst = 'New';
161
+ domainUser.nameLast = 'User';
162
+ domainUser.name = 'New User';
163
+ domainUser.$password('password');
164
+
165
+ expect(await domainUser.$save()).toEqual(true);
166
+
167
+ tilmeld.clearSession();
168
+
169
+ for (const user of [domainAdmin, domainUser]) {
170
+ if (user.guid != null) {
171
+ expect(await user.$deleteSkipAC()).toEqual(true);
172
+ }
173
+ }
174
+ });
175
+
176
+ it('disallows a domain user with no admin permission', async () => {
177
+ const domainAdmin = await User.factory();
178
+
179
+ domainAdmin.username = 'admin';
180
+ domainAdmin.email = 'admin@localhost';
181
+ domainAdmin.nameFirst = 'Admin';
182
+ domainAdmin.nameLast = 'User';
183
+ domainAdmin.name = 'Admin User';
184
+ domainAdmin.$password('password');
185
+ domainAdmin.$grant('tilmeld/domain/example.com/admin');
186
+
187
+ expect(await domainAdmin.$saveSkipAC()).toEqual(true);
188
+
189
+ // Log in the domain admin.
190
+ await tilmeld.fillSession(domainAdmin);
191
+
192
+ const domainUser = await User.factory();
193
+
194
+ // The wrong domain name.
195
+ domainUser.username = 'new-user@example.net';
196
+ domainUser.email = 'newuser@localhost';
197
+ domainUser.nameFirst = 'New';
198
+ domainUser.nameLast = 'User';
199
+ domainUser.name = 'New User';
200
+ domainUser.$password('password');
201
+
202
+ try {
203
+ await domainUser.$save();
204
+
205
+ throw new Error("Shouldn't get here because of access control.");
206
+ } catch (e: any) {
207
+ expect(e).toBeInstanceOf(AccessControlError);
208
+ }
209
+
210
+ tilmeld.clearSession();
211
+
212
+ for (const user of [domainAdmin, domainUser]) {
213
+ if (user.guid != null) {
214
+ expect(await user.$deleteSkipAC()).toEqual(true);
215
+ }
216
+ }
217
+ });
61
218
  });