@nymphjs/tilmeld 1.0.0-beta.13 → 1.0.0-beta.131
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/CHANGELOG.md +604 -0
- package/README.md +21 -5
- package/dist/AbleObject.d.ts +15 -0
- package/dist/AbleObject.js +18 -6
- package/dist/AbleObject.js.map +1 -1
- package/dist/Group.d.ts +183 -19
- package/dist/Group.js +814 -440
- package/dist/Group.js.map +1 -1
- package/dist/Group.testArtifacts.d.ts +3 -0
- package/dist/Group.testArtifacts.js +120 -0
- package/dist/Group.testArtifacts.js.map +1 -0
- package/dist/Tilmeld.d.ts +241 -12
- package/dist/Tilmeld.js +725 -286
- package/dist/Tilmeld.js.map +1 -1
- package/dist/Tilmeld.types.d.ts +5 -5
- package/dist/Tilmeld.types.js +1 -2
- package/dist/User.d.ts +396 -26
- package/dist/User.js +1955 -1058
- package/dist/User.js.map +1 -1
- package/dist/User.testArtifacts.d.ts +3 -0
- package/dist/User.testArtifacts.js +175 -0
- package/dist/User.testArtifacts.js.map +1 -0
- package/dist/conf/defaults.d.ts +1 -1
- package/dist/conf/defaults.js +196 -141
- package/dist/conf/defaults.js.map +1 -1
- package/dist/conf/index.d.ts +355 -2
- package/dist/conf/index.js +2 -8
- package/dist/conf/index.js.map +1 -1
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.js +3 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/requireAbility.d.ts +10 -0
- package/dist/decorators/requireAbility.js +21 -0
- package/dist/decorators/requireAbility.js.map +1 -0
- package/dist/decorators/requireAuthentication.d.ts +8 -0
- package/dist/decorators/requireAuthentication.js +16 -0
- package/dist/decorators/requireAuthentication.js.map +1 -0
- package/dist/enforceTilmeld.d.ts +3 -0
- package/dist/enforceTilmeld.js +18 -0
- package/dist/enforceTilmeld.js.map +1 -0
- package/dist/errors/AccessControlError.d.ts +2 -1
- package/dist/errors/AccessControlError.js +3 -6
- package/dist/errors/AccessControlError.js.map +1 -1
- package/dist/errors/BadDataError.d.ts +2 -1
- package/dist/errors/BadDataError.js +3 -6
- package/dist/errors/BadDataError.js.map +1 -1
- package/dist/errors/BadEmailError.d.ts +2 -1
- package/dist/errors/BadEmailError.js +3 -6
- package/dist/errors/BadEmailError.js.map +1 -1
- package/dist/errors/BadUsernameError.d.ts +2 -1
- package/dist/errors/BadUsernameError.js +3 -6
- package/dist/errors/BadUsernameError.js.map +1 -1
- package/dist/errors/CouldNotChangeDefaultPrimaryGroupError.js +1 -5
- package/dist/errors/CouldNotChangeDefaultPrimaryGroupError.js.map +1 -1
- package/dist/errors/EmailChangeRateLimitExceededError.js +1 -5
- package/dist/errors/EmailChangeRateLimitExceededError.js.map +1 -1
- package/dist/errors/index.d.ts +6 -6
- package/dist/errors/index.js +6 -22
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.js +17 -35
- package/dist/index.js.map +1 -1
- package/dist/testArtifacts.d.ts +23 -0
- package/dist/testArtifacts.js +1317 -0
- package/dist/testArtifacts.js.map +1 -0
- package/dist/tilmeldJoiProps.d.ts +3 -3
- package/dist/tilmeldJoiProps.js +13 -18
- package/dist/tilmeldJoiProps.js.map +1 -1
- package/jest.config.js +31 -5
- package/package.json +49 -36
- package/src/AbleObject.ts +2 -2
- package/src/Group.testArtifacts.ts +159 -0
- package/src/Group.ts +647 -241
- package/src/Tilmeld.ts +550 -315
- package/src/Tilmeld.types.ts +5 -5
- package/src/User.testArtifacts.ts +226 -0
- package/src/User.ts +1657 -637
- package/src/conf/defaults.ts +172 -109
- package/src/conf/index.ts +370 -2
- package/src/decorators/index.ts +2 -0
- package/src/decorators/requireAbility.ts +26 -0
- package/src/decorators/requireAuthentication.ts +19 -0
- package/src/enforceTilmeld.ts +20 -0
- package/src/errors/AccessControlError.ts +4 -2
- package/src/errors/BadDataError.ts +4 -2
- package/src/errors/BadEmailError.ts +4 -2
- package/src/errors/BadUsernameError.ts +4 -2
- package/src/errors/index.ts +6 -6
- package/src/index.ts +13 -10
- package/src/testArtifacts.ts +2098 -0
- package/src/tilmeldJoiProps.ts +8 -23
- package/tsconfig.json +6 -3
- package/typedoc.json +4 -0
- package/dist/Group.test.d.ts +0 -1
- package/dist/Group.test.js +0 -48
- package/dist/Group.test.js.map +0 -1
- package/dist/User.test.d.ts +0 -1
- package/dist/User.test.js +0 -51
- package/dist/User.test.js.map +0 -1
- package/dist/conf/d.d.ts +0 -55
- package/dist/conf/d.js +0 -3
- package/dist/conf/d.js.map +0 -1
- package/src/Group.test.ts +0 -58
- package/src/User.test.ts +0 -61
- package/src/conf/d.ts +0 -303
package/src/Tilmeld.types.ts
CHANGED
|
@@ -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?:
|
|
11
|
-
acWrite?:
|
|
12
|
-
acRead?:
|
|
10
|
+
acFull?: string[];
|
|
11
|
+
acWrite?: string[];
|
|
12
|
+
acRead?: string[];
|
|
13
13
|
};
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { type Nymph, EntityUniqueConstraintError } from '@nymphjs/nymph';
|
|
2
|
+
|
|
3
|
+
import type Tilmeld from './Tilmeld.js';
|
|
4
|
+
import defaults from './conf/defaults.js';
|
|
5
|
+
import { AccessControlError } from './errors/index.js';
|
|
6
|
+
|
|
7
|
+
export function UserTest(
|
|
8
|
+
nymph: Nymph,
|
|
9
|
+
tilmeld: Tilmeld,
|
|
10
|
+
describe: (name: string, fn: () => void) => void,
|
|
11
|
+
it: (name: string, fn: () => void) => void,
|
|
12
|
+
) {
|
|
13
|
+
const User = tilmeld.User;
|
|
14
|
+
const Group = tilmeld.Group;
|
|
15
|
+
|
|
16
|
+
describe('User', () => {
|
|
17
|
+
beforeAll(async () => {
|
|
18
|
+
// Ensure the tables exist.
|
|
19
|
+
try {
|
|
20
|
+
await User.factoryUsername('user');
|
|
21
|
+
await Group.factoryGroupname('group');
|
|
22
|
+
} catch (e) {
|
|
23
|
+
// ignore
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
async function makeNewUser() {
|
|
28
|
+
const newUser = await User.factory();
|
|
29
|
+
|
|
30
|
+
newUser.username = 'new-user';
|
|
31
|
+
newUser.email = 'newuser@localhost';
|
|
32
|
+
newUser.nameFirst = 'New';
|
|
33
|
+
newUser.nameLast = 'User';
|
|
34
|
+
newUser.name = 'New User';
|
|
35
|
+
newUser.$password('password');
|
|
36
|
+
|
|
37
|
+
return newUser;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
it('new user passes validation', async () => {
|
|
41
|
+
const validUser = await makeNewUser();
|
|
42
|
+
|
|
43
|
+
expect(() => {
|
|
44
|
+
defaults.validatorUser({ config: defaults } as Tilmeld, validUser);
|
|
45
|
+
}).not.toThrow();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("doesn't allow unknown keys", async () => {
|
|
49
|
+
const invalidUser = await makeNewUser();
|
|
50
|
+
|
|
51
|
+
// @ts-ignore: testing unknown keys
|
|
52
|
+
invalidUser.unknown = 'I should cause an error.';
|
|
53
|
+
|
|
54
|
+
expect(() => {
|
|
55
|
+
defaults.validatorUser({ config: defaults } as Tilmeld, invalidUser);
|
|
56
|
+
}).toThrow('Invalid User: "unknown" is not allowed');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("doesn't allow duplicate usernames", async () => {
|
|
60
|
+
tilmeld.config.generatePrimary = false;
|
|
61
|
+
class NoUsernameCheckUser extends User {
|
|
62
|
+
public async $checkUsername() {
|
|
63
|
+
return {
|
|
64
|
+
result: true,
|
|
65
|
+
message: 'No problem here!',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const newUserA = await NoUsernameCheckUser.factory();
|
|
71
|
+
|
|
72
|
+
newUserA.username = 'new-user';
|
|
73
|
+
newUserA.email = 'newusera@localhost';
|
|
74
|
+
newUserA.nameFirst = 'New';
|
|
75
|
+
newUserA.nameLast = 'User';
|
|
76
|
+
newUserA.name = 'New User';
|
|
77
|
+
newUserA.$password('password');
|
|
78
|
+
|
|
79
|
+
await newUserA.$saveSkipAC();
|
|
80
|
+
|
|
81
|
+
const newUserB = await NoUsernameCheckUser.factory();
|
|
82
|
+
|
|
83
|
+
newUserB.username = 'new-user';
|
|
84
|
+
newUserB.email = 'newuserb@localhost';
|
|
85
|
+
newUserB.nameFirst = 'New';
|
|
86
|
+
newUserB.nameLast = 'User';
|
|
87
|
+
newUserB.name = 'New User';
|
|
88
|
+
newUserB.$password('password');
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
await newUserB.$saveSkipAC();
|
|
92
|
+
|
|
93
|
+
throw new Error("Shouldn't get here because of unique constraint.");
|
|
94
|
+
} catch (e: any) {
|
|
95
|
+
expect(e).toBeInstanceOf(EntityUniqueConstraintError);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
await newUserA.$deleteSkipAC();
|
|
99
|
+
|
|
100
|
+
tilmeld.config.generatePrimary = true;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("doesn't allow duplicate emails", async () => {
|
|
104
|
+
tilmeld.config.generatePrimary = false;
|
|
105
|
+
class NoEmailCheckUser extends User {
|
|
106
|
+
public async $checkEmail() {
|
|
107
|
+
return {
|
|
108
|
+
result: true,
|
|
109
|
+
message: 'No problem here!',
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const newUserA = await NoEmailCheckUser.factory();
|
|
115
|
+
|
|
116
|
+
newUserA.username = 'new-user-a';
|
|
117
|
+
newUserA.email = 'newuser@localhost';
|
|
118
|
+
newUserA.nameFirst = 'New';
|
|
119
|
+
newUserA.nameLast = 'User';
|
|
120
|
+
newUserA.name = 'New User';
|
|
121
|
+
newUserA.$password('password');
|
|
122
|
+
|
|
123
|
+
await newUserA.$saveSkipAC();
|
|
124
|
+
|
|
125
|
+
const newUserB = await NoEmailCheckUser.factory();
|
|
126
|
+
|
|
127
|
+
newUserB.username = 'new-user-b';
|
|
128
|
+
newUserB.email = 'newuser@localhost';
|
|
129
|
+
newUserB.nameFirst = 'New';
|
|
130
|
+
newUserB.nameLast = 'User';
|
|
131
|
+
newUserB.name = 'New User';
|
|
132
|
+
newUserB.$password('password');
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
await newUserB.$saveSkipAC();
|
|
136
|
+
|
|
137
|
+
throw new Error("Shouldn't get here because of unique constraint.");
|
|
138
|
+
} catch (e: any) {
|
|
139
|
+
expect(e).toBeInstanceOf(EntityUniqueConstraintError);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
await newUserA.$deleteSkipAC();
|
|
143
|
+
|
|
144
|
+
tilmeld.config.generatePrimary = true;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('allows a domain user', async () => {
|
|
148
|
+
const domainAdmin = await User.factory();
|
|
149
|
+
|
|
150
|
+
domainAdmin.username = 'admin';
|
|
151
|
+
domainAdmin.email = 'admin@localhost';
|
|
152
|
+
domainAdmin.nameFirst = 'Admin';
|
|
153
|
+
domainAdmin.nameLast = 'User';
|
|
154
|
+
domainAdmin.name = 'Admin User';
|
|
155
|
+
domainAdmin.$password('password');
|
|
156
|
+
domainAdmin.$grant('tilmeld/domain/example.com/admin');
|
|
157
|
+
|
|
158
|
+
await domainAdmin.$saveSkipAC();
|
|
159
|
+
|
|
160
|
+
// Log in the domain admin.
|
|
161
|
+
await tilmeld.fillSession(domainAdmin);
|
|
162
|
+
|
|
163
|
+
const domainUser = await User.factory();
|
|
164
|
+
|
|
165
|
+
domainUser.username = 'new-user@example.com';
|
|
166
|
+
domainUser.email = 'newuser@localhost';
|
|
167
|
+
domainUser.nameFirst = 'New';
|
|
168
|
+
domainUser.nameLast = 'User';
|
|
169
|
+
domainUser.name = 'New User';
|
|
170
|
+
domainUser.$password('password');
|
|
171
|
+
|
|
172
|
+
await domainUser.$save();
|
|
173
|
+
|
|
174
|
+
tilmeld.clearSession();
|
|
175
|
+
|
|
176
|
+
for (const user of [domainAdmin, domainUser]) {
|
|
177
|
+
if (user.guid != null) {
|
|
178
|
+
await user.$deleteSkipAC();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('disallows a domain user with no admin permission', async () => {
|
|
184
|
+
const domainAdmin = await User.factory();
|
|
185
|
+
|
|
186
|
+
domainAdmin.username = 'admin';
|
|
187
|
+
domainAdmin.email = 'admin@localhost';
|
|
188
|
+
domainAdmin.nameFirst = 'Admin';
|
|
189
|
+
domainAdmin.nameLast = 'User';
|
|
190
|
+
domainAdmin.name = 'Admin User';
|
|
191
|
+
domainAdmin.$password('password');
|
|
192
|
+
domainAdmin.$grant('tilmeld/domain/example.com/admin');
|
|
193
|
+
|
|
194
|
+
await domainAdmin.$saveSkipAC();
|
|
195
|
+
|
|
196
|
+
// Log in the domain admin.
|
|
197
|
+
await tilmeld.fillSession(domainAdmin);
|
|
198
|
+
|
|
199
|
+
const domainUser = await User.factory();
|
|
200
|
+
|
|
201
|
+
// The wrong domain name.
|
|
202
|
+
domainUser.username = 'new-user@example.net';
|
|
203
|
+
domainUser.email = 'newuser@localhost';
|
|
204
|
+
domainUser.nameFirst = 'New';
|
|
205
|
+
domainUser.nameLast = 'User';
|
|
206
|
+
domainUser.name = 'New User';
|
|
207
|
+
domainUser.$password('password');
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
await domainUser.$save();
|
|
211
|
+
|
|
212
|
+
throw new Error("Shouldn't get here because of access control.");
|
|
213
|
+
} catch (e: any) {
|
|
214
|
+
expect(e).toBeInstanceOf(AccessControlError);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
tilmeld.clearSession();
|
|
218
|
+
|
|
219
|
+
for (const user of [domainAdmin, domainUser]) {
|
|
220
|
+
if (user.guid != null) {
|
|
221
|
+
await user.$deleteSkipAC();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
}
|