@driveflux/api-functions 1.0.118 → 1.0.119
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 +24 -24
- package/dist/auth/consent.js +22 -27
- package/dist/auth/emails.js +12 -13
- package/dist/auth/formatter.js +5 -5
- package/dist/auth/otp.js +66 -50
- package/dist/auth/register.js +48 -35
- package/dist/auth/tokens.js +58 -55
- package/dist/auth/verifications.js +53 -52
- package/dist/constants.js +0 -1
- package/dist/create-logger.js +1 -2
- package/dist/mailjet/calls/manage-contacts-in-list.js +5 -6
- package/dist/mailjet/calls/manage-subscription-status.js +4 -5
- package/dist/mailjet/calls/request-service.js +7 -6
- package/dist/mailjet/refresh-email-preferences.js +11 -12
- package/dist/mailjet/set-contact.js +11 -12
- package/dist/mailjet/types.js +1 -2
- package/dist/mailjet/utils/convert-to-array.js +8 -6
- package/dist/mailjet/utils/extract-email-preferences.js +14 -15
- package/dist/mailjet/utils/lists.js +7 -8
- package/dist/mailjet/utils/update-email-references.js +16 -15
- package/dist/notion/client.js +22 -19
- package/dist/notion/helpful.js +6 -9
- package/dist/notion/schemas/block.js +42 -48
- package/dist/notion/schemas/common.js +9 -14
- package/dist/notion/schemas/database.js +62 -60
- package/dist/notion/schemas/emoji.js +1 -2
- package/dist/notion/schemas/file.js +9 -9
- package/dist/notion/schemas/kb.js +5 -6
- package/dist/notion/schemas/page.js +72 -61
- package/dist/notion/schemas/parent.js +4 -5
- package/dist/notion/schemas/user.js +18 -19
- package/dist/reservation/agree.js +2 -3
- package/dist/reservation/checks.js +3 -4
- package/dist/reservation/display-vehicle.js +73 -83
- package/dist/reservation/ensure-user-billing-address.js +9 -11
- package/dist/reservation/fetch-or-create.js +49 -56
- package/dist/reservation/invoice.js +77 -88
- package/dist/reservation/payer.js +5 -6
- package/dist/reservation/payment-intent-sync.js +4 -6
- package/dist/reservation/reserve.js +3 -4
- package/dist/reservation/types.js +1 -2
- package/dist/reservation/vehicle.js +13 -16
- package/dist/slack.js +24 -29
- package/dist/validation.js +77 -79
- package/dist/vehicle/vehicle-pricing/constants.js +22 -19
- package/dist/vehicle/vehicle-pricing/index.js +28 -42
- package/dist/vehicle/vehicle-pricing/types.js +1 -2
- package/package.json +9 -9
package/dist/auth/confirm.js
CHANGED
|
@@ -13,35 +13,34 @@ const Body = z.object({
|
|
|
13
13
|
firstName: z.string(),
|
|
14
14
|
lastName: z.string(),
|
|
15
15
|
email: z.string(),
|
|
16
|
-
phoneNumber: z.string().transform((s)
|
|
16
|
+
phoneNumber: z.string().transform((s)=>s.replace(/[\s-]/g, '')),
|
|
17
17
|
code: z.string().optional().nullable(),
|
|
18
18
|
pageSource: z.string().optional().nullable(),
|
|
19
19
|
fingerprint: z.string().optional(),
|
|
20
20
|
ipAddress: z.string(),
|
|
21
|
-
userAgent: z.string().optional()
|
|
21
|
+
userAgent: z.string().optional()
|
|
22
22
|
});
|
|
23
|
-
export const handleConfirmUser = async (b, user)
|
|
23
|
+
export const handleConfirmUser = async (b, user)=>{
|
|
24
24
|
const { phoneNumber, code, pageSource, fingerprint, ipAddress, userAgent, ...body } = Body.parse(b);
|
|
25
25
|
console.log('fingerprint in handle confirm user???', fingerprint);
|
|
26
26
|
let phoneNumberVerified = false;
|
|
27
27
|
if (code) {
|
|
28
|
-
const tokenResult = await verifyToken(code, {
|
|
28
|
+
const tokenResult = await verifyToken(code, {
|
|
29
|
+
scope: 'verify-phone'
|
|
30
|
+
});
|
|
29
31
|
if (tokenResult.err) {
|
|
30
32
|
return new Err(makeProblem(PROBLEM_CONFLICT, 'Invalid OTP token'));
|
|
31
33
|
}
|
|
32
34
|
await clearToken(tokenResult.val.id);
|
|
33
35
|
phoneNumberVerified = true;
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
+
} else {
|
|
36
37
|
phoneNumberVerified = user.phoneNumberVerified;
|
|
37
38
|
}
|
|
38
|
-
const method = isMetadata(user?.metadata)
|
|
39
|
-
? user?.metadata?.signupProvider
|
|
40
|
-
: undefined;
|
|
39
|
+
const method = isMetadata(user?.metadata) ? user?.metadata?.signupProvider : undefined;
|
|
41
40
|
const tokenId = generateId('Token');
|
|
42
41
|
const updatedUser = await prisma.user.update({
|
|
43
42
|
where: {
|
|
44
|
-
id: user.id
|
|
43
|
+
id: user.id
|
|
45
44
|
},
|
|
46
45
|
data: {
|
|
47
46
|
...body,
|
|
@@ -49,18 +48,20 @@ export const handleConfirmUser = async (b, user) => {
|
|
|
49
48
|
preferredCurrency: 'MYR',
|
|
50
49
|
preferredLocale: 'en',
|
|
51
50
|
phoneNumberVerified,
|
|
52
|
-
groups: [
|
|
51
|
+
groups: [
|
|
52
|
+
'member'
|
|
53
|
+
],
|
|
53
54
|
signupParams: {
|
|
54
55
|
method,
|
|
55
|
-
source: pageSource
|
|
56
|
+
source: pageSource
|
|
56
57
|
},
|
|
57
58
|
registrationComplete: true,
|
|
58
59
|
tokens: {
|
|
59
60
|
create: {
|
|
60
61
|
id: tokenId,
|
|
61
62
|
expiresAt: addDays(new Date(), 365),
|
|
62
|
-
scope: 'all'
|
|
63
|
-
}
|
|
63
|
+
scope: 'all'
|
|
64
|
+
}
|
|
64
65
|
},
|
|
65
66
|
consented: true,
|
|
66
67
|
consents: {
|
|
@@ -69,31 +70,30 @@ export const handleConfirmUser = async (b, user) => {
|
|
|
69
70
|
...user,
|
|
70
71
|
phoneNumber,
|
|
71
72
|
firstName: body.firstName,
|
|
72
|
-
lastName: body.lastName
|
|
73
|
+
lastName: body.lastName
|
|
73
74
|
},
|
|
74
75
|
fingerprint,
|
|
75
76
|
termsVersion: 'universal',
|
|
76
77
|
ipAddress: ipAddress,
|
|
77
78
|
userAgent: userAgent,
|
|
78
79
|
sessionToken: tokenId,
|
|
79
|
-
consentType: 'terms'
|
|
80
|
-
})
|
|
81
|
-
}
|
|
80
|
+
consentType: 'terms'
|
|
81
|
+
})
|
|
82
|
+
}
|
|
82
83
|
},
|
|
83
84
|
include: {
|
|
84
85
|
tokens: {
|
|
85
86
|
where: {
|
|
86
|
-
id: tokenId
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
87
|
+
id: tokenId
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
90
91
|
});
|
|
91
92
|
// We don't want this to be a task. It should be instant
|
|
92
93
|
await sendVerificationEmail(updatedUser.id);
|
|
93
94
|
await refreshEmailPreferences(updatedUser.id);
|
|
94
95
|
return new Ok({
|
|
95
96
|
token: updatedUser.tokens[0],
|
|
96
|
-
user: updatedUser
|
|
97
|
+
user: updatedUser
|
|
97
98
|
});
|
|
98
99
|
};
|
|
99
|
-
//# sourceMappingURL=confirm.js.map
|
package/dist/auth/consent.js
CHANGED
|
@@ -1,58 +1,53 @@
|
|
|
1
1
|
import { prisma } from '@driveflux/db';
|
|
2
2
|
import { generateId } from '@driveflux/db/id';
|
|
3
|
-
export const getConsentCreateData = ({ fingerprint, termsVersion, ipAddress, userAgent, user, sessionToken, sessionId, consentType
|
|
3
|
+
export const getConsentCreateData = ({ fingerprint, termsVersion, ipAddress, userAgent, user, sessionToken, sessionId, consentType })=>{
|
|
4
4
|
const consentCreate = {
|
|
5
5
|
id: generateId('UserConsent'),
|
|
6
6
|
ipAddress,
|
|
7
7
|
consentType: consentType || 'terms',
|
|
8
8
|
sessionToken,
|
|
9
|
-
userName: [
|
|
9
|
+
userName: [
|
|
10
|
+
user.firstName,
|
|
11
|
+
user.lastName
|
|
12
|
+
].filter(Boolean).join(' '),
|
|
10
13
|
phoneNumber: user.phoneNumber,
|
|
11
14
|
email: user.email,
|
|
12
15
|
fingerprint,
|
|
13
16
|
user: {
|
|
14
17
|
connect: {
|
|
15
|
-
id: user.id
|
|
16
|
-
}
|
|
18
|
+
id: user.id
|
|
19
|
+
}
|
|
17
20
|
},
|
|
18
|
-
...
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
},
|
|
24
|
-
},
|
|
21
|
+
...sessionId ? {
|
|
22
|
+
session: {
|
|
23
|
+
connect: {
|
|
24
|
+
id: sessionId
|
|
25
|
+
}
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
+
} : undefined,
|
|
27
28
|
userAgent,
|
|
28
|
-
termsVersion: termsVersion || 'universal'
|
|
29
|
+
termsVersion: termsVersion || 'universal'
|
|
29
30
|
};
|
|
30
31
|
return consentCreate;
|
|
31
32
|
};
|
|
32
|
-
export const createConsent = (data)
|
|
33
|
+
export const createConsent = (data)=>{
|
|
33
34
|
const consentData = getConsentCreateData(data);
|
|
34
35
|
return prisma.userConsent.create({
|
|
35
|
-
data: consentData
|
|
36
|
+
data: consentData
|
|
36
37
|
});
|
|
37
38
|
};
|
|
38
|
-
export const shouldConsentAgain = (consent)
|
|
39
|
-
return
|
|
40
|
-
!consent.ipAddress ||
|
|
41
|
-
consent.ipAddress === '0.0.0.0' ||
|
|
42
|
-
!consent.userName ||
|
|
43
|
-
!consent.phoneNumber ||
|
|
44
|
-
!consent.email);
|
|
39
|
+
export const shouldConsentAgain = (consent)=>{
|
|
40
|
+
return !consent.userAgent || !consent.ipAddress || consent.ipAddress === '0.0.0.0' || !consent.userName || !consent.phoneNumber || !consent.email;
|
|
45
41
|
};
|
|
46
|
-
export const checkUserConsent = async (userId)
|
|
42
|
+
export const checkUserConsent = async (userId)=>{
|
|
47
43
|
const consent = await prisma.userConsent.findFirst({
|
|
48
44
|
where: {
|
|
49
45
|
userId,
|
|
50
|
-
consentType: 'terms'
|
|
46
|
+
consentType: 'terms'
|
|
51
47
|
},
|
|
52
48
|
orderBy: {
|
|
53
|
-
createdAt: 'desc'
|
|
54
|
-
}
|
|
49
|
+
createdAt: 'desc'
|
|
50
|
+
}
|
|
55
51
|
});
|
|
56
52
|
return consent && !shouldConsentAgain(consent);
|
|
57
53
|
};
|
|
58
|
-
//# sourceMappingURL=consent.js.map
|
package/dist/auth/emails.js
CHANGED
|
@@ -4,11 +4,11 @@ import { emailChangedEmail } from '@driveflux/email-templates/flux/email-changed
|
|
|
4
4
|
import { passwordChangedEmail } from '@driveflux/email-templates/flux/password-changed';
|
|
5
5
|
import { makeProblem, PROBLEM_NOT_FOUND } from '@driveflux/problem';
|
|
6
6
|
import { Err } from '@driveflux/result';
|
|
7
|
-
export const sendEmailChangedEmail = async (userId)
|
|
7
|
+
export const sendEmailChangedEmail = async (userId)=>{
|
|
8
8
|
const user = await prisma.user.findUnique({
|
|
9
9
|
where: {
|
|
10
|
-
id: userId
|
|
11
|
-
}
|
|
10
|
+
id: userId
|
|
11
|
+
}
|
|
12
12
|
});
|
|
13
13
|
if (!user) {
|
|
14
14
|
return new Err(makeProblem(PROBLEM_NOT_FOUND, `The user ${userId} was not found`));
|
|
@@ -17,20 +17,20 @@ export const sendEmailChangedEmail = async (userId) => {
|
|
|
17
17
|
subject: 'Email change confirmation',
|
|
18
18
|
to: {
|
|
19
19
|
name: user.firstName || '',
|
|
20
|
-
address: user.email
|
|
20
|
+
address: user.email
|
|
21
21
|
},
|
|
22
22
|
html: emailChangedEmail({
|
|
23
23
|
user: user.firstName || '',
|
|
24
24
|
title: 'Email change confirmation',
|
|
25
|
-
newEmail: user.email
|
|
26
|
-
})
|
|
25
|
+
newEmail: user.email
|
|
26
|
+
})
|
|
27
27
|
});
|
|
28
28
|
};
|
|
29
|
-
export const sendPasswordChangedEmail = async (userId)
|
|
29
|
+
export const sendPasswordChangedEmail = async (userId)=>{
|
|
30
30
|
const user = await prisma.user.findUnique({
|
|
31
31
|
where: {
|
|
32
|
-
id: userId
|
|
33
|
-
}
|
|
32
|
+
id: userId
|
|
33
|
+
}
|
|
34
34
|
});
|
|
35
35
|
if (!user) {
|
|
36
36
|
return new Err(makeProblem(PROBLEM_NOT_FOUND, `The user ${userId} was not found`));
|
|
@@ -40,12 +40,11 @@ export const sendPasswordChangedEmail = async (userId) => {
|
|
|
40
40
|
subject: title,
|
|
41
41
|
to: {
|
|
42
42
|
name: user.firstName || '',
|
|
43
|
-
address: user.email
|
|
43
|
+
address: user.email
|
|
44
44
|
},
|
|
45
45
|
html: passwordChangedEmail({
|
|
46
46
|
user: user.firstName || '',
|
|
47
|
-
title: title
|
|
48
|
-
})
|
|
47
|
+
title: title
|
|
48
|
+
})
|
|
49
49
|
});
|
|
50
50
|
};
|
|
51
|
-
//# sourceMappingURL=emails.js.map
|
package/dist/auth/formatter.js
CHANGED
|
@@ -221,9 +221,9 @@ const knownCountryCodes = [
|
|
|
221
221
|
'246',
|
|
222
222
|
'269',
|
|
223
223
|
'692',
|
|
224
|
-
'383'
|
|
224
|
+
'383'
|
|
225
225
|
];
|
|
226
|
-
export const cleanupPhoneNumber = (phoneNumber)
|
|
226
|
+
export const cleanupPhoneNumber = (phoneNumber)=>{
|
|
227
227
|
// Remove all characters except numbers and +
|
|
228
228
|
const cleaned = phoneNumber.replace(/[^\d+]/g, '');
|
|
229
229
|
// If it doesn't start with +, add it
|
|
@@ -232,8 +232,9 @@ export const cleanupPhoneNumber = (phoneNumber) => {
|
|
|
232
232
|
let countryCode = '';
|
|
233
233
|
let remainingNumber = '';
|
|
234
234
|
// Try to find the country code by checking the longest matches first
|
|
235
|
-
for
|
|
236
|
-
const potentialCode = withPlus.substring(1, 1 + i)
|
|
235
|
+
for(let i = 4; i >= 1; i--){
|
|
236
|
+
const potentialCode = withPlus.substring(1, 1 + i) // Skip the + and take i digits
|
|
237
|
+
;
|
|
237
238
|
if (knownCountryCodes.includes(potentialCode)) {
|
|
238
239
|
countryCode = potentialCode;
|
|
239
240
|
remainingNumber = withPlus.substring(1 + i); // Everything after the country code
|
|
@@ -246,4 +247,3 @@ export const cleanupPhoneNumber = (phoneNumber) => {
|
|
|
246
247
|
}
|
|
247
248
|
return withPlus;
|
|
248
249
|
};
|
|
249
|
-
//# sourceMappingURL=formatter.js.map
|
package/dist/auth/otp.js
CHANGED
|
@@ -2,7 +2,7 @@ import { ROLES } from '@driveflux/auth/authorization/constants';
|
|
|
2
2
|
import { config } from '@driveflux/config/backend';
|
|
3
3
|
import { prisma } from '@driveflux/db';
|
|
4
4
|
import { generateId } from '@driveflux/db/id';
|
|
5
|
-
import { makeProblem, PROBLEM_CONFLICT, PROBLEM_INVALID_DATA
|
|
5
|
+
import { makeProblem, PROBLEM_CONFLICT, PROBLEM_INVALID_DATA } from '@driveflux/problem';
|
|
6
6
|
import { Err, Ok } from '@driveflux/result';
|
|
7
7
|
import { addDays } from 'date-fns/addDays';
|
|
8
8
|
import { z } from 'zod';
|
|
@@ -13,43 +13,46 @@ const SendVerificationSMSBody = z.object({
|
|
|
13
13
|
phoneNumber: z.string(),
|
|
14
14
|
checkDuplication: z.boolean().optional().nullable(),
|
|
15
15
|
includeUser: z.boolean().optional().nullable(),
|
|
16
|
-
userId: z.string().optional().nullable()
|
|
16
|
+
userId: z.string().optional().nullable()
|
|
17
17
|
});
|
|
18
|
-
const VerifyOtpBody = z
|
|
19
|
-
.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.transform((email) => email?.toLowerCase().trim()),
|
|
18
|
+
const VerifyOtpBody = z.object({
|
|
19
|
+
scope: z.enum([
|
|
20
|
+
'verify-email',
|
|
21
|
+
'verify-phone'
|
|
22
|
+
]),
|
|
23
|
+
email: z.email().optional().transform((email)=>email?.toLowerCase().trim()),
|
|
25
24
|
phoneNumber: z.string().optional(),
|
|
26
|
-
code: z.string()
|
|
27
|
-
})
|
|
28
|
-
.refine((d) => {
|
|
25
|
+
code: z.string()
|
|
26
|
+
}).refine((d)=>{
|
|
29
27
|
if (d.scope === 'verify-email' && !d.email) {
|
|
30
28
|
return false;
|
|
31
29
|
}
|
|
32
30
|
return true;
|
|
33
31
|
}, {
|
|
34
|
-
path: [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
path: [
|
|
33
|
+
'email'
|
|
34
|
+
],
|
|
35
|
+
message: 'Email is required'
|
|
36
|
+
}).refine((d)=>{
|
|
38
37
|
if (d.scope === 'verify-phone' && !d.phoneNumber) {
|
|
39
38
|
return false;
|
|
40
39
|
}
|
|
41
40
|
return true;
|
|
42
41
|
}, {
|
|
43
|
-
path: [
|
|
44
|
-
|
|
42
|
+
path: [
|
|
43
|
+
'phoneNumber'
|
|
44
|
+
],
|
|
45
|
+
message: 'Phone number is required'
|
|
45
46
|
});
|
|
46
47
|
const INVALID_TOKEN_PROBLEM = makeProblem(PROBLEM_INVALID_DATA, 'Unable to verify token. It could have been expired.');
|
|
47
48
|
const VerifyOtpOnlyBody = z.object({
|
|
48
49
|
phoneNumber: z.string().optional(),
|
|
49
|
-
code: z.string()
|
|
50
|
+
code: z.string()
|
|
50
51
|
});
|
|
51
|
-
export const handleVerifyOTPOnly = async ({ phoneNumber, code
|
|
52
|
-
const tokenResult = await verifyToken(code, {
|
|
52
|
+
export const handleVerifyOTPOnly = async ({ phoneNumber, code })=>{
|
|
53
|
+
const tokenResult = await verifyToken(code, {
|
|
54
|
+
scope: 'verify-phone'
|
|
55
|
+
});
|
|
53
56
|
if (tokenResult.err) {
|
|
54
57
|
console.error('Error verifying token', tokenResult.val);
|
|
55
58
|
return new Err(INVALID_TOKEN_PROBLEM);
|
|
@@ -59,13 +62,21 @@ export const handleVerifyOTPOnly = async ({ phoneNumber, code, }) => {
|
|
|
59
62
|
// await clearToken(tokenResult.val.id)
|
|
60
63
|
return new Ok({
|
|
61
64
|
phoneNumber,
|
|
62
|
-
phoneNumberVerified: true
|
|
65
|
+
phoneNumberVerified: true
|
|
63
66
|
});
|
|
64
67
|
};
|
|
65
|
-
export const handleVerifyOTP = async (b)
|
|
66
|
-
const { scope, email, phoneNumber: preFormattedPhoneNumber, code
|
|
68
|
+
export const handleVerifyOTP = async (b)=>{
|
|
69
|
+
const { scope, email, phoneNumber: preFormattedPhoneNumber, code } = VerifyOtpBody.parse(b);
|
|
67
70
|
const phoneNumber = `+${preFormattedPhoneNumber?.replace(/[^0-9]/g, '')}`;
|
|
68
|
-
const tokenResult = await verifyToken(code, {
|
|
71
|
+
const tokenResult = await verifyToken(code, {
|
|
72
|
+
scope,
|
|
73
|
+
metadata: {
|
|
74
|
+
email,
|
|
75
|
+
phoneNumber
|
|
76
|
+
}
|
|
77
|
+
}, {
|
|
78
|
+
includeUser: true
|
|
79
|
+
});
|
|
69
80
|
if (tokenResult.err) {
|
|
70
81
|
return new Err(INVALID_TOKEN_PROBLEM);
|
|
71
82
|
}
|
|
@@ -73,25 +84,25 @@ export const handleVerifyOTP = async (b) => {
|
|
|
73
84
|
return new Err(INVALID_TOKEN_PROBLEM);
|
|
74
85
|
}
|
|
75
86
|
const previousUser = tokenResult.val.user;
|
|
76
|
-
const userUpdate = scope === 'verify-email'
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
phoneNumber,
|
|
84
|
-
};
|
|
87
|
+
const userUpdate = scope === 'verify-email' ? {
|
|
88
|
+
emailVerified: true,
|
|
89
|
+
email
|
|
90
|
+
} : {
|
|
91
|
+
phoneNumberVerified: true,
|
|
92
|
+
phoneNumber
|
|
93
|
+
};
|
|
85
94
|
userUpdate.temporary = false;
|
|
86
95
|
userUpdate.temporaryEmail = null;
|
|
87
96
|
const userGroups = new Set(tokenResult.val.user?.groups);
|
|
88
97
|
userGroups.add(ROLES.MEMBER);
|
|
89
|
-
userUpdate.groups = [
|
|
98
|
+
userUpdate.groups = [
|
|
99
|
+
...userGroups
|
|
100
|
+
];
|
|
90
101
|
const user = await prisma.user.update({
|
|
91
102
|
where: {
|
|
92
|
-
id: tokenResult.val.user.id
|
|
103
|
+
id: tokenResult.val.user.id
|
|
93
104
|
},
|
|
94
|
-
data: userUpdate
|
|
105
|
+
data: userUpdate
|
|
95
106
|
});
|
|
96
107
|
// delete the previous token
|
|
97
108
|
await clearToken(tokenResult.val.id);
|
|
@@ -101,12 +112,12 @@ export const handleVerifyOTP = async (b) => {
|
|
|
101
112
|
id: generateId('Token'),
|
|
102
113
|
user: {
|
|
103
114
|
connect: {
|
|
104
|
-
id: user?.id
|
|
105
|
-
}
|
|
115
|
+
id: user?.id
|
|
116
|
+
}
|
|
106
117
|
},
|
|
107
118
|
expiresAt: addDays(new Date(), 365),
|
|
108
|
-
scope: 'all'
|
|
109
|
-
}
|
|
119
|
+
scope: 'all'
|
|
120
|
+
}
|
|
110
121
|
});
|
|
111
122
|
if (previousUser.email !== user.email) {
|
|
112
123
|
await sendEmailChangedEmail(user.id);
|
|
@@ -114,21 +125,25 @@ export const handleVerifyOTP = async (b) => {
|
|
|
114
125
|
return new Ok({
|
|
115
126
|
accessToken: token.id,
|
|
116
127
|
expiresAt: token.expiresAt,
|
|
117
|
-
user: user
|
|
128
|
+
user: user
|
|
118
129
|
});
|
|
119
130
|
};
|
|
120
|
-
export const handleSendVerificationSMS = async (b)
|
|
131
|
+
export const handleSendVerificationSMS = async (b)=>{
|
|
121
132
|
const { phoneNumber, checkDuplication, userId } = SendVerificationSMSBody.parse(b);
|
|
122
133
|
const formattedPhoneNumber = `+${phoneNumber.replace(/[^0-9]/g, '')}`;
|
|
123
134
|
if (checkDuplication) {
|
|
124
135
|
const user = await prisma.user.findFirst({
|
|
125
136
|
where: {
|
|
126
137
|
OR: [
|
|
127
|
-
{
|
|
128
|
-
|
|
138
|
+
{
|
|
139
|
+
phoneNumber: formattedPhoneNumber
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
phoneNumber: phoneNumber
|
|
143
|
+
}
|
|
129
144
|
],
|
|
130
|
-
phoneNumberVerified: true
|
|
131
|
-
}
|
|
145
|
+
phoneNumberVerified: true
|
|
146
|
+
}
|
|
132
147
|
});
|
|
133
148
|
if (user) {
|
|
134
149
|
return new Err(makeProblem(PROBLEM_CONFLICT, 'This phone number is already registered'));
|
|
@@ -141,7 +156,7 @@ export const handleSendVerificationSMS = async (b) => {
|
|
|
141
156
|
}
|
|
142
157
|
return new Ok({
|
|
143
158
|
success: true,
|
|
144
|
-
code: code.value
|
|
159
|
+
code: code.value
|
|
145
160
|
});
|
|
146
161
|
}
|
|
147
162
|
// Send the sms verification
|
|
@@ -149,6 +164,7 @@ export const handleSendVerificationSMS = async (b) => {
|
|
|
149
164
|
if (verificationResult.err) {
|
|
150
165
|
return verificationResult;
|
|
151
166
|
}
|
|
152
|
-
return new Ok({
|
|
167
|
+
return new Ok({
|
|
168
|
+
success: true
|
|
169
|
+
});
|
|
153
170
|
};
|
|
154
|
-
//# sourceMappingURL=otp.js.map
|
package/dist/auth/register.js
CHANGED
|
@@ -19,19 +19,25 @@ import { sendVerificationEmail } from './verifications.js';
|
|
|
19
19
|
export const RegistrationValidation = z.object({
|
|
20
20
|
firstName: z.string(),
|
|
21
21
|
lastName: z.string(),
|
|
22
|
-
phoneNumber: z.string().transform((s)
|
|
23
|
-
authMethod: z.enum([
|
|
22
|
+
phoneNumber: z.string().transform((s)=>s.replace(/[\s-]/g, '')),
|
|
23
|
+
authMethod: z.enum([
|
|
24
|
+
'mobile',
|
|
25
|
+
'email',
|
|
26
|
+
'facebook',
|
|
27
|
+
'google',
|
|
28
|
+
'apple'
|
|
29
|
+
]),
|
|
24
30
|
code: z.string().optional().nullable(),
|
|
25
31
|
keepCode: z.boolean().optional().default(false),
|
|
26
|
-
email: z.email().transform((s)
|
|
27
|
-
dateOfBirth: dateValidation
|
|
28
|
-
.refine((d) => {
|
|
32
|
+
email: z.email().transform((s)=>s.toLowerCase().trim()),
|
|
33
|
+
dateOfBirth: dateValidation.refine((d)=>{
|
|
29
34
|
return isAfter(d, subYears(new Date(), 25));
|
|
30
35
|
}, {
|
|
31
|
-
path: [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.
|
|
36
|
+
path: [
|
|
37
|
+
'dateOfBirth'
|
|
38
|
+
],
|
|
39
|
+
message: 'You must be at least 25 years old to signup for the service.'
|
|
40
|
+
}).optional(),
|
|
35
41
|
password: z.string().min(6).optional(),
|
|
36
42
|
noMarketing: z.boolean().optional(),
|
|
37
43
|
pageSource: z.string().optional().nullable(),
|
|
@@ -41,12 +47,14 @@ export const RegistrationValidation = z.object({
|
|
|
41
47
|
userAgent: z.string().optional(),
|
|
42
48
|
ipAddress: z.ipv4().or(z.ipv6()),
|
|
43
49
|
sessionToken: z.string().optional(),
|
|
44
|
-
sessionId: z.string().optional()
|
|
50
|
+
sessionId: z.string().optional()
|
|
45
51
|
});
|
|
46
|
-
export const handleRegister = async ({ noMarketing, password, authMethod, phoneNumber, code, keepCode, pageSource, skipPassword, fingerprint, termsVersion, userAgent, ipAddress, sessionToken, sessionId, ...body })
|
|
52
|
+
export const handleRegister = async ({ noMarketing, password, authMethod, phoneNumber, code, keepCode, pageSource, skipPassword, fingerprint, termsVersion, userAgent, ipAddress, sessionToken, sessionId, ...body })=>{
|
|
47
53
|
let phoneNumberVerified = false;
|
|
48
54
|
if (code) {
|
|
49
|
-
const tokenResult = await verifyToken(code, {
|
|
55
|
+
const tokenResult = await verifyToken(code, {
|
|
56
|
+
scope: 'verify-phone'
|
|
57
|
+
});
|
|
50
58
|
if (tokenResult.err) {
|
|
51
59
|
return new Err(makeProblem(PROBLEM_CONFLICT, 'Invalid OTP token'));
|
|
52
60
|
}
|
|
@@ -60,7 +68,9 @@ export const handleRegister = async ({ noMarketing, password, authMethod, phoneN
|
|
|
60
68
|
}
|
|
61
69
|
// Check if the user exists
|
|
62
70
|
const foundUser = await prisma.user.findFirst({
|
|
63
|
-
where: {
|
|
71
|
+
where: {
|
|
72
|
+
email: body.email
|
|
73
|
+
}
|
|
64
74
|
});
|
|
65
75
|
if (foundUser) {
|
|
66
76
|
return new Err(makeProblem(PROBLEM_CONFLICT, 'A user with this email address already exists. Did you mean to login?'));
|
|
@@ -77,10 +87,12 @@ export const handleRegister = async ({ noMarketing, password, authMethod, phoneN
|
|
|
77
87
|
preferredCurrency: 'MYR',
|
|
78
88
|
preferredLocale: 'en',
|
|
79
89
|
phoneNumberVerified,
|
|
80
|
-
groups: [
|
|
90
|
+
groups: [
|
|
91
|
+
'member'
|
|
92
|
+
],
|
|
81
93
|
signupParams: {
|
|
82
94
|
method: authMethod,
|
|
83
|
-
source: pageSource
|
|
95
|
+
source: pageSource
|
|
84
96
|
},
|
|
85
97
|
registrationComplete: true,
|
|
86
98
|
accounts: {
|
|
@@ -89,16 +101,16 @@ export const handleRegister = async ({ noMarketing, password, authMethod, phoneN
|
|
|
89
101
|
object: 'account',
|
|
90
102
|
type: 'default',
|
|
91
103
|
provider: 'credentials',
|
|
92
|
-
providerAccountId: id
|
|
93
|
-
}
|
|
104
|
+
providerAccountId: id
|
|
105
|
+
}
|
|
94
106
|
},
|
|
95
107
|
tokens: {
|
|
96
108
|
create: {
|
|
97
109
|
id: tokenId,
|
|
98
110
|
expiresAt: addDays(new Date(), 365),
|
|
99
|
-
scope: 'all'
|
|
100
|
-
}
|
|
101
|
-
}
|
|
111
|
+
scope: 'all'
|
|
112
|
+
}
|
|
113
|
+
}
|
|
102
114
|
};
|
|
103
115
|
const { user: _removeDueToNestedCreate, ...consentCreate } = getConsentCreateData({
|
|
104
116
|
user: userCreateData,
|
|
@@ -107,28 +119,28 @@ export const handleRegister = async ({ noMarketing, password, authMethod, phoneN
|
|
|
107
119
|
ipAddress: ipAddress,
|
|
108
120
|
userAgent: userAgent,
|
|
109
121
|
sessionToken: tokenId,
|
|
110
|
-
consentType: 'terms'
|
|
122
|
+
consentType: 'terms'
|
|
111
123
|
});
|
|
112
124
|
const finalCreateData = {
|
|
113
125
|
...userCreateData,
|
|
114
126
|
consents: {
|
|
115
|
-
create: consentCreate
|
|
116
|
-
}
|
|
127
|
+
create: consentCreate
|
|
128
|
+
}
|
|
117
129
|
};
|
|
118
130
|
// Find a host with the same email
|
|
119
131
|
const host = await prisma.host.findFirst({
|
|
120
132
|
where: {
|
|
121
|
-
email: finalCreateData.email
|
|
133
|
+
email: finalCreateData.email
|
|
122
134
|
},
|
|
123
135
|
select: {
|
|
124
|
-
id: true
|
|
125
|
-
}
|
|
136
|
+
id: true
|
|
137
|
+
}
|
|
126
138
|
});
|
|
127
139
|
if (host?.id) {
|
|
128
140
|
finalCreateData.host = {
|
|
129
141
|
connect: {
|
|
130
|
-
id: host.id
|
|
131
|
-
}
|
|
142
|
+
id: host.id
|
|
143
|
+
}
|
|
132
144
|
};
|
|
133
145
|
}
|
|
134
146
|
const user = await prisma.user.create({
|
|
@@ -136,20 +148,21 @@ export const handleRegister = async ({ noMarketing, password, authMethod, phoneN
|
|
|
136
148
|
include: {
|
|
137
149
|
tokens: {
|
|
138
150
|
where: {
|
|
139
|
-
id: tokenId
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
151
|
+
id: tokenId
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
143
155
|
});
|
|
144
156
|
// We don't want this to be a task. It should be instant
|
|
145
157
|
await sendVerificationEmail(user.id);
|
|
146
158
|
if (!noMarketing) {
|
|
147
|
-
await setContactInList(user.id, {
|
|
159
|
+
await setContactInList(user.id, {
|
|
160
|
+
generalMarketing: true
|
|
161
|
+
});
|
|
148
162
|
}
|
|
149
163
|
await refreshEmailPreferences(user.id);
|
|
150
164
|
return new Ok({
|
|
151
165
|
token: user.tokens[0],
|
|
152
|
-
user
|
|
166
|
+
user
|
|
153
167
|
});
|
|
154
168
|
};
|
|
155
|
-
//# sourceMappingURL=register.js.map
|