@nymphjs/tilmeld 1.0.0-alpha.9 → 1.0.0-beta.1
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 +174 -0
- package/dist/Group.d.ts +1 -1
- package/dist/Group.js +309 -357
- package/dist/Group.js.map +1 -1
- package/dist/Group.test.js +12 -23
- package/dist/Group.test.js.map +1 -1
- package/dist/Tilmeld.js +137 -91
- package/dist/Tilmeld.js.map +1 -1
- package/dist/Tilmeld.types.d.ts +1 -1
- package/dist/User.d.ts +41 -3
- package/dist/User.js +798 -759
- package/dist/User.js.map +1 -1
- package/dist/User.test.js +15 -26
- package/dist/User.test.js.map +1 -1
- package/dist/conf/d.d.ts +2 -1
- package/dist/conf/defaults.js +96 -57
- package/dist/conf/defaults.js.map +1 -1
- package/dist/errors/index.js +5 -1
- package/dist/errors/index.js.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/tilmeldJoiProps.d.ts +6 -6
- package/jest.config.js +1 -1
- package/package.json +20 -22
- package/src/Group.ts +2 -1
- package/src/Tilmeld.ts +137 -43
- package/src/User.ts +229 -16
- package/src/conf/d.ts +13 -1
- package/src/conf/defaults.ts +15 -18
- package/tsconfig.json +2 -0
package/dist/User.js
CHANGED
|
@@ -1,27 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
14
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
6
|
const strtotime_1 = __importDefault(require("locutus/php/datetime/strtotime"));
|
|
16
|
-
const nanoid_1 = require("nanoid");
|
|
17
|
-
const nanoid_dictionary_1 = require("nanoid-dictionary");
|
|
18
7
|
const enc_base64_1 = __importDefault(require("crypto-js/enc-base64"));
|
|
19
8
|
const sha256_1 = __importDefault(require("crypto-js/sha256"));
|
|
20
9
|
const md5_1 = __importDefault(require("crypto-js/md5"));
|
|
21
10
|
const lodash_1 = require("lodash");
|
|
11
|
+
const guid_1 = require("@nymphjs/guid");
|
|
22
12
|
const AbleObject_1 = __importDefault(require("./AbleObject"));
|
|
23
13
|
const errors_1 = require("./errors");
|
|
24
14
|
class User extends AbleObject_1.default {
|
|
15
|
+
static async factory(guid) {
|
|
16
|
+
return (await super.factory(guid));
|
|
17
|
+
}
|
|
18
|
+
static async factoryUsername(username) {
|
|
19
|
+
const entity = new this();
|
|
20
|
+
if (username != null) {
|
|
21
|
+
const entity = await this.nymph.getEntity({
|
|
22
|
+
class: this,
|
|
23
|
+
}, {
|
|
24
|
+
type: '&',
|
|
25
|
+
ilike: ['username', username.replace(/([\\%_])/g, (s) => `\\${s}`)],
|
|
26
|
+
});
|
|
27
|
+
if (entity != null) {
|
|
28
|
+
return entity;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return entity;
|
|
32
|
+
}
|
|
33
|
+
static factorySync(guid) {
|
|
34
|
+
return super.factorySync(guid);
|
|
35
|
+
}
|
|
25
36
|
constructor(guid) {
|
|
26
37
|
super(guid);
|
|
27
38
|
this.$clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
|
|
@@ -37,151 +48,117 @@ class User extends AbleObject_1.default {
|
|
|
37
48
|
this.$updateDataProtection();
|
|
38
49
|
}
|
|
39
50
|
}
|
|
40
|
-
static factory(guid) {
|
|
41
|
-
const _super = Object.create(null, {
|
|
42
|
-
factory: { get: () => super.factory }
|
|
43
|
-
});
|
|
44
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
-
return (yield _super.factory.call(this, guid));
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
static factoryUsername(username) {
|
|
49
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
-
const entity = new this();
|
|
51
|
-
if (username != null) {
|
|
52
|
-
const entity = yield this.nymph.getEntity({
|
|
53
|
-
class: this,
|
|
54
|
-
}, {
|
|
55
|
-
type: '&',
|
|
56
|
-
ilike: ['username', username.replace(/([\\%_])/g, (s) => `\\${s}`)],
|
|
57
|
-
});
|
|
58
|
-
if (entity != null) {
|
|
59
|
-
return entity;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return entity;
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
static factorySync(guid) {
|
|
66
|
-
return super.factorySync(guid);
|
|
67
|
-
}
|
|
68
51
|
static current(returnObjectIfNotExist) {
|
|
69
52
|
if (this.tilmeld.currentUser == null) {
|
|
70
53
|
return returnObjectIfNotExist ? this.factorySync() : null;
|
|
71
54
|
}
|
|
72
55
|
return this.tilmeld.currentUser;
|
|
73
56
|
}
|
|
74
|
-
static sendRecovery(data) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
});
|
|
91
|
-
if (getUser == null) {
|
|
92
|
-
return {
|
|
93
|
-
result: false,
|
|
94
|
-
message: 'Requested account is not accessible.',
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
user = getUser;
|
|
98
|
-
options.template = 'RecoverUsername';
|
|
99
|
-
options.message = {
|
|
100
|
-
to: {
|
|
101
|
-
name: (_a = user.name) !== null && _a !== void 0 ? _a : '',
|
|
102
|
-
address: (_b = user.email) !== null && _b !== void 0 ? _b : '',
|
|
103
|
-
},
|
|
104
|
-
};
|
|
105
|
-
options.locals = {};
|
|
106
|
-
}
|
|
107
|
-
else if (data.recoveryType === 'password') {
|
|
108
|
-
const getUser = yield this.tilmeld.User.factoryUsername(data.account);
|
|
109
|
-
if (getUser.guid == null) {
|
|
110
|
-
return {
|
|
111
|
-
result: false,
|
|
112
|
-
message: 'Requested account is not accessible.',
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
getUser.recoverSecret = (0, nanoid_1.customAlphabet)(nanoid_dictionary_1.nolookalikesSafe, 10)();
|
|
116
|
-
getUser.recoverSecretDate = Date.now();
|
|
117
|
-
if (!(yield getUser.$saveSkipAC())) {
|
|
118
|
-
return { result: false, message: "Couldn't save recovery secret." };
|
|
119
|
-
}
|
|
120
|
-
user = getUser;
|
|
121
|
-
options.template = 'RecoverPassword';
|
|
122
|
-
options.message = {
|
|
123
|
-
to: {
|
|
124
|
-
name: (_c = user.name) !== null && _c !== void 0 ? _c : '',
|
|
125
|
-
address: (_d = user.email) !== null && _d !== void 0 ? _d : '',
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
options.locals = {
|
|
129
|
-
recoverCode: getUser.recoverSecret,
|
|
130
|
-
timeLimit: this.tilmeld.config.pwRecoveryTimeLimit,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
return { result: false, message: 'Invalid recovery type.' };
|
|
135
|
-
}
|
|
136
|
-
if (yield this.tilmeld.config.sendEmail(this.tilmeld, options, user)) {
|
|
137
|
-
return {
|
|
138
|
-
result: true,
|
|
139
|
-
message: "We've sent an email to your registered address. Please " +
|
|
140
|
-
'check your email to continue with account recovery.',
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
return { result: false, message: "Couldn't send recovery email." };
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
static recover(data) {
|
|
149
|
-
var _a;
|
|
150
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
-
if (!this.tilmeld.config.pwRecovery) {
|
|
57
|
+
static async sendRecovery(data) {
|
|
58
|
+
if (!this.tilmeld.config.pwRecovery) {
|
|
59
|
+
return {
|
|
60
|
+
result: false,
|
|
61
|
+
message: 'Account recovery is not allowed.',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
let user;
|
|
65
|
+
const options = {};
|
|
66
|
+
if (!this.tilmeld.config.emailUsernames &&
|
|
67
|
+
data.recoveryType === 'username') {
|
|
68
|
+
const getUser = await this.nymph.getEntity({ class: this.tilmeld.User, skipAc: true }, {
|
|
69
|
+
type: '&',
|
|
70
|
+
ilike: ['email', data.account.replace(/([\\%_])/g, (s) => `\\${s}`)],
|
|
71
|
+
});
|
|
72
|
+
if (getUser == null) {
|
|
152
73
|
return {
|
|
153
74
|
result: false,
|
|
154
|
-
message: '
|
|
75
|
+
message: 'Requested account is not accessible.',
|
|
155
76
|
};
|
|
156
77
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
78
|
+
user = getUser;
|
|
79
|
+
options.template = 'RecoverUsername';
|
|
80
|
+
options.message = {
|
|
81
|
+
to: {
|
|
82
|
+
name: user.name ?? '',
|
|
83
|
+
address: user.email ?? '',
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
options.locals = {};
|
|
87
|
+
}
|
|
88
|
+
else if (data.recoveryType === 'password') {
|
|
89
|
+
const getUser = await this.tilmeld.User.factoryUsername(data.account);
|
|
90
|
+
if (getUser.guid == null) {
|
|
164
91
|
return {
|
|
165
92
|
result: false,
|
|
166
|
-
message: '
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
if (!('password' in data) || !data.password.length) {
|
|
170
|
-
return { result: false, message: 'Password cannot be empty.' };
|
|
171
|
-
}
|
|
172
|
-
user.$password(data.password);
|
|
173
|
-
delete user.recoverSecret;
|
|
174
|
-
delete user.recoverSecretDate;
|
|
175
|
-
if (yield user.$saveSkipAC()) {
|
|
176
|
-
return {
|
|
177
|
-
result: true,
|
|
178
|
-
message: 'Your password has been reset. You can now log in using your new password.',
|
|
93
|
+
message: 'Requested account is not accessible.',
|
|
179
94
|
};
|
|
180
95
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
96
|
+
getUser.recoverSecret = (0, guid_1.humanSecret)();
|
|
97
|
+
getUser.recoverSecretDate = Date.now();
|
|
98
|
+
if (!(await getUser.$saveSkipAC())) {
|
|
99
|
+
return { result: false, message: "Couldn't save recovery secret." };
|
|
100
|
+
}
|
|
101
|
+
user = getUser;
|
|
102
|
+
options.template = 'RecoverPassword';
|
|
103
|
+
options.message = {
|
|
104
|
+
to: {
|
|
105
|
+
name: user.name ?? '',
|
|
106
|
+
address: user.email ?? '',
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
options.locals = {
|
|
110
|
+
recoverCode: getUser.recoverSecret,
|
|
111
|
+
timeLimit: this.tilmeld.config.pwRecoveryTimeLimit,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
return { result: false, message: 'Invalid recovery type.' };
|
|
116
|
+
}
|
|
117
|
+
if (await this.tilmeld.config.sendEmail(this.tilmeld, options, user)) {
|
|
118
|
+
return {
|
|
119
|
+
result: true,
|
|
120
|
+
message: "We've sent an email to your registered address. Please " +
|
|
121
|
+
'check your email to continue with account recovery.',
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
return { result: false, message: "Couldn't send recovery email." };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
static async recover(data) {
|
|
129
|
+
if (!this.tilmeld.config.pwRecovery) {
|
|
130
|
+
return {
|
|
131
|
+
result: false,
|
|
132
|
+
message: 'Account recovery is not allowed.',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const user = await this.tilmeld.User.factoryUsername(data.username);
|
|
136
|
+
if (user.guid == null ||
|
|
137
|
+
user.recoverSecret == null ||
|
|
138
|
+
data.secret !== user.recoverSecret ||
|
|
139
|
+
(0, strtotime_1.default)('+' + this.tilmeld.config.pwRecoveryTimeLimit, Math.floor((user.recoverSecretDate ?? 0) / 1000)) *
|
|
140
|
+
1000 <
|
|
141
|
+
Date.now()) {
|
|
142
|
+
return {
|
|
143
|
+
result: false,
|
|
144
|
+
message: 'The secret code does not match.',
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if (!('password' in data) || !data.password.length) {
|
|
148
|
+
return { result: false, message: 'Password cannot be empty.' };
|
|
149
|
+
}
|
|
150
|
+
user.$password(data.password);
|
|
151
|
+
delete user.recoverSecret;
|
|
152
|
+
delete user.recoverSecretDate;
|
|
153
|
+
if (await user.$saveSkipAC()) {
|
|
154
|
+
return {
|
|
155
|
+
result: true,
|
|
156
|
+
message: 'Your password has been reset. You can now log in using your new password.',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
return { result: false, message: 'Error saving new password.' };
|
|
161
|
+
}
|
|
185
162
|
}
|
|
186
163
|
static getClientConfig() {
|
|
187
164
|
return {
|
|
@@ -195,19 +172,17 @@ class User extends AbleObject_1.default {
|
|
|
195
172
|
unverifiedAccess: this.tilmeld.config.unverifiedAccess,
|
|
196
173
|
};
|
|
197
174
|
}
|
|
198
|
-
static loginUser(data) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return result;
|
|
210
|
-
});
|
|
175
|
+
static async loginUser(data) {
|
|
176
|
+
if (!('username' in data) || !data.username.length) {
|
|
177
|
+
return { result: false, message: 'Incorrect login/password.' };
|
|
178
|
+
}
|
|
179
|
+
const user = await this.tilmeld.User.factoryUsername(data.username);
|
|
180
|
+
const result = user.$login(data);
|
|
181
|
+
if (result.result) {
|
|
182
|
+
user.$updateDataProtection();
|
|
183
|
+
result.user = user;
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
211
186
|
}
|
|
212
187
|
$login(data) {
|
|
213
188
|
const tilmeld = this.$nymph.tilmeld;
|
|
@@ -223,14 +198,54 @@ class User extends AbleObject_1.default {
|
|
|
223
198
|
if (!this.$checkPassword(data.password)) {
|
|
224
199
|
return { result: false, message: 'Incorrect login/password.' };
|
|
225
200
|
}
|
|
201
|
+
try {
|
|
202
|
+
for (let callback of this.constructor
|
|
203
|
+
.beforeLoginCallbacks) {
|
|
204
|
+
if (callback) {
|
|
205
|
+
callback(this, data);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch (e) {
|
|
210
|
+
return {
|
|
211
|
+
result: false,
|
|
212
|
+
message: e.message,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
226
215
|
if (!tilmeld.login(this, true)) {
|
|
227
216
|
return { result: false, message: 'Incorrect login/password.' };
|
|
228
217
|
}
|
|
218
|
+
for (let callback of this.constructor
|
|
219
|
+
.afterLoginCallbacks) {
|
|
220
|
+
if (callback) {
|
|
221
|
+
callback(this);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
229
224
|
return { result: true, message: 'You are logged in.' };
|
|
230
225
|
}
|
|
231
226
|
$logout() {
|
|
232
227
|
const tilmeld = this.$nymph.tilmeld;
|
|
228
|
+
try {
|
|
229
|
+
for (let callback of this.constructor
|
|
230
|
+
.beforeLogoutCallbacks) {
|
|
231
|
+
if (callback) {
|
|
232
|
+
callback(this);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch (e) {
|
|
237
|
+
return {
|
|
238
|
+
result: false,
|
|
239
|
+
message: e.message,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
233
242
|
tilmeld.logout();
|
|
243
|
+
for (let callback of this.constructor
|
|
244
|
+
.afterLogoutCallbacks) {
|
|
245
|
+
if (callback) {
|
|
246
|
+
callback(this);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
234
249
|
return { result: true, message: 'You have been logged out.' };
|
|
235
250
|
}
|
|
236
251
|
$getAvatar() {
|
|
@@ -244,40 +259,35 @@ class User extends AbleObject_1.default {
|
|
|
244
259
|
(0, md5_1.default)(this.$data.email.trim().toLowerCase()).toString() +
|
|
245
260
|
'?d=identicon&s=40');
|
|
246
261
|
}
|
|
247
|
-
$getDescendantGroups() {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (this.$
|
|
251
|
-
this.$descendantGroups =
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
for (let curGroup of (_a = this.$data.groups) !== null && _a !== void 0 ? _a : []) {
|
|
256
|
-
this.$descendantGroups = (_b = this.$descendantGroups) === null || _b === void 0 ? void 0 : _b.concat(yield curGroup.$getDescendants());
|
|
257
|
-
}
|
|
262
|
+
async $getDescendantGroups() {
|
|
263
|
+
if (this.$descendantGroups == null) {
|
|
264
|
+
this.$descendantGroups = [];
|
|
265
|
+
if (this.$data.group != null) {
|
|
266
|
+
this.$descendantGroups = await this.$data.group.$getDescendants();
|
|
267
|
+
}
|
|
268
|
+
for (let curGroup of this.$data.groups ?? []) {
|
|
269
|
+
this.$descendantGroups = this.$descendantGroups?.concat(await curGroup.$getDescendants());
|
|
258
270
|
}
|
|
259
|
-
|
|
260
|
-
|
|
271
|
+
}
|
|
272
|
+
return this.$descendantGroups;
|
|
261
273
|
}
|
|
262
274
|
$getDescendantGroupsSync() {
|
|
263
|
-
var _a, _b;
|
|
264
275
|
if (this.$descendantGroups == null) {
|
|
265
276
|
this.$descendantGroups = [];
|
|
266
277
|
if (this.$data.group != null) {
|
|
267
278
|
this.$descendantGroups = this.$data.group.$getDescendantsSync();
|
|
268
279
|
}
|
|
269
|
-
for (let curGroup of
|
|
270
|
-
this.$descendantGroups =
|
|
280
|
+
for (let curGroup of this.$data.groups ?? []) {
|
|
281
|
+
this.$descendantGroups = this.$descendantGroups?.concat(curGroup.$getDescendantsSync());
|
|
271
282
|
}
|
|
272
283
|
}
|
|
273
284
|
return this.$descendantGroups;
|
|
274
285
|
}
|
|
275
286
|
$jsonAcceptData(input, allowConflict = false) {
|
|
276
|
-
var _a, _b;
|
|
277
287
|
const tilmeld = this.$nymph.tilmeld;
|
|
278
288
|
this.$referenceWake();
|
|
279
|
-
if (
|
|
280
|
-
|
|
289
|
+
if (input.data.abilities?.indexOf('system/admin') !== -1 &&
|
|
290
|
+
this.$data.abilities?.indexOf('system/admin') === -1 &&
|
|
281
291
|
tilmeld.gatekeeper('tilmeld/admin') &&
|
|
282
292
|
!tilmeld.gatekeeper('system/admin')) {
|
|
283
293
|
throw new errors_1.BadDataError("You don't have the authority to make this user a system admin.");
|
|
@@ -286,11 +296,10 @@ class User extends AbleObject_1.default {
|
|
|
286
296
|
super.$jsonAcceptData(input, allowConflict);
|
|
287
297
|
}
|
|
288
298
|
$jsonAcceptPatch(patch, allowConflict = false) {
|
|
289
|
-
var _a, _b;
|
|
290
299
|
const tilmeld = this.$nymph.tilmeld;
|
|
291
300
|
this.$referenceWake();
|
|
292
|
-
if (
|
|
293
|
-
|
|
301
|
+
if (patch.set.abilities?.indexOf('system/admin') !== -1 &&
|
|
302
|
+
this.$data.abilities?.indexOf('system/admin') === -1 &&
|
|
294
303
|
tilmeld.gatekeeper('tilmeld/admin') &&
|
|
295
304
|
!tilmeld.gatekeeper('system/admin')) {
|
|
296
305
|
throw new errors_1.BadDataError("You don't have the authority to make this user a system admin.");
|
|
@@ -303,9 +312,8 @@ class User extends AbleObject_1.default {
|
|
|
303
312
|
this.$updateDataProtection();
|
|
304
313
|
}
|
|
305
314
|
$updateDataProtection(givenUser) {
|
|
306
|
-
var _a;
|
|
307
315
|
const tilmeld = this.$nymph.tilmeld;
|
|
308
|
-
let user = givenUser
|
|
316
|
+
let user = givenUser ?? tilmeld.User.current();
|
|
309
317
|
this.$clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
|
|
310
318
|
this.$privateData = [...User.DEFAULT_PRIVATE_DATA];
|
|
311
319
|
this.$allowlistData = [...User.DEFAULT_ALLOWLIST_DATA];
|
|
@@ -313,9 +321,9 @@ class User extends AbleObject_1.default {
|
|
|
313
321
|
this.$privateData.push('username');
|
|
314
322
|
}
|
|
315
323
|
const isCurrentUser = user != null && user.$is(this);
|
|
316
|
-
const abilities = (
|
|
324
|
+
const abilities = (isCurrentUser || user == null
|
|
317
325
|
? this.$data.abilities
|
|
318
|
-
: user
|
|
326
|
+
: user?.abilities) ?? [];
|
|
319
327
|
const isNewUser = this.guid == null;
|
|
320
328
|
if (isCurrentUser) {
|
|
321
329
|
this.$clientEnabledMethods.push('$gatekeeper');
|
|
@@ -360,23 +368,22 @@ class User extends AbleObject_1.default {
|
|
|
360
368
|
}
|
|
361
369
|
}
|
|
362
370
|
$gatekeeper(ability) {
|
|
363
|
-
var _a, _b, _c, _d, _e, _f;
|
|
364
371
|
const tilmeld = this.$nymph.tilmeld;
|
|
365
372
|
if (ability == null) {
|
|
366
|
-
return
|
|
373
|
+
return tilmeld.User.current()?.$is(this) ?? false;
|
|
367
374
|
}
|
|
368
375
|
if (this.$gatekeeperCache == null) {
|
|
369
|
-
let abilities =
|
|
376
|
+
let abilities = this.$data.abilities ?? [];
|
|
370
377
|
if (this.$data.inheritAbilities) {
|
|
371
|
-
for (let curGroup of
|
|
378
|
+
for (let curGroup of this.$data.groups ?? []) {
|
|
372
379
|
if (curGroup.enabled) {
|
|
373
|
-
abilities = abilities.concat(
|
|
380
|
+
abilities = abilities.concat(curGroup.abilities ?? []);
|
|
374
381
|
}
|
|
375
382
|
}
|
|
376
383
|
if (this.$data.group != null &&
|
|
377
384
|
this.$data.group.cdate != null &&
|
|
378
385
|
this.$data.group.enabled) {
|
|
379
|
-
abilities = abilities.concat(
|
|
386
|
+
abilities = abilities.concat(this.$data.group.abilities ?? []);
|
|
380
387
|
}
|
|
381
388
|
}
|
|
382
389
|
this.$gatekeeperCache = Object.fromEntries(abilities.map((ability) => [ability, true]));
|
|
@@ -390,72 +397,69 @@ class User extends AbleObject_1.default {
|
|
|
390
397
|
this.$gatekeeperCache = undefined;
|
|
391
398
|
return ret;
|
|
392
399
|
}
|
|
393
|
-
$sendEmailVerification() {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
name: (_a = this.$data.name) !== null && _a !== void 0 ? _a : '',
|
|
411
|
-
address: (_b = this.$data.email) !== null && _b !== void 0 ? _b : '',
|
|
412
|
-
},
|
|
413
|
-
},
|
|
414
|
-
locals: {
|
|
415
|
-
verifyLink: link,
|
|
416
|
-
},
|
|
417
|
-
}, this));
|
|
418
|
-
}
|
|
419
|
-
if (this.$data.newEmailSecret != null) {
|
|
420
|
-
const link = `${verifyUrl}?action=verifychange&id=${encodeURIComponent(this.guid)}&secret=${encodeURIComponent(this.$data.newEmailSecret)}`;
|
|
421
|
-
success =
|
|
422
|
-
success &&
|
|
423
|
-
(yield tilmeld.config.sendEmail(tilmeld, {
|
|
424
|
-
template: 'VerifyEmailChange',
|
|
425
|
-
message: {
|
|
426
|
-
to: {
|
|
427
|
-
name: (_c = this.$data.name) !== null && _c !== void 0 ? _c : '',
|
|
428
|
-
address: (_d = this.$data.newEmailAddress) !== null && _d !== void 0 ? _d : '',
|
|
429
|
-
},
|
|
430
|
-
},
|
|
431
|
-
locals: {
|
|
432
|
-
verifyLink: link,
|
|
433
|
-
oldEmail: this.$data.cancelEmailAddress,
|
|
434
|
-
newEmail: this.$data.newEmailAddress,
|
|
400
|
+
async $sendEmailVerification() {
|
|
401
|
+
const tilmeld = this.$nymph.tilmeld;
|
|
402
|
+
if (this.guid == null) {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
let success = true;
|
|
406
|
+
const verifyUrl = `${tilmeld.config.appUrl.replace(/\/$/, () => '')}${tilmeld.config.setupPath}/verify`;
|
|
407
|
+
if (this.$data.secret != null) {
|
|
408
|
+
const link = `${verifyUrl}?action=verify&id=${encodeURIComponent(this.guid)}&secret=${encodeURIComponent(this.$data.secret)}`;
|
|
409
|
+
success =
|
|
410
|
+
success &&
|
|
411
|
+
(await tilmeld.config.sendEmail(tilmeld, {
|
|
412
|
+
template: 'VerifyEmail',
|
|
413
|
+
message: {
|
|
414
|
+
to: {
|
|
415
|
+
name: this.$data.name ?? '',
|
|
416
|
+
address: this.$data.email ?? '',
|
|
435
417
|
},
|
|
436
|
-
},
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
418
|
+
},
|
|
419
|
+
locals: {
|
|
420
|
+
verifyLink: link,
|
|
421
|
+
},
|
|
422
|
+
}, this));
|
|
423
|
+
}
|
|
424
|
+
if (this.$data.newEmailSecret != null) {
|
|
425
|
+
const link = `${verifyUrl}?action=verifychange&id=${encodeURIComponent(this.guid)}&secret=${encodeURIComponent(this.$data.newEmailSecret)}`;
|
|
426
|
+
success =
|
|
427
|
+
success &&
|
|
428
|
+
(await tilmeld.config.sendEmail(tilmeld, {
|
|
429
|
+
template: 'VerifyEmailChange',
|
|
430
|
+
message: {
|
|
431
|
+
to: {
|
|
432
|
+
name: this.$data.name ?? '',
|
|
433
|
+
address: this.$data.newEmailAddress ?? '',
|
|
449
434
|
},
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
435
|
+
},
|
|
436
|
+
locals: {
|
|
437
|
+
verifyLink: link,
|
|
438
|
+
oldEmail: this.$data.cancelEmailAddress,
|
|
439
|
+
newEmail: this.$data.newEmailAddress,
|
|
440
|
+
},
|
|
441
|
+
}, this));
|
|
442
|
+
}
|
|
443
|
+
if (this.$data.cancelEmailSecret != null) {
|
|
444
|
+
const link = `${verifyUrl}?action=cancelchange&id=${encodeURIComponent(this.guid)}&secret=${encodeURIComponent(this.$data.cancelEmailSecret)}`;
|
|
445
|
+
success =
|
|
446
|
+
success &&
|
|
447
|
+
(await tilmeld.config.sendEmail(tilmeld, {
|
|
448
|
+
template: 'CancelEmailChange',
|
|
449
|
+
message: {
|
|
450
|
+
to: {
|
|
451
|
+
name: this.$data.name ?? '',
|
|
452
|
+
address: this.$data.cancelEmailAddress ?? '',
|
|
454
453
|
},
|
|
455
|
-
},
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
454
|
+
},
|
|
455
|
+
locals: {
|
|
456
|
+
cancelLink: link,
|
|
457
|
+
oldEmail: this.$data.cancelEmailAddress,
|
|
458
|
+
newEmail: this.$data.newEmailAddress ?? this.$data.email,
|
|
459
|
+
},
|
|
460
|
+
}, this));
|
|
461
|
+
}
|
|
462
|
+
return success;
|
|
459
463
|
}
|
|
460
464
|
$addGroup(group) {
|
|
461
465
|
if (this.$data.groups == null) {
|
|
@@ -494,50 +498,45 @@ class User extends AbleObject_1.default {
|
|
|
494
498
|
return true;
|
|
495
499
|
}
|
|
496
500
|
$inGroup(group) {
|
|
497
|
-
var _a, _b, _c;
|
|
498
501
|
if (typeof group === 'string') {
|
|
499
|
-
if (
|
|
502
|
+
if (this.$data.group?.guid === group) {
|
|
500
503
|
return true;
|
|
501
504
|
}
|
|
502
|
-
for (let curGroup of
|
|
505
|
+
for (let curGroup of this.$data.groups ?? []) {
|
|
503
506
|
if (curGroup.guid === group) {
|
|
504
507
|
return true;
|
|
505
508
|
}
|
|
506
509
|
}
|
|
507
510
|
return false;
|
|
508
511
|
}
|
|
509
|
-
return (group.$is(this.$data.group) || group.$inArray(
|
|
512
|
+
return (group.$is(this.$data.group) || group.$inArray(this.$data.groups ?? []));
|
|
510
513
|
}
|
|
511
514
|
$isDescendant(group) {
|
|
512
|
-
|
|
513
|
-
if (((_a = this.$data.group) === null || _a === void 0 ? void 0 : _a.cdate) != null &&
|
|
515
|
+
if (this.$data.group?.cdate != null &&
|
|
514
516
|
this.$data.group.$isDescendant(group)) {
|
|
515
517
|
return true;
|
|
516
518
|
}
|
|
517
|
-
for (let curGroup of
|
|
519
|
+
for (let curGroup of this.$data.groups ?? []) {
|
|
518
520
|
if (curGroup.$isDescendant(group)) {
|
|
519
521
|
return true;
|
|
520
522
|
}
|
|
521
523
|
}
|
|
522
524
|
return false;
|
|
523
525
|
}
|
|
524
|
-
$changePassword(data) {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
return { result: false, message: "Couldn't save new password." };
|
|
539
|
-
}
|
|
540
|
-
});
|
|
526
|
+
async $changePassword(data) {
|
|
527
|
+
if (!('newPassword' in data) || !data.newPassword.length) {
|
|
528
|
+
return { result: false, message: 'Please specify a password.' };
|
|
529
|
+
}
|
|
530
|
+
if (!this.$checkPassword(data.currentPassword ?? '')) {
|
|
531
|
+
return { result: false, message: 'Incorrect password.' };
|
|
532
|
+
}
|
|
533
|
+
this.$data.passwordTemp = data.newPassword;
|
|
534
|
+
if (await this.$save()) {
|
|
535
|
+
return { result: true, message: 'Your password has been changed.' };
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
return { result: false, message: "Couldn't save new password." };
|
|
539
|
+
}
|
|
541
540
|
}
|
|
542
541
|
$password(password) {
|
|
543
542
|
const tilmeld = this.$nymph.tilmeld;
|
|
@@ -552,554 +551,574 @@ class User extends AbleObject_1.default {
|
|
|
552
551
|
break;
|
|
553
552
|
case 'salt':
|
|
554
553
|
default:
|
|
555
|
-
this.$data.salt = (0,
|
|
554
|
+
this.$data.salt = (0, guid_1.nanoid)();
|
|
556
555
|
this.$data.password = (0, sha256_1.default)(password + this.$data.salt).toString(enc_base64_1.default);
|
|
557
556
|
break;
|
|
558
557
|
}
|
|
559
558
|
return this.$data.password;
|
|
560
559
|
}
|
|
561
|
-
$checkUsername() {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
if (!
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
this.$data.username.length > tilmeld.config.maxUsernameLength) {
|
|
570
|
-
return {
|
|
571
|
-
result: false,
|
|
572
|
-
message: 'Usernames must not exceed ' +
|
|
573
|
-
tilmeld.config.maxUsernameLength +
|
|
574
|
-
' characters.',
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
if ((0, lodash_1.difference)(this.$data.username.split(''), tilmeld.config.validChars.split('')).length) {
|
|
578
|
-
return {
|
|
579
|
-
result: false,
|
|
580
|
-
message: tilmeld.config.validCharsNotice,
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
if (!tilmeld.config.validRegex.test(this.$data.username)) {
|
|
584
|
-
return {
|
|
585
|
-
result: false,
|
|
586
|
-
message: tilmeld.config.validRegexNotice,
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
const selector = {
|
|
590
|
-
type: '&',
|
|
591
|
-
ilike: [
|
|
592
|
-
'username',
|
|
593
|
-
this.$data.username.replace(/([\\%_])/g, (s) => `\\${s}`),
|
|
594
|
-
],
|
|
595
|
-
};
|
|
596
|
-
if (this.guid != null) {
|
|
597
|
-
selector['!guid'] = this.guid;
|
|
598
|
-
}
|
|
599
|
-
const test = yield this.$nymph.getEntity({ class: tilmeld.User, skipAc: true }, selector);
|
|
600
|
-
if (test != null) {
|
|
601
|
-
return { result: false, message: 'That username is taken.' };
|
|
602
|
-
}
|
|
560
|
+
async $checkUsername() {
|
|
561
|
+
const tilmeld = this.$nymph.tilmeld;
|
|
562
|
+
if (!tilmeld.config.emailUsernames) {
|
|
563
|
+
if (this.$data.username == null || !this.$data.username.length) {
|
|
564
|
+
return { result: false, message: 'Please specify a username.' };
|
|
565
|
+
}
|
|
566
|
+
if (tilmeld.config.maxUsernameLength > 0 &&
|
|
567
|
+
this.$data.username.length > tilmeld.config.maxUsernameLength) {
|
|
603
568
|
return {
|
|
604
|
-
result:
|
|
605
|
-
message:
|
|
569
|
+
result: false,
|
|
570
|
+
message: 'Usernames must not exceed ' +
|
|
571
|
+
tilmeld.config.maxUsernameLength +
|
|
572
|
+
' characters.',
|
|
606
573
|
};
|
|
607
574
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
}
|
|
613
|
-
if (tilmeld.config.maxUsernameLength > 0 &&
|
|
614
|
-
this.$data.username.length > tilmeld.config.maxUsernameLength) {
|
|
615
|
-
return {
|
|
616
|
-
result: false,
|
|
617
|
-
message: 'Emails must not exceed ' +
|
|
618
|
-
tilmeld.config.maxUsernameLength +
|
|
619
|
-
' characters.',
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
return yield this.$checkEmail();
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
$checkEmail() {
|
|
627
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
628
|
-
const tilmeld = this.$nymph.tilmeld;
|
|
629
|
-
if (this.$data.email == null || !this.$data.email.length) {
|
|
630
|
-
if (tilmeld.config.verifyEmail) {
|
|
631
|
-
return { result: false, message: 'Please specify an email.' };
|
|
632
|
-
}
|
|
633
|
-
else {
|
|
634
|
-
return { result: true, message: '' };
|
|
635
|
-
}
|
|
575
|
+
if ((0, lodash_1.difference)(this.$data.username.split(''), tilmeld.config.validChars.split('')).length) {
|
|
576
|
+
return {
|
|
577
|
+
result: false,
|
|
578
|
+
message: tilmeld.config.validCharsNotice,
|
|
579
|
+
};
|
|
636
580
|
}
|
|
637
|
-
if (!tilmeld.config.
|
|
581
|
+
if (!tilmeld.config.validRegex.test(this.$data.username)) {
|
|
638
582
|
return {
|
|
639
583
|
result: false,
|
|
640
|
-
message: tilmeld.config.
|
|
584
|
+
message: tilmeld.config.validRegexNotice,
|
|
641
585
|
};
|
|
642
586
|
}
|
|
643
587
|
const selector = {
|
|
644
588
|
type: '&',
|
|
645
|
-
ilike: [
|
|
589
|
+
ilike: [
|
|
590
|
+
'username',
|
|
591
|
+
this.$data.username.replace(/([\\%_])/g, (s) => `\\${s}`),
|
|
592
|
+
],
|
|
646
593
|
};
|
|
647
594
|
if (this.guid != null) {
|
|
648
595
|
selector['!guid'] = this.guid;
|
|
649
596
|
}
|
|
650
|
-
const test =
|
|
597
|
+
const test = await this.$nymph.getEntity({ class: tilmeld.User, skipAc: true }, selector);
|
|
651
598
|
if (test != null) {
|
|
652
|
-
return {
|
|
653
|
-
result: false,
|
|
654
|
-
message: 'That email address is already registered.',
|
|
655
|
-
};
|
|
599
|
+
return { result: false, message: 'That username is taken.' };
|
|
656
600
|
}
|
|
657
601
|
return {
|
|
658
602
|
result: true,
|
|
659
|
-
message: this.guid != null ? '
|
|
603
|
+
message: this.guid != null ? 'Username is valid.' : 'Username is available!',
|
|
660
604
|
};
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
if (this.$data.phone == null || !this.$data.phone.length) {
|
|
667
|
-
return { result: false, message: 'Please specify a phone number.' };
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
this.$data.email = this.$data.username;
|
|
608
|
+
if (this.$data.username == null || !this.$data.username.length) {
|
|
609
|
+
return { result: false, message: 'Please specify an email.' };
|
|
668
610
|
}
|
|
669
|
-
|
|
670
|
-
|
|
611
|
+
if (tilmeld.config.maxUsernameLength > 0 &&
|
|
612
|
+
this.$data.username.length > tilmeld.config.maxUsernameLength) {
|
|
671
613
|
return {
|
|
672
614
|
result: false,
|
|
673
|
-
message: '
|
|
615
|
+
message: 'Emails must not exceed ' +
|
|
616
|
+
tilmeld.config.maxUsernameLength +
|
|
617
|
+
' characters.',
|
|
674
618
|
};
|
|
675
619
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
620
|
+
return await this.$checkEmail();
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
async $checkEmail() {
|
|
624
|
+
const tilmeld = this.$nymph.tilmeld;
|
|
625
|
+
if (this.$data.email == null || !this.$data.email.length) {
|
|
626
|
+
if (tilmeld.config.verifyEmail) {
|
|
627
|
+
return { result: false, message: 'Please specify an email.' };
|
|
682
628
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
return { result: false, message: 'Phone number is in use.' };
|
|
629
|
+
else {
|
|
630
|
+
return { result: true, message: '' };
|
|
686
631
|
}
|
|
632
|
+
}
|
|
633
|
+
if (!tilmeld.config.validEmailRegex.test(this.$data.email)) {
|
|
687
634
|
return {
|
|
688
|
-
result:
|
|
689
|
-
message:
|
|
635
|
+
result: false,
|
|
636
|
+
message: tilmeld.config.validEmailRegexNotice,
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
const selector = {
|
|
640
|
+
type: '&',
|
|
641
|
+
ilike: ['email', this.$data.email.replace(/([\\%_])/g, (s) => `\\${s}`)],
|
|
642
|
+
};
|
|
643
|
+
if (this.guid != null) {
|
|
644
|
+
selector['!guid'] = this.guid;
|
|
645
|
+
}
|
|
646
|
+
const test = await this.$nymph.getEntity({ class: tilmeld.User, skipAc: true }, selector);
|
|
647
|
+
if (test != null) {
|
|
648
|
+
return {
|
|
649
|
+
result: false,
|
|
650
|
+
message: 'That email address is already registered.',
|
|
690
651
|
};
|
|
691
|
-
}
|
|
652
|
+
}
|
|
653
|
+
return {
|
|
654
|
+
result: true,
|
|
655
|
+
message: this.guid != null ? 'Email is valid.' : 'Email address is valid!',
|
|
656
|
+
};
|
|
692
657
|
}
|
|
693
|
-
$
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
658
|
+
async $checkPhone() {
|
|
659
|
+
const tilmeld = this.$nymph.tilmeld;
|
|
660
|
+
if (this.$data.phone == null || !this.$data.phone.length) {
|
|
661
|
+
return { result: false, message: 'Please specify a phone number.' };
|
|
662
|
+
}
|
|
663
|
+
const stripToDigits = this.$data.phone.replace(/\D/g, () => '');
|
|
664
|
+
if (!/\d{10}/.test(stripToDigits)) {
|
|
665
|
+
return {
|
|
666
|
+
result: false,
|
|
667
|
+
message: 'Phone must contain at least 10 digits, but formatting does not matter.',
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
const selector = {
|
|
671
|
+
type: '&',
|
|
672
|
+
equal: ['phone', stripToDigits],
|
|
673
|
+
};
|
|
674
|
+
if (this.guid != null) {
|
|
675
|
+
selector['!guid'] = this.guid;
|
|
676
|
+
}
|
|
677
|
+
const test = await this.$nymph.getEntity({ class: tilmeld.User, skipAc: true }, selector);
|
|
678
|
+
if (test != null) {
|
|
679
|
+
return { result: false, message: 'Phone number is in use.' };
|
|
680
|
+
}
|
|
681
|
+
return {
|
|
682
|
+
result: true,
|
|
683
|
+
message: this.guid != null ? 'Phone number is valid.' : 'Phone number is valid!',
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
async $register(data) {
|
|
687
|
+
let tilmeld = this.$nymph.tilmeld;
|
|
688
|
+
if (!tilmeld.config.allowRegistration) {
|
|
689
|
+
return {
|
|
690
|
+
result: false,
|
|
691
|
+
loggedin: false,
|
|
692
|
+
message: 'Registration is not allowed.',
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
if (this.guid != null) {
|
|
696
|
+
return {
|
|
697
|
+
result: false,
|
|
698
|
+
loggedin: false,
|
|
699
|
+
message: 'This is already a registered user.',
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
try {
|
|
703
|
+
for (let callback of this.constructor
|
|
704
|
+
.beforeRegisterCallbacks) {
|
|
705
|
+
if (callback) {
|
|
706
|
+
await callback(this, data);
|
|
707
|
+
}
|
|
702
708
|
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
+
}
|
|
710
|
+
catch (e) {
|
|
711
|
+
return {
|
|
712
|
+
result: false,
|
|
713
|
+
loggedin: false,
|
|
714
|
+
message: e.message,
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
if (!('password' in data) || !data.password.length) {
|
|
718
|
+
return {
|
|
719
|
+
result: false,
|
|
720
|
+
loggedin: false,
|
|
721
|
+
message: 'Password is a required field.',
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
const unCheck = await this.$checkUsername();
|
|
725
|
+
if (!unCheck.result) {
|
|
726
|
+
return { ...unCheck, loggedin: false };
|
|
727
|
+
}
|
|
728
|
+
this.$password(data.password);
|
|
729
|
+
if (tilmeld.config.regFields.indexOf('name') !== -1) {
|
|
730
|
+
this.$data.name =
|
|
731
|
+
this.$data.nameFirst +
|
|
732
|
+
(this.$data.nameMiddle == null ? '' : ' ' + this.$data.nameMiddle) +
|
|
733
|
+
(this.$data.nameLast == null ? '' : ' ' + this.$data.nameLast);
|
|
734
|
+
if (this.$data.name === '') {
|
|
735
|
+
this.$data.name = this.$data.username;
|
|
709
736
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
737
|
+
}
|
|
738
|
+
if (tilmeld.config.emailUsernames) {
|
|
739
|
+
this.$data.email = this.$data.username;
|
|
740
|
+
}
|
|
741
|
+
const transaction = 'tilmeld-register-' + (0, guid_1.nanoid)();
|
|
742
|
+
const nymph = this.$nymph;
|
|
743
|
+
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
744
|
+
this.$nymph = tnymph;
|
|
745
|
+
tilmeld = this.$nymph.tilmeld;
|
|
746
|
+
try {
|
|
747
|
+
let generatedPrimaryGroup = null;
|
|
748
|
+
if (tilmeld.config.generatePrimary) {
|
|
749
|
+
generatedPrimaryGroup = await tilmeld.Group.factory();
|
|
750
|
+
generatedPrimaryGroup.groupname = this.$data.username;
|
|
751
|
+
generatedPrimaryGroup.avatar = this.$data.avatar;
|
|
752
|
+
generatedPrimaryGroup.name = this.$data.name;
|
|
753
|
+
generatedPrimaryGroup.email = this.$data.email;
|
|
754
|
+
const parent = await tnymph.getEntity({ class: tilmeld.Group }, {
|
|
755
|
+
type: '&',
|
|
756
|
+
equal: ['defaultPrimary', true],
|
|
757
|
+
});
|
|
758
|
+
if (parent != null) {
|
|
759
|
+
generatedPrimaryGroup.parent = parent;
|
|
760
|
+
}
|
|
761
|
+
if (!(await generatedPrimaryGroup.$saveSkipAC())) {
|
|
762
|
+
await tnymph.rollback(transaction);
|
|
763
|
+
this.$nymph = nymph;
|
|
764
|
+
return {
|
|
765
|
+
result: false,
|
|
766
|
+
loggedin: false,
|
|
767
|
+
message: 'Error creating primary group for user.',
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
this.$data.group = generatedPrimaryGroup;
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
const group = await tnymph.getEntity({ class: tilmeld.Group }, {
|
|
774
|
+
type: '&',
|
|
775
|
+
equal: ['defaultPrimary', true],
|
|
776
|
+
});
|
|
777
|
+
if (group != null) {
|
|
778
|
+
this.$data.group = group;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
if (tilmeld.config.verifyEmail && tilmeld.config.unverifiedAccess) {
|
|
782
|
+
this.$data.groups = await tnymph.getEntities({ class: tilmeld.Group }, {
|
|
783
|
+
type: '&',
|
|
784
|
+
equal: ['unverifiedSecondary', true],
|
|
785
|
+
});
|
|
716
786
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
787
|
+
else {
|
|
788
|
+
this.$data.groups = await tnymph.getEntities({ class: tilmeld.Group }, {
|
|
789
|
+
type: '&',
|
|
790
|
+
equal: ['defaultSecondary', true],
|
|
791
|
+
});
|
|
720
792
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
this.$data.nameFirst +
|
|
725
|
-
(this.$data.nameMiddle == null ? '' : ' ' + this.$data.nameMiddle) +
|
|
726
|
-
(this.$data.nameLast == null ? '' : ' ' + this.$data.nameLast);
|
|
727
|
-
if (this.$data.name === '') {
|
|
728
|
-
this.$data.name = this.$data.username;
|
|
793
|
+
if (tilmeld.config.verifyEmail) {
|
|
794
|
+
if (!tilmeld.config.unverifiedAccess) {
|
|
795
|
+
this.$data.enabled = false;
|
|
729
796
|
}
|
|
730
797
|
}
|
|
731
|
-
|
|
732
|
-
this.$data.
|
|
798
|
+
else {
|
|
799
|
+
this.$data.enabled = true;
|
|
800
|
+
}
|
|
801
|
+
let madeAdmin = false;
|
|
802
|
+
if (tilmeld.config.createAdmin) {
|
|
803
|
+
const otherUsers = await tnymph.getEntities({
|
|
804
|
+
class: tilmeld.User,
|
|
805
|
+
skipAc: true,
|
|
806
|
+
limit: 1,
|
|
807
|
+
return: 'guid',
|
|
808
|
+
});
|
|
809
|
+
if (!otherUsers.length) {
|
|
810
|
+
this.$grant('system/admin');
|
|
811
|
+
this.$data.enabled = true;
|
|
812
|
+
madeAdmin = true;
|
|
813
|
+
}
|
|
733
814
|
}
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
});
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
815
|
+
if (await this.$saveSkipAC()) {
|
|
816
|
+
if (tilmeld.config.userRegisteredRecipient != null) {
|
|
817
|
+
await tilmeld.config.sendEmail(tilmeld, {
|
|
818
|
+
template: 'UserRegistered',
|
|
819
|
+
message: {
|
|
820
|
+
to: tilmeld.config.userRegisteredRecipient,
|
|
821
|
+
},
|
|
822
|
+
locals: {
|
|
823
|
+
userUsername: this.$data.username,
|
|
824
|
+
userName: this.$data.name,
|
|
825
|
+
userFirstName: this.$data.nameFirst,
|
|
826
|
+
userLastName: this.$data.nameLast,
|
|
827
|
+
userEmail: this.$data.email,
|
|
828
|
+
userPhone: this.$data.phone,
|
|
829
|
+
},
|
|
830
|
+
}, this);
|
|
831
|
+
}
|
|
832
|
+
let message = '';
|
|
833
|
+
let loggedin = false;
|
|
834
|
+
if (generatedPrimaryGroup != null) {
|
|
835
|
+
generatedPrimaryGroup.user = this;
|
|
836
|
+
if (!(await generatedPrimaryGroup.$saveSkipAC())) {
|
|
837
|
+
await tnymph.rollback(transaction);
|
|
755
838
|
this.$nymph = nymph;
|
|
756
839
|
return {
|
|
757
840
|
result: false,
|
|
758
841
|
loggedin: false,
|
|
759
|
-
message: '
|
|
842
|
+
message: 'Your primary group could not be assigned. Please try again later.',
|
|
760
843
|
};
|
|
761
844
|
}
|
|
762
|
-
this.$data.group = generatedPrimaryGroup;
|
|
763
|
-
}
|
|
764
|
-
else {
|
|
765
|
-
const group = yield tnymph.getEntity({ class: tilmeld.Group }, {
|
|
766
|
-
type: '&',
|
|
767
|
-
equal: ['defaultPrimary', true],
|
|
768
|
-
});
|
|
769
|
-
if (group != null) {
|
|
770
|
-
this.$data.group = group;
|
|
771
|
-
}
|
|
772
845
|
}
|
|
773
|
-
if (tilmeld.config.verifyEmail &&
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
else {
|
|
780
|
-
this.$data.groups = yield tnymph.getEntities({ class: tilmeld.Group }, {
|
|
781
|
-
type: '&',
|
|
782
|
-
equal: ['defaultSecondary', true],
|
|
783
|
-
});
|
|
846
|
+
if (tilmeld.config.verifyEmail &&
|
|
847
|
+
!tilmeld.config.unverifiedAccess &&
|
|
848
|
+
!madeAdmin) {
|
|
849
|
+
message +=
|
|
850
|
+
`Almost there. An email has been sent to ${this.$data.email} ` +
|
|
851
|
+
'with a verification link for you to finish registration.';
|
|
784
852
|
}
|
|
785
|
-
if (tilmeld.config.verifyEmail
|
|
786
|
-
|
|
787
|
-
|
|
853
|
+
else if (tilmeld.config.verifyEmail &&
|
|
854
|
+
tilmeld.config.unverifiedAccess &&
|
|
855
|
+
!madeAdmin) {
|
|
856
|
+
if (!tilmeld.login(this, true)) {
|
|
857
|
+
throw new Error('An error occurred trying to log you in.');
|
|
788
858
|
}
|
|
859
|
+
message +=
|
|
860
|
+
"You're now logged in! An email has been sent to " +
|
|
861
|
+
`${this.$data.email} with a verification link for you to finish ` +
|
|
862
|
+
'registration.';
|
|
863
|
+
loggedin = true;
|
|
789
864
|
}
|
|
790
865
|
else {
|
|
791
|
-
this
|
|
792
|
-
|
|
793
|
-
let madeAdmin = false;
|
|
794
|
-
if (tilmeld.config.createAdmin) {
|
|
795
|
-
const otherUsers = yield tnymph.getEntities({
|
|
796
|
-
class: tilmeld.User,
|
|
797
|
-
skipAc: true,
|
|
798
|
-
limit: 1,
|
|
799
|
-
return: 'guid',
|
|
800
|
-
});
|
|
801
|
-
if (!otherUsers.length) {
|
|
802
|
-
this.$grant('system/admin');
|
|
803
|
-
this.$data.enabled = true;
|
|
804
|
-
madeAdmin = true;
|
|
866
|
+
if (!tilmeld.login(this, true)) {
|
|
867
|
+
throw new Error('An error occurred trying to log you in.');
|
|
805
868
|
}
|
|
869
|
+
message += "You're now registered and logged in!";
|
|
870
|
+
loggedin = true;
|
|
806
871
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
locals: {
|
|
815
|
-
userUsername: this.$data.username,
|
|
816
|
-
userName: this.$data.name,
|
|
817
|
-
userFirstName: this.$data.nameFirst,
|
|
818
|
-
userLastName: this.$data.nameLast,
|
|
819
|
-
userEmail: this.$data.email,
|
|
820
|
-
userPhone: this.$data.phone,
|
|
821
|
-
},
|
|
822
|
-
}, this);
|
|
823
|
-
}
|
|
824
|
-
let message = '';
|
|
825
|
-
let loggedin = false;
|
|
826
|
-
if (generatedPrimaryGroup != null) {
|
|
827
|
-
generatedPrimaryGroup.user = this;
|
|
828
|
-
if (!(yield generatedPrimaryGroup.$saveSkipAC())) {
|
|
829
|
-
yield tnymph.rollback(transaction);
|
|
830
|
-
this.$nymph = nymph;
|
|
831
|
-
return {
|
|
832
|
-
result: false,
|
|
833
|
-
loggedin: false,
|
|
834
|
-
message: 'Your primary group could not be assigned. Please try again later.',
|
|
835
|
-
};
|
|
836
|
-
}
|
|
872
|
+
for (let callback of this.constructor
|
|
873
|
+
.afterRegisterCallbacks) {
|
|
874
|
+
if (callback) {
|
|
875
|
+
await callback(this, {
|
|
876
|
+
loggedin,
|
|
877
|
+
message,
|
|
878
|
+
});
|
|
837
879
|
}
|
|
838
|
-
if (tilmeld.config.verifyEmail &&
|
|
839
|
-
!tilmeld.config.unverifiedAccess &&
|
|
840
|
-
!madeAdmin) {
|
|
841
|
-
message +=
|
|
842
|
-
`Almost there. An email has been sent to ${this.$data.email} ` +
|
|
843
|
-
'with a verification link for you to finish registration.';
|
|
844
|
-
}
|
|
845
|
-
else if (tilmeld.config.verifyEmail &&
|
|
846
|
-
tilmeld.config.unverifiedAccess &&
|
|
847
|
-
!madeAdmin) {
|
|
848
|
-
tilmeld.login(this, true);
|
|
849
|
-
message +=
|
|
850
|
-
"You're now logged in! An email has been sent to " +
|
|
851
|
-
`${this.$data.email} with a verification link for you to finish ` +
|
|
852
|
-
'registration.';
|
|
853
|
-
loggedin = true;
|
|
854
|
-
}
|
|
855
|
-
else {
|
|
856
|
-
tilmeld.login(this, true);
|
|
857
|
-
message += "You're now registered and logged in!";
|
|
858
|
-
loggedin = true;
|
|
859
|
-
}
|
|
860
|
-
yield tnymph.commit(transaction);
|
|
861
|
-
this.$nymph = nymph;
|
|
862
|
-
return {
|
|
863
|
-
result: true,
|
|
864
|
-
loggedin,
|
|
865
|
-
message,
|
|
866
|
-
};
|
|
867
880
|
}
|
|
868
|
-
|
|
869
|
-
|
|
881
|
+
try {
|
|
882
|
+
await tnymph.commit(transaction);
|
|
870
883
|
this.$nymph = nymph;
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
};
|
|
884
|
+
this.$nymph.tilmeld?.fillSession(this);
|
|
885
|
+
}
|
|
886
|
+
catch (e) {
|
|
887
|
+
throw e;
|
|
876
888
|
}
|
|
889
|
+
return {
|
|
890
|
+
result: true,
|
|
891
|
+
loggedin,
|
|
892
|
+
message,
|
|
893
|
+
};
|
|
877
894
|
}
|
|
878
|
-
|
|
879
|
-
|
|
895
|
+
else {
|
|
896
|
+
await tnymph.rollback(transaction);
|
|
880
897
|
this.$nymph = nymph;
|
|
881
|
-
|
|
898
|
+
return {
|
|
899
|
+
result: false,
|
|
900
|
+
loggedin: false,
|
|
901
|
+
message: 'Error registering user.',
|
|
902
|
+
};
|
|
882
903
|
}
|
|
883
|
-
}
|
|
904
|
+
}
|
|
905
|
+
catch (e) {
|
|
906
|
+
await tnymph.rollback(transaction);
|
|
907
|
+
this.$nymph = nymph;
|
|
908
|
+
throw e;
|
|
909
|
+
}
|
|
884
910
|
}
|
|
885
|
-
$save() {
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
this.$data.nameFirst
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
const
|
|
969
|
-
if (!
|
|
970
|
-
throw new errors_1.
|
|
911
|
+
async $save() {
|
|
912
|
+
let tilmeld = this.$nymph.tilmeld;
|
|
913
|
+
if (this.$data.username == null || !this.$data.username.trim().length) {
|
|
914
|
+
return false;
|
|
915
|
+
}
|
|
916
|
+
if (tilmeld.gatekeeper('tilmeld/admin') &&
|
|
917
|
+
!tilmeld.gatekeeper('system/admin') &&
|
|
918
|
+
this.$gatekeeper('system/admin')) {
|
|
919
|
+
throw new errors_1.BadDataError("You don't have the authority to modify system admins.");
|
|
920
|
+
}
|
|
921
|
+
let sendVerification = false;
|
|
922
|
+
this.$data.username = this.$data.username.trim();
|
|
923
|
+
if (tilmeld.config.emailUsernames) {
|
|
924
|
+
this.$data.email = this.$data.username;
|
|
925
|
+
}
|
|
926
|
+
this.$data.nameFirst = (this.$data.nameFirst ?? '').trim();
|
|
927
|
+
this.$data.nameMiddle = (this.$data.nameMiddle ?? '').trim();
|
|
928
|
+
this.$data.nameLast = (this.$data.nameLast ?? '').trim();
|
|
929
|
+
this.$data.phone = (this.$data.phone ?? '').trim();
|
|
930
|
+
this.$data.name =
|
|
931
|
+
this.$data.nameFirst +
|
|
932
|
+
(this.$data.nameMiddle ? ' ' + this.$data.nameMiddle : '') +
|
|
933
|
+
(this.$data.nameLast ? ' ' + this.$data.nameLast : '');
|
|
934
|
+
this.$data.enabled = !!this.$data.enabled;
|
|
935
|
+
if (this.$data.nameFirst === '') {
|
|
936
|
+
delete this.$data.nameFirst;
|
|
937
|
+
}
|
|
938
|
+
if (this.$data.nameMiddle === '') {
|
|
939
|
+
delete this.$data.nameMiddle;
|
|
940
|
+
}
|
|
941
|
+
if (this.$data.nameLast === '') {
|
|
942
|
+
delete this.$data.nameLast;
|
|
943
|
+
}
|
|
944
|
+
if (this.$data.name === '') {
|
|
945
|
+
delete this.$data.name;
|
|
946
|
+
}
|
|
947
|
+
if (this.$data.email === '') {
|
|
948
|
+
delete this.$data.email;
|
|
949
|
+
}
|
|
950
|
+
if (this.$data.avatar === '') {
|
|
951
|
+
delete this.$data.avatar;
|
|
952
|
+
}
|
|
953
|
+
if (this.$data.phone === '') {
|
|
954
|
+
delete this.$data.phone;
|
|
955
|
+
}
|
|
956
|
+
if (this.$data.secret === '') {
|
|
957
|
+
delete this.$data.secret;
|
|
958
|
+
}
|
|
959
|
+
if (this.$data.emailChangeDate === 0) {
|
|
960
|
+
delete this.$data.emailChangeDate;
|
|
961
|
+
}
|
|
962
|
+
if (this.$data.newEmailSecret === '') {
|
|
963
|
+
delete this.$data.newEmailSecret;
|
|
964
|
+
}
|
|
965
|
+
if (this.$data.newEmailAddress === '') {
|
|
966
|
+
delete this.$data.newEmailAddress;
|
|
967
|
+
}
|
|
968
|
+
if (this.$data.cancelEmailSecret === '') {
|
|
969
|
+
delete this.$data.cancelEmailSecret;
|
|
970
|
+
}
|
|
971
|
+
if (this.$data.cancelEmailAddress === '') {
|
|
972
|
+
delete this.$data.cancelEmailAddress;
|
|
973
|
+
}
|
|
974
|
+
if (this.$data.recoverSecret === '') {
|
|
975
|
+
delete this.$data.recoverSecret;
|
|
976
|
+
}
|
|
977
|
+
if (this.$data.recoverSecretDate === 0) {
|
|
978
|
+
delete this.$data.recoverSecretDate;
|
|
979
|
+
}
|
|
980
|
+
if (this.$data.password === '') {
|
|
981
|
+
delete this.$data.password;
|
|
982
|
+
}
|
|
983
|
+
if (this.$data.passwordTemp === '') {
|
|
984
|
+
delete this.$data.passwordTemp;
|
|
985
|
+
}
|
|
986
|
+
if (this.$data.inheritAbilities === false) {
|
|
987
|
+
delete this.$data.inheritAbilities;
|
|
988
|
+
}
|
|
989
|
+
const unCheck = await this.$checkUsername();
|
|
990
|
+
if (!unCheck.result) {
|
|
991
|
+
throw new errors_1.BadUsernameError(unCheck.message);
|
|
992
|
+
}
|
|
993
|
+
if (!tilmeld.config.emailUsernames) {
|
|
994
|
+
const emCheck = await this.$checkEmail();
|
|
995
|
+
if (!emCheck.result) {
|
|
996
|
+
throw new errors_1.BadEmailError(emCheck.message);
|
|
971
997
|
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
998
|
+
}
|
|
999
|
+
if (!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
1000
|
+
if (tilmeld.config.verifyEmail) {
|
|
1001
|
+
if (this.guid == null) {
|
|
1002
|
+
if ((this.$data.abilities?.indexOf('system/admin') ?? -1) === -1) {
|
|
1003
|
+
this.$data.secret = (0, guid_1.nanoid)();
|
|
1004
|
+
sendVerification = true;
|
|
1005
|
+
}
|
|
976
1006
|
}
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1007
|
+
else if (this.$originalEmail != null &&
|
|
1008
|
+
this.$originalEmail !== this.$data.email) {
|
|
1009
|
+
if (tilmeld.config.emailRateLimit !== '' &&
|
|
1010
|
+
this.$data.emailChangeDate != null &&
|
|
1011
|
+
this.$data.emailChangeDate >=
|
|
1012
|
+
(0, strtotime_1.default)('-' + tilmeld.config.emailRateLimit) * 1000) {
|
|
1013
|
+
throw new errors_1.EmailChangeRateLimitExceededError('You already changed your email address recently. Please wait until ' +
|
|
1014
|
+
new Date((0, strtotime_1.default)('+' + tilmeld.config.emailRateLimit, Math.floor(this.$data.emailChangeDate / 1000)) * 1000).toString() +
|
|
1015
|
+
' to change your email address again.');
|
|
985
1016
|
}
|
|
986
|
-
else
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
this.$data.emailChangeDate
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1017
|
+
else {
|
|
1018
|
+
if (this.$data.newEmailSecret == null &&
|
|
1019
|
+
tilmeld.config.emailRateLimit !== '' &&
|
|
1020
|
+
(this.$data.emailChangeDate == null ||
|
|
1021
|
+
this.$data.emailChangeDate <
|
|
1022
|
+
(0, strtotime_1.default)('-' + tilmeld.config.emailRateLimit) * 1000)) {
|
|
1023
|
+
this.$data.cancelEmailAddress = this.$originalEmail;
|
|
1024
|
+
this.$data.cancelEmailSecret = (0, guid_1.nanoid)();
|
|
1025
|
+
this.$data.emailChangeDate = Date.now();
|
|
995
1026
|
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
this.$data.emailChangeDate <
|
|
1001
|
-
(0, strtotime_1.default)('-' + tilmeld.config.emailRateLimit) * 1000)) {
|
|
1002
|
-
this.$data.cancelEmailAddress = this.$originalEmail;
|
|
1003
|
-
this.$data.cancelEmailSecret = (0, nanoid_1.nanoid)();
|
|
1004
|
-
this.$data.emailChangeDate = Date.now();
|
|
1005
|
-
}
|
|
1006
|
-
this.$data.newEmailAddress = this.$data.email;
|
|
1007
|
-
this.$data.email = this.$originalEmail;
|
|
1008
|
-
if (tilmeld.config.emailUsernames) {
|
|
1009
|
-
this.$data.username = this.$data.email;
|
|
1010
|
-
}
|
|
1011
|
-
this.$data.newEmailSecret = (0, nanoid_1.nanoid)();
|
|
1012
|
-
sendVerification = true;
|
|
1027
|
+
this.$data.newEmailAddress = this.$data.email;
|
|
1028
|
+
this.$data.email = this.$originalEmail;
|
|
1029
|
+
if (tilmeld.config.emailUsernames) {
|
|
1030
|
+
this.$data.username = this.$data.email;
|
|
1013
1031
|
}
|
|
1032
|
+
this.$data.newEmailSecret = (0, guid_1.nanoid)();
|
|
1033
|
+
sendVerification = true;
|
|
1014
1034
|
}
|
|
1015
1035
|
}
|
|
1016
|
-
else if (this.guid != null &&
|
|
1017
|
-
this.$originalEmail != null &&
|
|
1018
|
-
this.$originalEmail !== this.$data.email &&
|
|
1019
|
-
(this.$data.emailChangeDate == null ||
|
|
1020
|
-
this.$data.emailChangeDate <
|
|
1021
|
-
(0, strtotime_1.default)('-' + tilmeld.config.emailRateLimit) * 1000)) {
|
|
1022
|
-
this.$data.cancelEmailAddress = this.$originalEmail;
|
|
1023
|
-
this.$data.cancelEmailSecret = (0, nanoid_1.nanoid)();
|
|
1024
|
-
sendVerification = true;
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
if (this.$data.passwordTemp != null) {
|
|
1028
|
-
this.$password(this.$data.passwordTemp);
|
|
1029
1036
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1037
|
+
else if (this.guid != null &&
|
|
1038
|
+
this.$originalEmail != null &&
|
|
1039
|
+
this.$originalEmail !== this.$data.email &&
|
|
1040
|
+
(this.$data.emailChangeDate == null ||
|
|
1041
|
+
this.$data.emailChangeDate <
|
|
1042
|
+
(0, strtotime_1.default)('-' + tilmeld.config.emailRateLimit) * 1000)) {
|
|
1043
|
+
this.$data.cancelEmailAddress = this.$originalEmail;
|
|
1044
|
+
this.$data.cancelEmailSecret = (0, guid_1.nanoid)();
|
|
1045
|
+
sendVerification = true;
|
|
1033
1046
|
}
|
|
1047
|
+
}
|
|
1048
|
+
if (this.$data.passwordTemp != null) {
|
|
1049
|
+
this.$password(this.$data.passwordTemp);
|
|
1050
|
+
}
|
|
1051
|
+
delete this.$data.passwordTemp;
|
|
1052
|
+
if (this.$data.password == null) {
|
|
1053
|
+
throw new errors_1.BadDataError('A password is required.');
|
|
1054
|
+
}
|
|
1055
|
+
try {
|
|
1056
|
+
tilmeld.config.validatorUser(this);
|
|
1057
|
+
}
|
|
1058
|
+
catch (e) {
|
|
1059
|
+
throw new errors_1.BadDataError(e?.message);
|
|
1060
|
+
}
|
|
1061
|
+
const transaction = 'tilmeld-save-' + (0, guid_1.nanoid)();
|
|
1062
|
+
const nymph = this.$nymph;
|
|
1063
|
+
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
1064
|
+
this.$nymph = tnymph;
|
|
1065
|
+
tilmeld = this.$nymph.tilmeld;
|
|
1066
|
+
if (this.$data.group != null &&
|
|
1067
|
+
this.$data.group.user != null &&
|
|
1068
|
+
this.$is(this.$data.group.user)) {
|
|
1034
1069
|
try {
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
const nymph = this.$nymph;
|
|
1042
|
-
const tnymph = yield this.$nymph.startTransaction(transaction);
|
|
1043
|
-
this.$nymph = tnymph;
|
|
1044
|
-
if (this.$data.group != null &&
|
|
1045
|
-
this.$data.group.user != null &&
|
|
1046
|
-
this.$is(this.$data.group.user)) {
|
|
1047
|
-
try {
|
|
1048
|
-
this.$data.group.groupname = this.$data.username;
|
|
1049
|
-
this.$data.group.avatar = this.$data.avatar;
|
|
1050
|
-
this.$data.group.email = this.$data.email;
|
|
1051
|
-
this.$data.group.name = this.$data.name;
|
|
1052
|
-
this.$data.group.phone = this.$data.phone;
|
|
1053
|
-
yield this.$data.group.$saveSkipAC();
|
|
1054
|
-
}
|
|
1055
|
-
catch (e) {
|
|
1056
|
-
yield tnymph.rollback(transaction);
|
|
1057
|
-
this.$nymph = nymph;
|
|
1058
|
-
throw e;
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
let ret;
|
|
1062
|
-
let preGuid = this.guid;
|
|
1063
|
-
let preCdate = this.cdate;
|
|
1064
|
-
let preMdate = this.mdate;
|
|
1065
|
-
try {
|
|
1066
|
-
ret = yield _super.$save.call(this);
|
|
1070
|
+
this.$data.group.groupname = this.$data.username;
|
|
1071
|
+
this.$data.group.avatar = this.$data.avatar;
|
|
1072
|
+
this.$data.group.email = this.$data.email;
|
|
1073
|
+
this.$data.group.name = this.$data.name;
|
|
1074
|
+
this.$data.group.phone = this.$data.phone;
|
|
1075
|
+
await this.$data.group.$saveSkipAC();
|
|
1067
1076
|
}
|
|
1068
1077
|
catch (e) {
|
|
1069
|
-
|
|
1078
|
+
await tnymph.rollback(transaction);
|
|
1070
1079
|
this.$nymph = nymph;
|
|
1071
1080
|
throw e;
|
|
1072
1081
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1082
|
+
}
|
|
1083
|
+
let ret;
|
|
1084
|
+
let preGuid = this.guid;
|
|
1085
|
+
let preCdate = this.cdate;
|
|
1086
|
+
let preMdate = this.mdate;
|
|
1087
|
+
try {
|
|
1088
|
+
ret = await super.$save();
|
|
1089
|
+
}
|
|
1090
|
+
catch (e) {
|
|
1091
|
+
await tnymph.rollback(transaction);
|
|
1092
|
+
this.$nymph = nymph;
|
|
1093
|
+
throw e;
|
|
1094
|
+
}
|
|
1095
|
+
if (ret) {
|
|
1096
|
+
if (sendVerification) {
|
|
1097
|
+
if (!(await this.$sendEmailVerification())) {
|
|
1098
|
+
await tnymph.rollback(transaction);
|
|
1099
|
+
this.guid = preGuid;
|
|
1100
|
+
this.cdate = preCdate;
|
|
1101
|
+
this.mdate = preMdate;
|
|
1102
|
+
this.$nymph = nymph;
|
|
1103
|
+
throw new Error("Couldn't send verification email.");
|
|
1086
1104
|
}
|
|
1087
|
-
this.$descendantGroups = undefined;
|
|
1088
|
-
this.$gatekeeperCache = undefined;
|
|
1089
|
-
yield tnymph.commit(transaction);
|
|
1090
1105
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1106
|
+
this.$descendantGroups = undefined;
|
|
1107
|
+
this.$gatekeeperCache = undefined;
|
|
1108
|
+
await tnymph.commit(transaction);
|
|
1109
|
+
if (nymph.tilmeld.User.current(true).$is(this)) {
|
|
1110
|
+
nymph.tilmeld.fillSession(this);
|
|
1093
1111
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1112
|
+
}
|
|
1113
|
+
else {
|
|
1114
|
+
await tnymph.rollback(transaction);
|
|
1115
|
+
}
|
|
1116
|
+
this.$nymph = nymph;
|
|
1117
|
+
return ret;
|
|
1097
1118
|
}
|
|
1098
|
-
$saveSkipAC() {
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
return yield this.$save();
|
|
1102
|
-
});
|
|
1119
|
+
async $saveSkipAC() {
|
|
1120
|
+
this.$skipAcWhenSaving = true;
|
|
1121
|
+
return await this.$save();
|
|
1103
1122
|
}
|
|
1104
1123
|
$tilmeldSaveSkipAC() {
|
|
1105
1124
|
if (this.$skipAcWhenSaving) {
|
|
@@ -1108,29 +1127,49 @@ class User extends AbleObject_1.default {
|
|
|
1108
1127
|
}
|
|
1109
1128
|
return false;
|
|
1110
1129
|
}
|
|
1111
|
-
$delete() {
|
|
1112
|
-
const
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1130
|
+
async $delete() {
|
|
1131
|
+
const tilmeld = this.$nymph.tilmeld;
|
|
1132
|
+
if (!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
1133
|
+
throw new errors_1.BadDataError("You don't have the authority to delete users.");
|
|
1134
|
+
}
|
|
1135
|
+
if (!tilmeld.gatekeeper('system/admin') &&
|
|
1136
|
+
this.$gatekeeper('system/admin')) {
|
|
1137
|
+
throw new errors_1.BadDataError("You don't have the authority to delete system admins.");
|
|
1138
|
+
}
|
|
1139
|
+
if (tilmeld.User.current(true).$is(this)) {
|
|
1140
|
+
this.$logout();
|
|
1141
|
+
}
|
|
1142
|
+
return await super.$delete();
|
|
1143
|
+
}
|
|
1144
|
+
static on(event, callback) {
|
|
1145
|
+
const prop = (event + 'Callbacks');
|
|
1146
|
+
if (!(prop in this)) {
|
|
1147
|
+
throw new Error('Invalid event type.');
|
|
1148
|
+
}
|
|
1149
|
+
this[prop].push(callback);
|
|
1150
|
+
return () => this.off(event, callback);
|
|
1151
|
+
}
|
|
1152
|
+
static off(event, callback) {
|
|
1153
|
+
const prop = (event + 'Callbacks');
|
|
1154
|
+
if (!(prop in this)) {
|
|
1155
|
+
return false;
|
|
1156
|
+
}
|
|
1157
|
+
const i = this[prop].indexOf(callback);
|
|
1158
|
+
if (i > -1) {
|
|
1159
|
+
this[prop].splice(i, 1);
|
|
1160
|
+
}
|
|
1161
|
+
return true;
|
|
1129
1162
|
}
|
|
1130
1163
|
}
|
|
1131
1164
|
exports.default = User;
|
|
1132
1165
|
User.ETYPE = 'tilmeld_user';
|
|
1133
1166
|
User.class = 'User';
|
|
1167
|
+
User.beforeRegisterCallbacks = [];
|
|
1168
|
+
User.afterRegisterCallbacks = [];
|
|
1169
|
+
User.beforeLoginCallbacks = [];
|
|
1170
|
+
User.afterLoginCallbacks = [];
|
|
1171
|
+
User.beforeLogoutCallbacks = [];
|
|
1172
|
+
User.afterLogoutCallbacks = [];
|
|
1134
1173
|
User.DEFAULT_CLIENT_ENABLED_METHODS = [
|
|
1135
1174
|
'$checkUsername',
|
|
1136
1175
|
'$checkEmail',
|