@driveflux/api-functions 0.0.7-next.2 → 0.0.7-next.20
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/dist/auth/confirm.js +66 -325
- package/dist/auth/emails.js +42 -210
- package/dist/auth/formatter.js +9 -9
- package/dist/auth/otp.js +120 -374
- package/dist/auth/register.js +95 -383
- package/dist/auth/register.js.map +1 -1
- package/dist/auth/tokens.d.ts +3 -3
- package/dist/auth/tokens.js +114 -426
- package/dist/auth/verifications.js +176 -581
- package/dist/constants.js +4 -4
- package/dist/mailjet/calls/manage-contacts-in-list.d.ts +2 -2
- package/dist/mailjet/calls/manage-contacts-in-list.d.ts.map +1 -1
- package/dist/mailjet/calls/manage-contacts-in-list.js +22 -167
- package/dist/mailjet/calls/manage-contacts-in-list.js.map +1 -1
- package/dist/mailjet/calls/manage-subscription-status.d.ts +2 -2
- package/dist/mailjet/calls/manage-subscription-status.d.ts.map +1 -1
- package/dist/mailjet/calls/manage-subscription-status.js +13 -154
- package/dist/mailjet/calls/manage-subscription-status.js.map +1 -1
- package/dist/mailjet/calls/request-service.js +18 -182
- package/dist/mailjet/refresh-email-preferences.js +21 -221
- package/dist/mailjet/set-contact.d.ts +2 -2
- package/dist/mailjet/set-contact.d.ts.map +1 -1
- package/dist/mailjet/set-contact.js +21 -213
- package/dist/mailjet/set-contact.js.map +1 -1
- package/dist/mailjet/types.d.ts +2 -2
- package/dist/mailjet/types.d.ts.map +1 -1
- package/dist/mailjet/utils/convert-to-array.d.ts +1 -1
- package/dist/mailjet/utils/convert-to-array.d.ts.map +1 -1
- package/dist/mailjet/utils/convert-to-array.js +9 -56
- package/dist/mailjet/utils/extract-email-preferences.d.ts +1 -1
- package/dist/mailjet/utils/extract-email-preferences.d.ts.map +1 -1
- package/dist/mailjet/utils/extract-email-preferences.js +37 -214
- package/dist/mailjet/utils/lists.js +28 -248
- package/dist/mailjet/utils/update-email-references.d.ts +2 -2
- package/dist/mailjet/utils/update-email-references.d.ts.map +1 -1
- package/dist/mailjet/utils/update-email-references.js +27 -207
- package/dist/mailjet/utils/update-email-references.js.map +1 -1
- package/dist/notion/client.js +50 -196
- package/dist/notion/helpful.js +25 -169
- package/dist/notion/schemas/block.js +1 -1
- package/dist/notion/schemas/common.js +7 -9
- package/dist/notion/schemas/database.d.ts +1 -1
- package/dist/notion/schemas/database.js +68 -100
- package/dist/notion/schemas/emoji.js +1 -1
- package/dist/notion/schemas/file.js +1 -1
- package/dist/notion/schemas/kb.js +3 -3
- package/dist/notion/schemas/page.d.ts +1 -1
- package/dist/notion/schemas/page.js +69 -103
- package/dist/notion/schemas/parent.js +4 -4
- package/dist/notion/schemas/user.js +2 -2
- package/dist/reservation/agree.d.ts +1 -1
- package/dist/reservation/agree.d.ts.map +1 -1
- package/dist/reservation/agree.js +17 -157
- package/dist/reservation/checks.d.ts +1 -1
- package/dist/reservation/checks.d.ts.map +1 -1
- package/dist/reservation/checks.js +21 -177
- package/dist/reservation/display-vehicle.d.ts +1 -1
- package/dist/reservation/display-vehicle.js +122 -500
- package/dist/reservation/display-vehicle.js.map +1 -1
- package/dist/reservation/fetch-or-create.d.ts +2 -2
- package/dist/reservation/fetch-or-create.d.ts.map +1 -1
- package/dist/reservation/fetch-or-create.js +188 -478
- package/dist/reservation/fetch-or-create.js.map +1 -1
- package/dist/reservation/invoice.d.ts +3 -3
- package/dist/reservation/invoice.d.ts.map +1 -1
- package/dist/reservation/invoice.js +182 -492
- package/dist/reservation/invoice.js.map +1 -1
- package/dist/reservation/payer.d.ts +1 -1
- package/dist/reservation/payer.d.ts.map +1 -1
- package/dist/reservation/payer.js +25 -175
- package/dist/reservation/reserve.d.ts +1 -1
- package/dist/reservation/reserve.d.ts.map +1 -1
- package/dist/reservation/reserve.js +35 -196
- package/dist/reservation/reserve.js.map +1 -1
- package/dist/reservation/types.d.ts +1 -0
- package/dist/reservation/types.d.ts.map +1 -1
- package/dist/reservation/vehicle.d.ts +1 -1
- package/dist/reservation/vehicle.d.ts.map +1 -1
- package/dist/reservation/vehicle.js +23 -188
- package/dist/reservation/vehicle.js.map +1 -1
- package/dist/slack.js +57 -268
- package/dist/validation.js +38 -98
- package/dist/vehicle/vehicle-pricing/constants.d.ts +1 -1
- package/dist/vehicle/vehicle-pricing/constants.d.ts.map +1 -1
- package/dist/vehicle/vehicle-pricing/constants.js +16 -16
- package/dist/vehicle/vehicle-pricing/index.d.ts +1 -1
- package/dist/vehicle/vehicle-pricing/index.d.ts.map +1 -1
- package/dist/vehicle/vehicle-pricing/index.js +87 -259
- package/dist/vehicle/vehicle-pricing/index.js.map +1 -1
- package/package.json +21 -21
|
@@ -1,123 +1,3 @@
|
|
|
1
|
-
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
-
try {
|
|
3
|
-
var info = gen[key](arg);
|
|
4
|
-
var value = info.value;
|
|
5
|
-
} catch (error) {
|
|
6
|
-
reject(error);
|
|
7
|
-
return;
|
|
8
|
-
}
|
|
9
|
-
if (info.done) {
|
|
10
|
-
resolve(value);
|
|
11
|
-
} else {
|
|
12
|
-
Promise.resolve(value).then(_next, _throw);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function _async_to_generator(fn) {
|
|
16
|
-
return function() {
|
|
17
|
-
var self = this, args = arguments;
|
|
18
|
-
return new Promise(function(resolve, reject) {
|
|
19
|
-
var gen = fn.apply(self, args);
|
|
20
|
-
function _next(value) {
|
|
21
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
-
}
|
|
23
|
-
function _throw(err) {
|
|
24
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
-
}
|
|
26
|
-
_next(undefined);
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function _ts_generator(thisArg, body) {
|
|
31
|
-
var f, y, t, _ = {
|
|
32
|
-
label: 0,
|
|
33
|
-
sent: function() {
|
|
34
|
-
if (t[0] & 1) throw t[1];
|
|
35
|
-
return t[1];
|
|
36
|
-
},
|
|
37
|
-
trys: [],
|
|
38
|
-
ops: []
|
|
39
|
-
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
40
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
41
|
-
return this;
|
|
42
|
-
}), g;
|
|
43
|
-
function verb(n) {
|
|
44
|
-
return function(v) {
|
|
45
|
-
return step([
|
|
46
|
-
n,
|
|
47
|
-
v
|
|
48
|
-
]);
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
function step(op) {
|
|
52
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
53
|
-
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
54
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
55
|
-
if (y = 0, t) op = [
|
|
56
|
-
op[0] & 2,
|
|
57
|
-
t.value
|
|
58
|
-
];
|
|
59
|
-
switch(op[0]){
|
|
60
|
-
case 0:
|
|
61
|
-
case 1:
|
|
62
|
-
t = op;
|
|
63
|
-
break;
|
|
64
|
-
case 4:
|
|
65
|
-
_.label++;
|
|
66
|
-
return {
|
|
67
|
-
value: op[1],
|
|
68
|
-
done: false
|
|
69
|
-
};
|
|
70
|
-
case 5:
|
|
71
|
-
_.label++;
|
|
72
|
-
y = op[1];
|
|
73
|
-
op = [
|
|
74
|
-
0
|
|
75
|
-
];
|
|
76
|
-
continue;
|
|
77
|
-
case 7:
|
|
78
|
-
op = _.ops.pop();
|
|
79
|
-
_.trys.pop();
|
|
80
|
-
continue;
|
|
81
|
-
default:
|
|
82
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
83
|
-
_ = 0;
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
87
|
-
_.label = op[1];
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
if (op[0] === 6 && _.label < t[1]) {
|
|
91
|
-
_.label = t[1];
|
|
92
|
-
t = op;
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
if (t && _.label < t[2]) {
|
|
96
|
-
_.label = t[2];
|
|
97
|
-
_.ops.push(op);
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
if (t[2]) _.ops.pop();
|
|
101
|
-
_.trys.pop();
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
op = body.call(thisArg, _);
|
|
105
|
-
} catch (e) {
|
|
106
|
-
op = [
|
|
107
|
-
6,
|
|
108
|
-
e
|
|
109
|
-
];
|
|
110
|
-
y = 0;
|
|
111
|
-
} finally{
|
|
112
|
-
f = t = 0;
|
|
113
|
-
}
|
|
114
|
-
if (op[0] & 5) throw op[1];
|
|
115
|
-
return {
|
|
116
|
-
value: op[0] ? op[1] : void 0,
|
|
117
|
-
done: true
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
1
|
import { config } from '@driveflux/config/backend';
|
|
122
2
|
import { prisma } from '@driveflux/db';
|
|
123
3
|
import { send } from '@driveflux/email';
|
|
@@ -128,488 +8,203 @@ import { reportProblem } from '@driveflux/reporter';
|
|
|
128
8
|
import { Err, Ok } from '@driveflux/result';
|
|
129
9
|
import { z } from 'zod';
|
|
130
10
|
import { clearToken, createEmailToken, createSMSToken } from './tokens.js';
|
|
131
|
-
|
|
11
|
+
const CheckDuplicationBody = z.object({
|
|
132
12
|
phoneNumber: z.string(),
|
|
133
|
-
email: z.string().transform(
|
|
134
|
-
return email.toLowerCase().trim();
|
|
135
|
-
})
|
|
13
|
+
email: z.string().transform((email)=>email.toLowerCase().trim())
|
|
136
14
|
});
|
|
137
|
-
export
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
3,
|
|
174
|
-
5
|
|
175
|
-
];
|
|
176
|
-
return [
|
|
177
|
-
4,
|
|
178
|
-
verifyEmailUsage(temporaryEmail)
|
|
179
|
-
];
|
|
180
|
-
case 4:
|
|
181
|
-
results = _state.sent();
|
|
182
|
-
if (results === null || results === void 0 ? void 0 : results.err) {
|
|
183
|
-
return [
|
|
184
|
-
2,
|
|
185
|
-
results
|
|
186
|
-
];
|
|
187
|
-
}
|
|
188
|
-
_state.label = 5;
|
|
189
|
-
case 5:
|
|
190
|
-
destinationEmail = temporaryEmail || user.email;
|
|
191
|
-
return [
|
|
192
|
-
4,
|
|
193
|
-
createEmailToken(user.id, destinationEmail)
|
|
194
|
-
];
|
|
195
|
-
case 6:
|
|
196
|
-
token = _state.sent();
|
|
197
|
-
if (!token) {
|
|
198
|
-
return [
|
|
199
|
-
2,
|
|
200
|
-
new Err(makeProblem(PROBLEM_NOT_IMPLEMENTED, 'Token was not created'))
|
|
201
|
-
];
|
|
202
|
-
}
|
|
203
|
-
return [
|
|
204
|
-
4,
|
|
205
|
-
prisma.user.update({
|
|
206
|
-
where: {
|
|
207
|
-
id: user.id
|
|
208
|
-
},
|
|
209
|
-
data: {
|
|
210
|
-
temporaryEmail: destinationEmail
|
|
211
|
-
},
|
|
212
|
-
include: {
|
|
213
|
-
tokens: true
|
|
214
|
-
}
|
|
215
|
-
})
|
|
216
|
-
];
|
|
217
|
-
case 7:
|
|
218
|
-
updatedUser = _state.sent();
|
|
219
|
-
tokens = updatedUser === null || updatedUser === void 0 ? void 0 : updatedUser.tokens;
|
|
220
|
-
if (!tokens) return [
|
|
221
|
-
3,
|
|
222
|
-
9
|
|
223
|
-
];
|
|
224
|
-
return [
|
|
225
|
-
4,
|
|
226
|
-
Promise.allSettled(tokens.map(function(userToken) {
|
|
227
|
-
return _async_to_generator(function() {
|
|
228
|
-
return _ts_generator(this, function(_state) {
|
|
229
|
-
switch(_state.label){
|
|
230
|
-
case 0:
|
|
231
|
-
if (!(userToken.scope === 'verify-email' && userToken.id !== token.id)) return [
|
|
232
|
-
3,
|
|
233
|
-
2
|
|
234
|
-
];
|
|
235
|
-
return [
|
|
236
|
-
4,
|
|
237
|
-
clearToken(userToken.id)
|
|
238
|
-
];
|
|
239
|
-
case 1:
|
|
240
|
-
return [
|
|
241
|
-
2,
|
|
242
|
-
_state.sent()
|
|
243
|
-
];
|
|
244
|
-
case 2:
|
|
245
|
-
return [
|
|
246
|
-
2
|
|
247
|
-
];
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
})();
|
|
251
|
-
}))
|
|
252
|
-
];
|
|
253
|
-
case 8:
|
|
254
|
-
_state.sent();
|
|
255
|
-
_state.label = 9;
|
|
256
|
-
case 9:
|
|
257
|
-
// Query object for the link
|
|
258
|
-
query = new URLSearchParams({
|
|
259
|
-
email: destinationEmail,
|
|
260
|
-
token: token.id,
|
|
261
|
-
code: token.value
|
|
262
|
-
});
|
|
263
|
-
if (next) {
|
|
264
|
-
query.append('next', next);
|
|
265
|
-
}
|
|
266
|
-
link = "".concat(config.appUrl, "/verify?").concat(query);
|
|
267
|
-
title = temporaryEmail ? 'Confirm email change' : 'Verify your email address';
|
|
268
|
-
_state.label = 10;
|
|
269
|
-
case 10:
|
|
270
|
-
_state.trys.push([
|
|
271
|
-
10,
|
|
272
|
-
12,
|
|
273
|
-
,
|
|
274
|
-
13
|
|
275
|
-
]);
|
|
276
|
-
// Generate html
|
|
277
|
-
html = verificationEmail({
|
|
278
|
-
user: user.firstName || '',
|
|
279
|
-
link: link,
|
|
280
|
-
title: "".concat(title),
|
|
281
|
-
newEmail: temporaryEmail,
|
|
282
|
-
isChanging: !!temporaryEmail
|
|
283
|
-
});
|
|
284
|
-
return [
|
|
285
|
-
4,
|
|
286
|
-
send({
|
|
287
|
-
to: {
|
|
288
|
-
name: user.firstName || '',
|
|
289
|
-
address: destinationEmail
|
|
290
|
-
},
|
|
291
|
-
subject: "".concat(title),
|
|
292
|
-
html: html
|
|
293
|
-
})
|
|
294
|
-
];
|
|
295
|
-
case 11:
|
|
296
|
-
result = _state.sent();
|
|
297
|
-
if (result.err) {
|
|
298
|
-
console.error('Error sending email:', result.val);
|
|
299
|
-
return [
|
|
300
|
-
2,
|
|
301
|
-
new Err(makeProblem('email_not_sent', 'Unable to send the verification email'))
|
|
302
|
-
];
|
|
303
|
-
}
|
|
304
|
-
return [
|
|
305
|
-
2,
|
|
306
|
-
new Ok({
|
|
307
|
-
success: true,
|
|
308
|
-
link: link
|
|
309
|
-
})
|
|
310
|
-
];
|
|
311
|
-
case 12:
|
|
312
|
-
e = _state.sent();
|
|
313
|
-
return [
|
|
314
|
-
2,
|
|
315
|
-
new Err(makeProblem('email_not_sent', e.message))
|
|
316
|
-
];
|
|
317
|
-
case 13:
|
|
318
|
-
return [
|
|
319
|
-
2
|
|
320
|
-
];
|
|
15
|
+
export const sendVerificationEmail = async (userId, temporaryEmail, next)=>{
|
|
16
|
+
const user = typeof userId === 'string' ? await prisma.user.findUnique({
|
|
17
|
+
where: {
|
|
18
|
+
id: userId
|
|
19
|
+
}
|
|
20
|
+
}) : userId;
|
|
21
|
+
if (!user) {
|
|
22
|
+
return new Err(makeProblem(PROBLEM_NOT_FOUND, `User ${typeof userId === 'string' ? userId : 'unknown'} not found.`));
|
|
23
|
+
}
|
|
24
|
+
if (temporaryEmail) {
|
|
25
|
+
const results = await verifyEmailUsage(temporaryEmail);
|
|
26
|
+
if (results?.err) {
|
|
27
|
+
return results;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const destinationEmail = temporaryEmail || user.email;
|
|
31
|
+
const token = await createEmailToken(user.id, destinationEmail);
|
|
32
|
+
if (!token) {
|
|
33
|
+
return new Err(makeProblem(PROBLEM_NOT_IMPLEMENTED, 'Token was not created'));
|
|
34
|
+
}
|
|
35
|
+
const updatedUser = await prisma.user.update({
|
|
36
|
+
where: {
|
|
37
|
+
id: user.id
|
|
38
|
+
},
|
|
39
|
+
data: {
|
|
40
|
+
temporaryEmail: destinationEmail
|
|
41
|
+
},
|
|
42
|
+
include: {
|
|
43
|
+
tokens: true
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const tokens = updatedUser?.tokens;
|
|
47
|
+
if (tokens) {
|
|
48
|
+
await Promise.allSettled(tokens.map(async (userToken)=>{
|
|
49
|
+
if (userToken.scope === 'verify-email' && userToken.id !== token.id) {
|
|
50
|
+
return await clearToken(userToken.id);
|
|
321
51
|
}
|
|
52
|
+
return;
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
// Query object for the link
|
|
56
|
+
const query = new URLSearchParams({
|
|
57
|
+
email: destinationEmail,
|
|
58
|
+
token: token.id,
|
|
59
|
+
code: token.value
|
|
60
|
+
});
|
|
61
|
+
if (next) {
|
|
62
|
+
query.append('next', next);
|
|
63
|
+
}
|
|
64
|
+
const link = `${config.appUrl}/verify?${query}`;
|
|
65
|
+
const title = temporaryEmail ? 'Confirm email change' : 'Verify your email address';
|
|
66
|
+
try {
|
|
67
|
+
// Generate html
|
|
68
|
+
const html = verificationEmail({
|
|
69
|
+
user: user.firstName || '',
|
|
70
|
+
link,
|
|
71
|
+
title: `${title}`,
|
|
72
|
+
newEmail: temporaryEmail,
|
|
73
|
+
isChanging: !!temporaryEmail
|
|
322
74
|
});
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
// TODO: add email regex checking
|
|
332
|
-
if (newEmail.length < 3) {
|
|
333
|
-
return [
|
|
334
|
-
2,
|
|
335
|
-
new Err(makeProblem(PROBLEM_INVALID_DATA, 'Email address needs minimum 3 characters'))
|
|
336
|
-
];
|
|
337
|
-
}
|
|
338
|
-
return [
|
|
339
|
-
4,
|
|
340
|
-
prisma.user.findFirst({
|
|
341
|
-
where: {
|
|
342
|
-
email: newEmail
|
|
343
|
-
}
|
|
344
|
-
})
|
|
345
|
-
];
|
|
346
|
-
case 1:
|
|
347
|
-
existingEmail = _state.sent();
|
|
348
|
-
if (existingEmail) {
|
|
349
|
-
return [
|
|
350
|
-
2,
|
|
351
|
-
new Err(makeProblem(PROBLEM_INVALID_DATA, 'The email address is already in use'))
|
|
352
|
-
];
|
|
353
|
-
}
|
|
354
|
-
return [
|
|
355
|
-
2,
|
|
356
|
-
new Ok({})
|
|
357
|
-
];
|
|
358
|
-
}
|
|
75
|
+
// send email
|
|
76
|
+
const result = await send({
|
|
77
|
+
to: {
|
|
78
|
+
name: user.firstName || '',
|
|
79
|
+
address: destinationEmail
|
|
80
|
+
},
|
|
81
|
+
subject: `${title}`,
|
|
82
|
+
html
|
|
359
83
|
});
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
case 0:
|
|
368
|
-
return [
|
|
369
|
-
4,
|
|
370
|
-
createSMSToken(userId, phoneNumber)
|
|
371
|
-
];
|
|
372
|
-
case 1:
|
|
373
|
-
token = _state.sent();
|
|
374
|
-
if (!token) {
|
|
375
|
-
return [
|
|
376
|
-
2,
|
|
377
|
-
new Err(makeProblem(PROBLEM_NOT_IMPLEMENTED, 'Token was not created'))
|
|
378
|
-
];
|
|
379
|
-
}
|
|
380
|
-
return [
|
|
381
|
-
4,
|
|
382
|
-
sendSms(phoneNumber, token.value)
|
|
383
|
-
];
|
|
384
|
-
case 2:
|
|
385
|
-
return [
|
|
386
|
-
2,
|
|
387
|
-
_state.sent()
|
|
388
|
-
];
|
|
389
|
-
}
|
|
84
|
+
if (result.err) {
|
|
85
|
+
console.error('Error sending email:', result.val);
|
|
86
|
+
return new Err(makeProblem('email_not_sent', 'Unable to send the verification email'));
|
|
87
|
+
}
|
|
88
|
+
return new Ok({
|
|
89
|
+
success: true,
|
|
90
|
+
link
|
|
390
91
|
});
|
|
391
|
-
}
|
|
92
|
+
} catch (e) {
|
|
93
|
+
return new Err(makeProblem('email_not_sent', e.message));
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
export const verifyEmailUsage = async (newEmail)=>{
|
|
97
|
+
// TODO: add email regex checking
|
|
98
|
+
if (newEmail.length < 3) {
|
|
99
|
+
return new Err(makeProblem(PROBLEM_INVALID_DATA, 'Email address needs minimum 3 characters'));
|
|
100
|
+
}
|
|
101
|
+
const existingEmail = await prisma.user.findFirst({
|
|
102
|
+
where: {
|
|
103
|
+
email: newEmail
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
if (existingEmail) {
|
|
107
|
+
return new Err(makeProblem(PROBLEM_INVALID_DATA, 'The email address is already in use'));
|
|
108
|
+
}
|
|
109
|
+
return new Ok({});
|
|
392
110
|
};
|
|
393
|
-
|
|
111
|
+
export const sendVerificationSMS = async (userId, phoneNumber)=>{
|
|
112
|
+
const token = await createSMSToken(userId, phoneNumber);
|
|
113
|
+
if (!token) {
|
|
114
|
+
return new Err(makeProblem(PROBLEM_NOT_IMPLEMENTED, 'Token was not created'));
|
|
115
|
+
}
|
|
116
|
+
return await sendSms(phoneNumber, token.value);
|
|
117
|
+
};
|
|
118
|
+
const formatPhoneNumber = (phoneNumber)=>{
|
|
394
119
|
return phoneNumber.replace(/[^0-9]/g, '');
|
|
395
120
|
};
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
3
|
|
414
|
-
];
|
|
415
|
-
return [
|
|
416
|
-
4,
|
|
417
|
-
sendVonageSms(phoneNumber, code)
|
|
418
|
-
];
|
|
419
|
-
case 2:
|
|
420
|
-
_tmp = _state.sent();
|
|
421
|
-
return [
|
|
422
|
-
3,
|
|
423
|
-
5
|
|
424
|
-
];
|
|
425
|
-
case 3:
|
|
426
|
-
return [
|
|
427
|
-
4,
|
|
428
|
-
sendEsmsSms(phoneNumber, code)
|
|
429
|
-
];
|
|
430
|
-
case 4:
|
|
431
|
-
_tmp = _state.sent();
|
|
432
|
-
_state.label = 5;
|
|
433
|
-
case 5:
|
|
434
|
-
sendSmsResult = _tmp;
|
|
435
|
-
if (!sendSmsResult.err) return [
|
|
436
|
-
3,
|
|
437
|
-
7
|
|
438
|
-
];
|
|
439
|
-
_ = Err.bind;
|
|
440
|
-
return [
|
|
441
|
-
4,
|
|
442
|
-
reportProblem(makeProblem({
|
|
443
|
-
type: 'public',
|
|
444
|
-
code: PROBLEM_EXTERNAL,
|
|
445
|
-
message: 'Unable to send sms verification',
|
|
446
|
-
privateMetadata: {
|
|
447
|
-
error: sendSmsResult.val
|
|
448
|
-
}
|
|
449
|
-
}))
|
|
450
|
-
];
|
|
451
|
-
case 6:
|
|
452
|
-
return [
|
|
453
|
-
2,
|
|
454
|
-
new (_.apply(Err, [
|
|
455
|
-
void 0,
|
|
456
|
-
_state.sent()
|
|
457
|
-
]))
|
|
458
|
-
];
|
|
459
|
-
case 7:
|
|
460
|
-
return [
|
|
461
|
-
2,
|
|
462
|
-
new Ok({
|
|
463
|
-
success: true,
|
|
464
|
-
code: code
|
|
465
|
-
})
|
|
466
|
-
];
|
|
467
|
-
case 8:
|
|
468
|
-
e = _state.sent();
|
|
469
|
-
_1 = Err.bind;
|
|
470
|
-
return [
|
|
471
|
-
4,
|
|
472
|
-
reportProblem(makeProblem({
|
|
473
|
-
type: 'public',
|
|
474
|
-
code: PROBLEM_INTERNAL,
|
|
475
|
-
message: 'Unable to send sms verification',
|
|
476
|
-
privateMetadata: {
|
|
477
|
-
error: e
|
|
478
|
-
}
|
|
479
|
-
}))
|
|
480
|
-
];
|
|
481
|
-
case 9:
|
|
482
|
-
return [
|
|
483
|
-
2,
|
|
484
|
-
new (_1.apply(Err, [
|
|
485
|
-
void 0,
|
|
486
|
-
_state.sent()
|
|
487
|
-
]))
|
|
488
|
-
];
|
|
489
|
-
case 10:
|
|
490
|
-
return [
|
|
491
|
-
2
|
|
492
|
-
];
|
|
493
|
-
}
|
|
121
|
+
const sendSms = async (phoneNumber, code)=>{
|
|
122
|
+
const isInternational = !formatPhoneNumber(phoneNumber).startsWith('60');
|
|
123
|
+
try {
|
|
124
|
+
const sendSmsResult = isInternational ? await sendVonageSms(phoneNumber, code) : await sendEsmsSms(phoneNumber, code);
|
|
125
|
+
if (sendSmsResult.err) {
|
|
126
|
+
return new Err(await reportProblem(makeProblem({
|
|
127
|
+
type: 'public',
|
|
128
|
+
code: PROBLEM_EXTERNAL,
|
|
129
|
+
message: 'Unable to send sms verification',
|
|
130
|
+
privateMetadata: {
|
|
131
|
+
error: sendSmsResult.val
|
|
132
|
+
}
|
|
133
|
+
})));
|
|
134
|
+
}
|
|
135
|
+
return new Ok({
|
|
136
|
+
success: true,
|
|
137
|
+
code
|
|
494
138
|
});
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
case 0:
|
|
503
|
-
_CheckDuplicationBody_parse = CheckDuplicationBody.parse(b), phoneNumber = _CheckDuplicationBody_parse.phoneNumber, email = _CheckDuplicationBody_parse.email;
|
|
504
|
-
return [
|
|
505
|
-
4,
|
|
506
|
-
prisma.user.findFirst({
|
|
507
|
-
where: {
|
|
508
|
-
email: email.toLowerCase().trim()
|
|
509
|
-
}
|
|
510
|
-
})
|
|
511
|
-
];
|
|
512
|
-
case 1:
|
|
513
|
-
checkForEmail = _state.sent();
|
|
514
|
-
if (checkForEmail) {
|
|
515
|
-
return [
|
|
516
|
-
2,
|
|
517
|
-
new Err(makeProblem(PROBLEM_CONFLICT, 'This email is already registered. Are you trying to sign in?'))
|
|
518
|
-
];
|
|
519
|
-
}
|
|
520
|
-
return [
|
|
521
|
-
4,
|
|
522
|
-
prisma.user.findFirst({
|
|
523
|
-
where: {
|
|
524
|
-
phoneNumber: phoneNumber.replace(/[\s-]/g, '')
|
|
525
|
-
}
|
|
526
|
-
})
|
|
527
|
-
];
|
|
528
|
-
case 2:
|
|
529
|
-
checkForMobile = _state.sent();
|
|
530
|
-
if (checkForMobile) {
|
|
531
|
-
return [
|
|
532
|
-
2,
|
|
533
|
-
new Err(makeProblem(PROBLEM_CONFLICT, 'The phone number is already in use. Please try a different one.'))
|
|
534
|
-
];
|
|
535
|
-
}
|
|
536
|
-
return [
|
|
537
|
-
2,
|
|
538
|
-
new Ok({
|
|
539
|
-
notDuplicate: true
|
|
540
|
-
})
|
|
541
|
-
];
|
|
139
|
+
} catch (e) {
|
|
140
|
+
return new Err(await reportProblem(makeProblem({
|
|
141
|
+
type: 'public',
|
|
142
|
+
code: PROBLEM_INTERNAL,
|
|
143
|
+
message: 'Unable to send sms verification',
|
|
144
|
+
privateMetadata: {
|
|
145
|
+
error: e
|
|
542
146
|
}
|
|
543
|
-
});
|
|
544
|
-
}
|
|
147
|
+
})));
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
export const handleCheckDuplication = async (b)=>{
|
|
151
|
+
const { phoneNumber, email } = CheckDuplicationBody.parse(b);
|
|
152
|
+
// Check if the user exists
|
|
153
|
+
const checkForEmail = await prisma.user.findFirst({
|
|
154
|
+
where: {
|
|
155
|
+
email: email.toLowerCase().trim()
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
if (checkForEmail) {
|
|
159
|
+
return new Err(makeProblem(PROBLEM_CONFLICT, 'This email is already registered. Are you trying to sign in?'));
|
|
160
|
+
}
|
|
161
|
+
const checkForMobile = await prisma.user.findFirst({
|
|
162
|
+
where: {
|
|
163
|
+
phoneNumber: phoneNumber.replace(/[\s-]/g, '')
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
if (checkForMobile) {
|
|
167
|
+
return new Err(makeProblem(PROBLEM_CONFLICT, 'The phone number is already in use. Please try a different one.'));
|
|
168
|
+
}
|
|
169
|
+
return new Ok({
|
|
170
|
+
notDuplicate: true
|
|
171
|
+
});
|
|
545
172
|
};
|
|
546
173
|
/**
|
|
547
174
|
* This function runs only for foreign numbers and sends an SMS containing the OTP code to the foreign number
|
|
548
175
|
* @param phoneNumber user's phone number
|
|
549
176
|
* @param code OTP code
|
|
550
177
|
* @returns result of sending SMS to user
|
|
551
|
-
*/
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
return [
|
|
565
|
-
4,
|
|
566
|
-
enhancedFetch('https://rest.nexmo.com/sms/json', {
|
|
567
|
-
method: 'POST',
|
|
568
|
-
body: JSON.stringify(body)
|
|
569
|
-
})
|
|
570
|
-
];
|
|
571
|
-
case 1:
|
|
572
|
-
result = _state.sent();
|
|
573
|
-
return [
|
|
574
|
-
2,
|
|
575
|
-
result
|
|
576
|
-
];
|
|
577
|
-
}
|
|
578
|
-
});
|
|
579
|
-
})();
|
|
178
|
+
*/ const sendVonageSms = async (phoneNumber, code)=>{
|
|
179
|
+
const body = {
|
|
180
|
+
from: 'FLUX',
|
|
181
|
+
to: formatPhoneNumber(phoneNumber),
|
|
182
|
+
text: `FLUX verification code: ${code}`,
|
|
183
|
+
api_key: config.vonage.apiKey,
|
|
184
|
+
api_secret: config.vonage.apiSecret
|
|
185
|
+
};
|
|
186
|
+
const result = await enhancedFetch('https://rest.nexmo.com/sms/json', {
|
|
187
|
+
method: 'POST',
|
|
188
|
+
body: JSON.stringify(body)
|
|
189
|
+
});
|
|
190
|
+
return result;
|
|
580
191
|
};
|
|
581
192
|
/**
|
|
582
193
|
* This function runs only for local numbers (MY) and sends an SMS containing the OTP code to the foreign number
|
|
583
194
|
* @param phoneNumber user's phone number
|
|
584
195
|
* @param code OTP code
|
|
585
196
|
* @returns result of sending SMS to user
|
|
586
|
-
*/
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
return [
|
|
600
|
-
4,
|
|
601
|
-
enhancedFetch('https://api.esms.com.my/sms/send', {
|
|
602
|
-
method: 'POST',
|
|
603
|
-
body: JSON.stringify(body)
|
|
604
|
-
})
|
|
605
|
-
];
|
|
606
|
-
case 1:
|
|
607
|
-
result = _state.sent();
|
|
608
|
-
return [
|
|
609
|
-
2,
|
|
610
|
-
result
|
|
611
|
-
];
|
|
612
|
-
}
|
|
613
|
-
});
|
|
614
|
-
})();
|
|
197
|
+
*/ const sendEsmsSms = async (phoneNumber, code)=>{
|
|
198
|
+
const body = {
|
|
199
|
+
user: config.esms.apiKey,
|
|
200
|
+
pass: config.esms.apiSecret,
|
|
201
|
+
to: formatPhoneNumber(phoneNumber),
|
|
202
|
+
msg: `RM0.00 FLUX verification code: ${code}`,
|
|
203
|
+
sender: 'FLUX'
|
|
204
|
+
};
|
|
205
|
+
const result = await enhancedFetch('https://api.esms.com.my/sms/send', {
|
|
206
|
+
method: 'POST',
|
|
207
|
+
body: JSON.stringify(body)
|
|
208
|
+
});
|
|
209
|
+
return result;
|
|
615
210
|
};
|