-
Notifications
You must be signed in to change notification settings - Fork 10.7k
/
registerUser.ts
155 lines (134 loc) · 4.45 KB
/
registerUser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import type { IUser } from '@rocket.chat/core-typings';
import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
import { Accounts } from 'meteor/accounts-base';
import { Match, check } from 'meteor/check';
import { DDPRateLimiter } from 'meteor/ddp-rate-limiter';
import { Meteor } from 'meteor/meteor';
import { validateInviteToken } from '../../app/invites/server/functions/validateInviteToken';
import { validateEmailDomain, passwordPolicy, RateLimiter } from '../../app/lib/server';
import { settings } from '../../app/settings/server';
import { trim } from '../../lib/utils/stringUtils';
declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
registerUser(
formData:
| { email: string; pass: string; username: IUser['username']; name: string; secretURL?: string; reason?: string }
| { email?: null },
):
| {
token: string;
when: Date;
}
| string;
}
}
Meteor.methods<ServerMethods>({
async registerUser(formData) {
const AllowAnonymousRead = settings.get<boolean>('Accounts_AllowAnonymousRead');
const AllowAnonymousWrite = settings.get<boolean>('Accounts_AllowAnonymousWrite');
const manuallyApproveNewUsers = settings.get<boolean>('Accounts_ManuallyApproveNewUsers');
if (AllowAnonymousRead === true && AllowAnonymousWrite === true && !formData.email) {
const userId = await Accounts.insertUserDoc(
{},
{
globalRoles: ['anonymous'],
active: true,
},
);
const stampedLoginToken = await Accounts._generateStampedLoginToken();
await Accounts._insertLoginToken(userId, stampedLoginToken);
return stampedLoginToken;
}
check(
formData,
Match.ObjectIncluding({
email: String,
pass: String,
name: String,
secretURL: Match.Optional(String),
reason: Match.Optional(String),
}),
);
if (settings.get('Accounts_RegistrationForm') === 'Disabled') {
throw new Meteor.Error('error-user-registration-disabled', 'User registration is disabled', {
method: 'registerUser',
});
}
if (
settings.get('Accounts_RegistrationForm') === 'Secret URL' &&
(!formData.secretURL || formData.secretURL !== settings.get('Accounts_RegistrationForm_SecretURL'))
) {
if (!formData.secretURL) {
throw new Meteor.Error('error-user-registration-secret', 'User registration is only allowed via Secret URL', {
method: 'registerUser',
});
}
try {
await validateInviteToken(formData.secretURL);
} catch (e) {
throw new Meteor.Error('error-user-registration-secret', 'User registration is only allowed via Secret URL', {
method: 'registerUser',
});
}
}
passwordPolicy.validate(formData.pass);
await validateEmailDomain(formData.email);
const userData = {
email: trim(formData.email.toLowerCase()),
password: formData.pass,
name: formData.name,
reason: formData.reason,
};
let userId;
try {
userId = await Accounts.createUserAsync(userData);
} catch (e) {
if (e instanceof Meteor.Error) {
throw e;
}
if (e instanceof Error) {
throw new Meteor.Error(e.message);
}
throw new Meteor.Error(String(e));
}
await Users.setName(userId, trim(formData.name));
const reason = trim(formData.reason);
if (manuallyApproveNewUsers && reason) {
await Users.setReason(userId, reason);
}
try {
Accounts.sendVerificationEmail(userId, userData.email);
} catch (error) {
// throw new Meteor.Error 'error-email-send-failed', 'Error trying to send email: ' + error.message, { method: 'registerUser', message: error.message }
}
return userId;
},
});
let registerUserRuleId = RateLimiter.limitMethod(
'registerUser',
settings.get('Rate_Limiter_Limit_RegisterUser'),
settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'),
{
userId() {
return true;
},
},
);
settings.watch('Rate_Limiter_Limit_RegisterUser', (value) => {
// When running on testMode, there's no rate limiting added, so this function throws an error
if (process.env.TEST_MODE === 'true') {
return;
}
if (!registerUserRuleId) {
throw new Error('Rate limiter rule for "registerUser" not found');
}
// remove old DDP rate limiter rule and create a new one with the updated setting value
DDPRateLimiter.removeRule(registerUserRuleId);
registerUserRuleId = RateLimiter.limitMethod('registerUser', value, settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), {
userId() {
return true;
},
});
});