vr-commons 1.0.113 → 1.0.115
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/middlewares/auth.users.middlewares.js +2 -2
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +4 -2
- package/dist/utils/verification.utils.d.ts +17 -0
- package/dist/utils/verification.utils.js +37 -1
- package/dist/validations/account.validations.d.ts +231 -0
- package/dist/validations/account.validations.js +136 -3
- package/dist/validations/auth.validations.d.ts +191 -49
- package/dist/validations/auth.validations.js +133 -18
- package/dist/validations/index.d.ts +1 -1
- package/dist/validations/index.js +6 -2
- package/dist/validations/profiles.validations.d.ts +271 -123
- package/dist/validations/profiles.validations.js +135 -46
- package/dist/validations/users.admin.validations.d.ts +223 -72
- package/dist/validations/users.admin.validations.js +105 -13
- package/package.json +1 -1
|
@@ -21,7 +21,7 @@ const checkUserAuthentication = (allowedRoles) => async (req, res, next) => {
|
|
|
21
21
|
}
|
|
22
22
|
catch (error) {
|
|
23
23
|
if (error instanceof jsonwebtoken_1.default.TokenExpiredError) {
|
|
24
|
-
return (0, response_utils_1.sendErrorResponse)(res, "Token expired. Please re-verify your
|
|
24
|
+
return (0, response_utils_1.sendErrorResponse)(res, "Token expired. Please re-verify your Email/Phone", 401);
|
|
25
25
|
}
|
|
26
26
|
return (0, response_utils_1.sendErrorResponse)(res, "Token invalid", 401);
|
|
27
27
|
}
|
|
@@ -40,7 +40,7 @@ const checkUserAuthentication = (allowedRoles) => async (req, res, next) => {
|
|
|
40
40
|
}
|
|
41
41
|
// 🔐 Token versioning (logout all devices)
|
|
42
42
|
if (user.tokenVersion !== payload.tokenVersion) {
|
|
43
|
-
return (0, response_utils_1.sendErrorResponse)(res, "Session expired. Please re-verify your
|
|
43
|
+
return (0, response_utils_1.sendErrorResponse)(res, "Session expired. Please re-verify your Email/Phone", 401);
|
|
44
44
|
}
|
|
45
45
|
// 🧱 Role enforcement
|
|
46
46
|
if (!allowedRoles.includes(user.securityClearance.role)) {
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { canModerate, canModerateUser, getModeratableRoles, hasHigherAuthority,
|
|
|
7
7
|
export { banUtil } from "./bans.utils";
|
|
8
8
|
export { suspensionUtil } from "./suspension.utils";
|
|
9
9
|
export { createDeviceSession } from "./session.utils";
|
|
10
|
-
export { generateOTP, getOTPExpiry, getVerificationMethod, sendEmail, sendSMS, sendVerificationCode, } from "./verification.utils";
|
|
10
|
+
export { generateOTP, getOTPExpiry, getVerificationMethod, sendEmail, sendSMS, sendVerificationCode, detectContactType, validateContactValue, } from "./verification.utils";
|
|
11
11
|
export { getUserLevel, isRankEqual, isSubordinate, isSubordinateOrEqual, isSuperior, isSuperiorOrEqual, validateHierarchy, } from "./hierarchy.utils";
|
|
12
12
|
export { stockUtil } from "./admin.device.utils";
|
|
13
13
|
export { cloudinaryUtil } from "./product.utils";
|
package/dist/utils/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.buildUserSearchConditions = exports.buildSearchConditions = exports.buildEventLogWhereClause = exports.formatEventLogs = exports.formatEventLog = exports.formatDeviceSession = exports.DPP_OperationsUtil = exports.cloudinaryUtil = exports.stockUtil = exports.validateHierarchy = exports.isSuperiorOrEqual = exports.isSuperior = exports.isSubordinateOrEqual = exports.isSubordinate = void 0;
|
|
3
|
+
exports.validateContactValue = exports.detectContactType = exports.sendVerificationCode = exports.sendSMS = exports.sendEmail = exports.getVerificationMethod = exports.getOTPExpiry = exports.generateOTP = exports.createDeviceSession = exports.suspensionUtil = exports.banUtil = exports.hasHigherAuthority = exports.getModeratableRoles = exports.canModerateUser = exports.canModerate = exports.softDeleteUser = exports.hashPassword = exports.validatePassword = exports.validateUniqueFields = exports.generateJacketId = exports.getSortOrder = exports.generateEventSearchConditions = exports.generateUserSearchConditions = exports.findSecurityClearanceByRole = exports.getUsersByRole = exports.getUserById = exports.isAccountAccessible = exports.canModifyAccount = exports.hasAllPermissions = exports.hasAnyPermission = exports.hasPermission = exports.hasRole = exports.formatUserListResponse = exports.formatUserProfile = exports.sendErrorResponse = exports.sendSuccessResponse = exports.logEvent = exports.formatTimeRemaining = exports.getTokenTimeRemaining = exports.generateToken = exports.shouldRefreshToken = exports.verifyToken = exports.generateRiderToken = exports.generatePassengerToken = exports.generateAdminToken = exports.checkSuspensionStatus = exports.checkIsUserBannedOrSuspended = exports.checkBanStatus = exports.hasActiveDependencies = exports.checkAccountDependencies = void 0;
|
|
4
|
+
exports.buildUserSearchConditions = exports.buildSearchConditions = exports.buildEventLogWhereClause = exports.formatEventLogs = exports.formatEventLog = exports.formatDeviceSession = exports.DPP_OperationsUtil = exports.cloudinaryUtil = exports.stockUtil = exports.validateHierarchy = exports.isSuperiorOrEqual = exports.isSuperior = exports.isSubordinateOrEqual = exports.isSubordinate = exports.isRankEqual = exports.getUserLevel = void 0;
|
|
5
5
|
var account_utils_1 = require("./account.utils");
|
|
6
6
|
Object.defineProperty(exports, "checkAccountDependencies", { enumerable: true, get: function () { return account_utils_1.checkAccountDependencies; } });
|
|
7
7
|
Object.defineProperty(exports, "hasActiveDependencies", { enumerable: true, get: function () { return account_utils_1.hasActiveDependencies; } });
|
|
@@ -67,6 +67,8 @@ Object.defineProperty(exports, "getVerificationMethod", { enumerable: true, get:
|
|
|
67
67
|
Object.defineProperty(exports, "sendEmail", { enumerable: true, get: function () { return verification_utils_1.sendEmail; } });
|
|
68
68
|
Object.defineProperty(exports, "sendSMS", { enumerable: true, get: function () { return verification_utils_1.sendSMS; } });
|
|
69
69
|
Object.defineProperty(exports, "sendVerificationCode", { enumerable: true, get: function () { return verification_utils_1.sendVerificationCode; } });
|
|
70
|
+
Object.defineProperty(exports, "detectContactType", { enumerable: true, get: function () { return verification_utils_1.detectContactType; } });
|
|
71
|
+
Object.defineProperty(exports, "validateContactValue", { enumerable: true, get: function () { return verification_utils_1.validateContactValue; } });
|
|
70
72
|
var hierarchy_utils_1 = require("./hierarchy.utils");
|
|
71
73
|
Object.defineProperty(exports, "getUserLevel", { enumerable: true, get: function () { return hierarchy_utils_1.getUserLevel; } });
|
|
72
74
|
Object.defineProperty(exports, "isRankEqual", { enumerable: true, get: function () { return hierarchy_utils_1.isRankEqual; } });
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import { VerificationMethod } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Regular expressions for contact validation
|
|
4
|
+
*/
|
|
5
|
+
export declare const phoneRegex: RegExp;
|
|
6
|
+
export declare const emailRegex: RegExp;
|
|
7
|
+
/**
|
|
8
|
+
* Detect the type of contact value
|
|
9
|
+
* @param value - The contact value to check (email or phone number)
|
|
10
|
+
* @returns The contact type: 'EMAIL', 'PHONE', 'WHATSAPP', or 'UNKNOWN'
|
|
11
|
+
*/
|
|
12
|
+
export declare const detectContactType: (value: string) => "EMAIL" | "PHONE" | "WHATSAPP" | "UNKNOWN";
|
|
13
|
+
/**
|
|
14
|
+
* Validate if a contact value is valid (either email or phone)
|
|
15
|
+
* @param value - The contact value to validate
|
|
16
|
+
* @returns True if valid email or phone, false otherwise
|
|
17
|
+
*/
|
|
18
|
+
export declare const validateContactValue: (value: string) => boolean;
|
|
2
19
|
export declare const getVerificationMethod: () => VerificationMethod;
|
|
3
20
|
export declare const generateOTP: (length?: number) => string;
|
|
4
21
|
export declare const getOTPExpiry: (minutes?: number) => Date;
|
|
@@ -3,8 +3,44 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.sendVerificationCode = exports.sendEmail = exports.sendSMS = exports.getOTPExpiry = exports.generateOTP = exports.getVerificationMethod = void 0;
|
|
6
|
+
exports.sendVerificationCode = exports.sendEmail = exports.sendSMS = exports.getOTPExpiry = exports.generateOTP = exports.getVerificationMethod = exports.validateContactValue = exports.detectContactType = exports.emailRegex = exports.phoneRegex = void 0;
|
|
7
7
|
const nodemailer_1 = __importDefault(require("nodemailer"));
|
|
8
|
+
// ==================== CONTACT VALIDATION HELPERS ====================
|
|
9
|
+
/**
|
|
10
|
+
* Regular expressions for contact validation
|
|
11
|
+
*/
|
|
12
|
+
exports.phoneRegex = /^\+250(78|79|73|72)[0-9]{7}$/;
|
|
13
|
+
exports.emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
14
|
+
/**
|
|
15
|
+
* Detect the type of contact value
|
|
16
|
+
* @param value - The contact value to check (email or phone number)
|
|
17
|
+
* @returns The contact type: 'EMAIL', 'PHONE', 'WHATSAPP', or 'UNKNOWN'
|
|
18
|
+
*/
|
|
19
|
+
const detectContactType = (value) => {
|
|
20
|
+
if (!value)
|
|
21
|
+
return "UNKNOWN";
|
|
22
|
+
// Check if it's an email
|
|
23
|
+
if (exports.emailRegex.test(value)) {
|
|
24
|
+
return "EMAIL";
|
|
25
|
+
}
|
|
26
|
+
// Check if it's a phone number
|
|
27
|
+
if (exports.phoneRegex.test(value)) {
|
|
28
|
+
return "PHONE";
|
|
29
|
+
}
|
|
30
|
+
return "UNKNOWN";
|
|
31
|
+
};
|
|
32
|
+
exports.detectContactType = detectContactType;
|
|
33
|
+
/**
|
|
34
|
+
* Validate if a contact value is valid (either email or phone)
|
|
35
|
+
* @param value - The contact value to validate
|
|
36
|
+
* @returns True if valid email or phone, false otherwise
|
|
37
|
+
*/
|
|
38
|
+
const validateContactValue = (value) => {
|
|
39
|
+
if (!value)
|
|
40
|
+
return false;
|
|
41
|
+
return exports.emailRegex.test(value) || exports.phoneRegex.test(value);
|
|
42
|
+
};
|
|
43
|
+
exports.validateContactValue = validateContactValue;
|
|
8
44
|
// Get verification method from env
|
|
9
45
|
const getVerificationMethod = () => {
|
|
10
46
|
const method = process.env.VERIFICATION_METHOD?.toUpperCase();
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const phoneRegex: RegExp;
|
|
3
|
+
export declare const emailRegex: RegExp;
|
|
3
4
|
export declare const strongPasswordRegex: RegExp;
|
|
5
|
+
export declare const detectContactType: (value: string) => "EMAIL" | "PHONE" | "WHATSAPP" | "UNKNOWN";
|
|
6
|
+
export declare const validateContactValue: (value: string) => boolean;
|
|
4
7
|
export declare const updateProfileSchema: z.ZodObject<{
|
|
5
8
|
body: z.ZodObject<{
|
|
6
9
|
firstName: z.ZodOptional<z.ZodString>;
|
|
@@ -28,6 +31,40 @@ export declare const updateProfileSchema: z.ZodObject<{
|
|
|
28
31
|
plateNumber?: string | undefined;
|
|
29
32
|
};
|
|
30
33
|
}>;
|
|
34
|
+
export declare const updateContactSchema: z.ZodObject<{
|
|
35
|
+
body: z.ZodObject<{
|
|
36
|
+
contactValue: z.ZodEffects<z.ZodString, string, string>;
|
|
37
|
+
}, "strip", z.ZodTypeAny, {
|
|
38
|
+
contactValue: string;
|
|
39
|
+
}, {
|
|
40
|
+
contactValue: string;
|
|
41
|
+
}>;
|
|
42
|
+
}, "strip", z.ZodTypeAny, {
|
|
43
|
+
body: {
|
|
44
|
+
contactValue: string;
|
|
45
|
+
};
|
|
46
|
+
}, {
|
|
47
|
+
body: {
|
|
48
|
+
contactValue: string;
|
|
49
|
+
};
|
|
50
|
+
}>;
|
|
51
|
+
export declare const changeEmailSchema: z.ZodObject<{
|
|
52
|
+
body: z.ZodObject<{
|
|
53
|
+
newEmail: z.ZodString;
|
|
54
|
+
}, "strip", z.ZodTypeAny, {
|
|
55
|
+
newEmail: string;
|
|
56
|
+
}, {
|
|
57
|
+
newEmail: string;
|
|
58
|
+
}>;
|
|
59
|
+
}, "strip", z.ZodTypeAny, {
|
|
60
|
+
body: {
|
|
61
|
+
newEmail: string;
|
|
62
|
+
};
|
|
63
|
+
}, {
|
|
64
|
+
body: {
|
|
65
|
+
newEmail: string;
|
|
66
|
+
};
|
|
67
|
+
}>;
|
|
31
68
|
export declare const requestPhoneChangeSchema: z.ZodObject<{
|
|
32
69
|
body: z.ZodObject<{
|
|
33
70
|
newPhoneNumber: z.ZodString;
|
|
@@ -67,6 +104,113 @@ export declare const verifyPhoneChangeSchema: z.ZodObject<{
|
|
|
67
104
|
newPhoneOtp: string;
|
|
68
105
|
};
|
|
69
106
|
}>;
|
|
107
|
+
export declare const verifyEmailChangeSchema: z.ZodObject<{
|
|
108
|
+
body: z.ZodObject<{
|
|
109
|
+
emailOtp: z.ZodString;
|
|
110
|
+
}, "strip", z.ZodTypeAny, {
|
|
111
|
+
emailOtp: string;
|
|
112
|
+
}, {
|
|
113
|
+
emailOtp: string;
|
|
114
|
+
}>;
|
|
115
|
+
}, "strip", z.ZodTypeAny, {
|
|
116
|
+
body: {
|
|
117
|
+
emailOtp: string;
|
|
118
|
+
};
|
|
119
|
+
}, {
|
|
120
|
+
body: {
|
|
121
|
+
emailOtp: string;
|
|
122
|
+
};
|
|
123
|
+
}>;
|
|
124
|
+
export declare const addContactSchema: z.ZodObject<{
|
|
125
|
+
body: z.ZodObject<{
|
|
126
|
+
contactValue: z.ZodEffects<z.ZodString, string, string>;
|
|
127
|
+
type: z.ZodEffects<z.ZodOptional<z.ZodEnum<["EMAIL", "PHONE", "WHATSAPP"]>>, "EMAIL" | "PHONE" | "WHATSAPP" | undefined, "EMAIL" | "PHONE" | "WHATSAPP" | undefined>;
|
|
128
|
+
}, "strip", z.ZodTypeAny, {
|
|
129
|
+
contactValue: string;
|
|
130
|
+
type?: "EMAIL" | "PHONE" | "WHATSAPP" | undefined;
|
|
131
|
+
}, {
|
|
132
|
+
contactValue: string;
|
|
133
|
+
type?: "EMAIL" | "PHONE" | "WHATSAPP" | undefined;
|
|
134
|
+
}>;
|
|
135
|
+
}, "strip", z.ZodTypeAny, {
|
|
136
|
+
body: {
|
|
137
|
+
contactValue: string;
|
|
138
|
+
type?: "EMAIL" | "PHONE" | "WHATSAPP" | undefined;
|
|
139
|
+
};
|
|
140
|
+
}, {
|
|
141
|
+
body: {
|
|
142
|
+
contactValue: string;
|
|
143
|
+
type?: "EMAIL" | "PHONE" | "WHATSAPP" | undefined;
|
|
144
|
+
};
|
|
145
|
+
}>;
|
|
146
|
+
export declare const deleteContactSchema: z.ZodObject<{
|
|
147
|
+
params: z.ZodObject<{
|
|
148
|
+
contactId: z.ZodString;
|
|
149
|
+
}, "strip", z.ZodTypeAny, {
|
|
150
|
+
contactId: string;
|
|
151
|
+
}, {
|
|
152
|
+
contactId: string;
|
|
153
|
+
}>;
|
|
154
|
+
}, "strip", z.ZodTypeAny, {
|
|
155
|
+
params: {
|
|
156
|
+
contactId: string;
|
|
157
|
+
};
|
|
158
|
+
}, {
|
|
159
|
+
params: {
|
|
160
|
+
contactId: string;
|
|
161
|
+
};
|
|
162
|
+
}>;
|
|
163
|
+
export declare const setPrimaryContactSchema: z.ZodObject<{
|
|
164
|
+
params: z.ZodObject<{
|
|
165
|
+
contactId: z.ZodString;
|
|
166
|
+
}, "strip", z.ZodTypeAny, {
|
|
167
|
+
contactId: string;
|
|
168
|
+
}, {
|
|
169
|
+
contactId: string;
|
|
170
|
+
}>;
|
|
171
|
+
}, "strip", z.ZodTypeAny, {
|
|
172
|
+
params: {
|
|
173
|
+
contactId: string;
|
|
174
|
+
};
|
|
175
|
+
}, {
|
|
176
|
+
params: {
|
|
177
|
+
contactId: string;
|
|
178
|
+
};
|
|
179
|
+
}>;
|
|
180
|
+
export declare const verifyContactSchema: z.ZodObject<{
|
|
181
|
+
params: z.ZodObject<{
|
|
182
|
+
contactId: z.ZodString;
|
|
183
|
+
}, "strip", z.ZodTypeAny, {
|
|
184
|
+
contactId: string;
|
|
185
|
+
}, {
|
|
186
|
+
contactId: string;
|
|
187
|
+
}>;
|
|
188
|
+
}, "strip", z.ZodTypeAny, {
|
|
189
|
+
params: {
|
|
190
|
+
contactId: string;
|
|
191
|
+
};
|
|
192
|
+
}, {
|
|
193
|
+
params: {
|
|
194
|
+
contactId: string;
|
|
195
|
+
};
|
|
196
|
+
}>;
|
|
197
|
+
export declare const confirmVerificationSchema: z.ZodObject<{
|
|
198
|
+
body: z.ZodObject<{
|
|
199
|
+
otp: z.ZodString;
|
|
200
|
+
}, "strip", z.ZodTypeAny, {
|
|
201
|
+
otp: string;
|
|
202
|
+
}, {
|
|
203
|
+
otp: string;
|
|
204
|
+
}>;
|
|
205
|
+
}, "strip", z.ZodTypeAny, {
|
|
206
|
+
body: {
|
|
207
|
+
otp: string;
|
|
208
|
+
};
|
|
209
|
+
}, {
|
|
210
|
+
body: {
|
|
211
|
+
otp: string;
|
|
212
|
+
};
|
|
213
|
+
}>;
|
|
70
214
|
export declare const deleteAccountSchema: z.ZodObject<{
|
|
71
215
|
body: z.ZodObject<{
|
|
72
216
|
confirmation: z.ZodLiteral<"DELETE">;
|
|
@@ -111,3 +255,90 @@ export declare const changePasswordSchema: z.ZodObject<{
|
|
|
111
255
|
newPassword: string;
|
|
112
256
|
};
|
|
113
257
|
}>;
|
|
258
|
+
export declare const loginSchema: z.ZodObject<{
|
|
259
|
+
body: z.ZodObject<{
|
|
260
|
+
contactValue: z.ZodEffects<z.ZodString, string, string>;
|
|
261
|
+
password: z.ZodString;
|
|
262
|
+
}, "strip", z.ZodTypeAny, {
|
|
263
|
+
password: string;
|
|
264
|
+
contactValue: string;
|
|
265
|
+
}, {
|
|
266
|
+
password: string;
|
|
267
|
+
contactValue: string;
|
|
268
|
+
}>;
|
|
269
|
+
}, "strip", z.ZodTypeAny, {
|
|
270
|
+
body: {
|
|
271
|
+
password: string;
|
|
272
|
+
contactValue: string;
|
|
273
|
+
};
|
|
274
|
+
}, {
|
|
275
|
+
body: {
|
|
276
|
+
password: string;
|
|
277
|
+
contactValue: string;
|
|
278
|
+
};
|
|
279
|
+
}>;
|
|
280
|
+
export declare const forgotPasswordSchema: z.ZodObject<{
|
|
281
|
+
body: z.ZodObject<{
|
|
282
|
+
contactValue: z.ZodEffects<z.ZodString, string, string>;
|
|
283
|
+
}, "strip", z.ZodTypeAny, {
|
|
284
|
+
contactValue: string;
|
|
285
|
+
}, {
|
|
286
|
+
contactValue: string;
|
|
287
|
+
}>;
|
|
288
|
+
}, "strip", z.ZodTypeAny, {
|
|
289
|
+
body: {
|
|
290
|
+
contactValue: string;
|
|
291
|
+
};
|
|
292
|
+
}, {
|
|
293
|
+
body: {
|
|
294
|
+
contactValue: string;
|
|
295
|
+
};
|
|
296
|
+
}>;
|
|
297
|
+
export declare const resetPasswordSchema: z.ZodEffects<z.ZodObject<{
|
|
298
|
+
body: z.ZodObject<{
|
|
299
|
+
newPassword: z.ZodString;
|
|
300
|
+
confirmPassword: z.ZodString;
|
|
301
|
+
}, "strip", z.ZodTypeAny, {
|
|
302
|
+
newPassword: string;
|
|
303
|
+
confirmPassword: string;
|
|
304
|
+
}, {
|
|
305
|
+
newPassword: string;
|
|
306
|
+
confirmPassword: string;
|
|
307
|
+
}>;
|
|
308
|
+
}, "strip", z.ZodTypeAny, {
|
|
309
|
+
body: {
|
|
310
|
+
newPassword: string;
|
|
311
|
+
confirmPassword: string;
|
|
312
|
+
};
|
|
313
|
+
}, {
|
|
314
|
+
body: {
|
|
315
|
+
newPassword: string;
|
|
316
|
+
confirmPassword: string;
|
|
317
|
+
};
|
|
318
|
+
}>, {
|
|
319
|
+
body: {
|
|
320
|
+
newPassword: string;
|
|
321
|
+
confirmPassword: string;
|
|
322
|
+
};
|
|
323
|
+
}, {
|
|
324
|
+
body: {
|
|
325
|
+
newPassword: string;
|
|
326
|
+
confirmPassword: string;
|
|
327
|
+
};
|
|
328
|
+
}>;
|
|
329
|
+
export type UpdateProfileSchema = z.infer<typeof updateProfileSchema>;
|
|
330
|
+
export type UpdateContactSchema = z.infer<typeof updateContactSchema>;
|
|
331
|
+
export type ChangeEmailSchema = z.infer<typeof changeEmailSchema>;
|
|
332
|
+
export type RequestPhoneChangeSchema = z.infer<typeof requestPhoneChangeSchema>;
|
|
333
|
+
export type VerifyPhoneChangeSchema = z.infer<typeof verifyPhoneChangeSchema>;
|
|
334
|
+
export type VerifyEmailChangeSchema = z.infer<typeof verifyEmailChangeSchema>;
|
|
335
|
+
export type AddContactSchema = z.infer<typeof addContactSchema>;
|
|
336
|
+
export type DeleteContactSchema = z.infer<typeof deleteContactSchema>;
|
|
337
|
+
export type SetPrimaryContactSchema = z.infer<typeof setPrimaryContactSchema>;
|
|
338
|
+
export type VerifyContactSchema = z.infer<typeof verifyContactSchema>;
|
|
339
|
+
export type ConfirmVerificationSchema = z.infer<typeof confirmVerificationSchema>;
|
|
340
|
+
export type DeleteAccountSchema = z.infer<typeof deleteAccountSchema>;
|
|
341
|
+
export type ChangePasswordSchema = z.infer<typeof changePasswordSchema>;
|
|
342
|
+
export type LoginSchema = z.infer<typeof loginSchema>;
|
|
343
|
+
export type ForgotPasswordSchema = z.infer<typeof forgotPasswordSchema>;
|
|
344
|
+
export type ResetPasswordSchema = z.infer<typeof resetPasswordSchema>;
|
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.changePasswordSchema = exports.deleteAccountSchema = exports.verifyPhoneChangeSchema = exports.requestPhoneChangeSchema = exports.updateProfileSchema = exports.strongPasswordRegex = exports.phoneRegex = void 0;
|
|
3
|
+
exports.resetPasswordSchema = exports.forgotPasswordSchema = exports.loginSchema = exports.changePasswordSchema = exports.deleteAccountSchema = exports.confirmVerificationSchema = exports.verifyContactSchema = exports.setPrimaryContactSchema = exports.deleteContactSchema = exports.addContactSchema = exports.verifyEmailChangeSchema = exports.verifyPhoneChangeSchema = exports.requestPhoneChangeSchema = exports.changeEmailSchema = exports.updateContactSchema = exports.updateProfileSchema = exports.validateContactValue = exports.detectContactType = exports.strongPasswordRegex = exports.emailRegex = exports.phoneRegex = void 0;
|
|
4
4
|
// src/modules/account/validations/account.schema.ts
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
+
// ==================== REGEX PATTERNS ====================
|
|
6
7
|
exports.phoneRegex = /^\+250(78|79|73|72)[0-9]{7}$/;
|
|
8
|
+
exports.emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
7
9
|
const plateRegex = /^[A-Z0-9]{3,10}$/i;
|
|
8
10
|
exports.strongPasswordRegex = /^(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&#^()_\-+=])[A-Za-z\d@$!%*?&#^()_\-+=]{8,}$/;
|
|
11
|
+
// ==================== CONTACT VALIDATION HELPERS ====================
|
|
12
|
+
const detectContactType = (value) => {
|
|
13
|
+
if (!value)
|
|
14
|
+
return "UNKNOWN";
|
|
15
|
+
// Check if it's an email
|
|
16
|
+
if (exports.emailRegex.test(value)) {
|
|
17
|
+
return "EMAIL";
|
|
18
|
+
}
|
|
19
|
+
// Check if it's a phone number
|
|
20
|
+
if (exports.phoneRegex.test(value)) {
|
|
21
|
+
return "PHONE";
|
|
22
|
+
}
|
|
23
|
+
return "UNKNOWN";
|
|
24
|
+
};
|
|
25
|
+
exports.detectContactType = detectContactType;
|
|
26
|
+
const validateContactValue = (value) => {
|
|
27
|
+
return exports.emailRegex.test(value) || exports.phoneRegex.test(value);
|
|
28
|
+
};
|
|
29
|
+
exports.validateContactValue = validateContactValue;
|
|
30
|
+
// ==================== SCHEMAS ====================
|
|
9
31
|
exports.updateProfileSchema = zod_1.z.object({
|
|
10
32
|
body: zod_1.z.object({
|
|
11
33
|
firstName: zod_1.z.string().min(2).max(50).optional(),
|
|
@@ -16,18 +38,91 @@ exports.updateProfileSchema = zod_1.z.object({
|
|
|
16
38
|
.optional(),
|
|
17
39
|
}),
|
|
18
40
|
});
|
|
41
|
+
// Schema for updating contact (email or phone)
|
|
42
|
+
exports.updateContactSchema = zod_1.z.object({
|
|
43
|
+
body: zod_1.z.object({
|
|
44
|
+
contactValue: zod_1.z
|
|
45
|
+
.string()
|
|
46
|
+
.min(1, "Contact value is required")
|
|
47
|
+
.refine((val) => (0, exports.validateContactValue)(val), {
|
|
48
|
+
message: "Invalid contact value. Must be a valid email or Rwandan phone number (+250...)",
|
|
49
|
+
}),
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
// Schema for changing email specifically
|
|
53
|
+
exports.changeEmailSchema = zod_1.z.object({
|
|
54
|
+
body: zod_1.z.object({
|
|
55
|
+
newEmail: zod_1.z
|
|
56
|
+
.string()
|
|
57
|
+
.email("Invalid email format")
|
|
58
|
+
.min(1, "Email is required"),
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
// Schema for changing phone number specifically
|
|
19
62
|
exports.requestPhoneChangeSchema = zod_1.z.object({
|
|
20
63
|
body: zod_1.z.object({
|
|
21
|
-
newPhoneNumber: zod_1.z
|
|
64
|
+
newPhoneNumber: zod_1.z
|
|
65
|
+
.string()
|
|
66
|
+
.regex(exports.phoneRegex, "Invalid phone number format. Must be a valid Rwandan phone number (+250...)"),
|
|
22
67
|
}),
|
|
23
68
|
});
|
|
24
|
-
//
|
|
69
|
+
// Schema for verifying phone change with OTP
|
|
25
70
|
exports.verifyPhoneChangeSchema = zod_1.z.object({
|
|
26
71
|
body: zod_1.z.object({
|
|
27
72
|
oldPhoneOtp: zod_1.z.string().length(6, "Old phone OTP must be 6 digits"),
|
|
28
73
|
newPhoneOtp: zod_1.z.string().length(6, "New phone OTP must be 6 digits"),
|
|
29
74
|
}),
|
|
30
75
|
});
|
|
76
|
+
// Schema for verifying email change with OTP
|
|
77
|
+
exports.verifyEmailChangeSchema = zod_1.z.object({
|
|
78
|
+
body: zod_1.z.object({
|
|
79
|
+
emailOtp: zod_1.z.string().length(6, "Email OTP must be 6 digits"),
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
82
|
+
// Schema for adding new contact
|
|
83
|
+
exports.addContactSchema = zod_1.z.object({
|
|
84
|
+
body: zod_1.z.object({
|
|
85
|
+
contactValue: zod_1.z
|
|
86
|
+
.string()
|
|
87
|
+
.min(1, "Contact value is required")
|
|
88
|
+
.refine((val) => (0, exports.validateContactValue)(val), {
|
|
89
|
+
message: "Invalid contact value. Must be a valid email or Rwandan phone number (+250...)",
|
|
90
|
+
}),
|
|
91
|
+
type: zod_1.z
|
|
92
|
+
.enum(["EMAIL", "PHONE", "WHATSAPP"])
|
|
93
|
+
.optional()
|
|
94
|
+
.refine((val) => {
|
|
95
|
+
if (!val)
|
|
96
|
+
return true;
|
|
97
|
+
return true;
|
|
98
|
+
}, { message: "Invalid contact type" }),
|
|
99
|
+
}),
|
|
100
|
+
});
|
|
101
|
+
// Schema for deleting a contact
|
|
102
|
+
exports.deleteContactSchema = zod_1.z.object({
|
|
103
|
+
params: zod_1.z.object({
|
|
104
|
+
contactId: zod_1.z.string().uuid("Invalid contact ID"),
|
|
105
|
+
}),
|
|
106
|
+
});
|
|
107
|
+
// Schema for making a contact primary
|
|
108
|
+
exports.setPrimaryContactSchema = zod_1.z.object({
|
|
109
|
+
params: zod_1.z.object({
|
|
110
|
+
contactId: zod_1.z.string().uuid("Invalid contact ID"),
|
|
111
|
+
}),
|
|
112
|
+
});
|
|
113
|
+
// Schema for verifying contact (sending OTP)
|
|
114
|
+
exports.verifyContactSchema = zod_1.z.object({
|
|
115
|
+
params: zod_1.z.object({
|
|
116
|
+
contactId: zod_1.z.string().uuid("Invalid contact ID"),
|
|
117
|
+
}),
|
|
118
|
+
});
|
|
119
|
+
// Schema for confirming contact verification with OTP
|
|
120
|
+
exports.confirmVerificationSchema = zod_1.z.object({
|
|
121
|
+
body: zod_1.z.object({
|
|
122
|
+
otp: zod_1.z.string().length(6, "OTP must be 6 digits"),
|
|
123
|
+
}),
|
|
124
|
+
});
|
|
125
|
+
// Schema for deleting account
|
|
31
126
|
exports.deleteAccountSchema = zod_1.z.object({
|
|
32
127
|
body: zod_1.z.object({
|
|
33
128
|
confirmation: zod_1.z.literal("DELETE", {
|
|
@@ -36,6 +131,7 @@ exports.deleteAccountSchema = zod_1.z.object({
|
|
|
36
131
|
reason: zod_1.z.string().max(500).optional(),
|
|
37
132
|
}),
|
|
38
133
|
});
|
|
134
|
+
// Schema for changing password
|
|
39
135
|
exports.changePasswordSchema = zod_1.z.object({
|
|
40
136
|
body: zod_1.z.object({
|
|
41
137
|
oldPassword: zod_1.z.string().min(1, "Old password is required"),
|
|
@@ -44,3 +140,40 @@ exports.changePasswordSchema = zod_1.z.object({
|
|
|
44
140
|
.regex(exports.strongPasswordRegex, "Password must be at least 8 characters, include 1 uppercase letter, 1 number and 1 symbol"),
|
|
45
141
|
}),
|
|
46
142
|
});
|
|
143
|
+
// Schema for login with contact
|
|
144
|
+
exports.loginSchema = zod_1.z.object({
|
|
145
|
+
body: zod_1.z.object({
|
|
146
|
+
contactValue: zod_1.z
|
|
147
|
+
.string()
|
|
148
|
+
.min(1, "Email or phone number is required")
|
|
149
|
+
.refine((val) => (0, exports.validateContactValue)(val), {
|
|
150
|
+
message: "Invalid contact value. Must be a valid email or Rwandan phone number (+250...)",
|
|
151
|
+
}),
|
|
152
|
+
password: zod_1.z.string().min(1, "Password is required"),
|
|
153
|
+
}),
|
|
154
|
+
});
|
|
155
|
+
// Schema for forgot password
|
|
156
|
+
exports.forgotPasswordSchema = zod_1.z.object({
|
|
157
|
+
body: zod_1.z.object({
|
|
158
|
+
contactValue: zod_1.z
|
|
159
|
+
.string()
|
|
160
|
+
.min(1, "Email or phone number is required")
|
|
161
|
+
.refine((val) => (0, exports.validateContactValue)(val), {
|
|
162
|
+
message: "Invalid contact value. Must be a valid email or Rwandan phone number (+250...)",
|
|
163
|
+
}),
|
|
164
|
+
}),
|
|
165
|
+
});
|
|
166
|
+
// Schema for reset password
|
|
167
|
+
exports.resetPasswordSchema = zod_1.z
|
|
168
|
+
.object({
|
|
169
|
+
body: zod_1.z.object({
|
|
170
|
+
newPassword: zod_1.z
|
|
171
|
+
.string()
|
|
172
|
+
.regex(exports.strongPasswordRegex, "Password must be at least 8 characters, include 1 uppercase letter, 1 number and 1 symbol"),
|
|
173
|
+
confirmPassword: zod_1.z.string(),
|
|
174
|
+
}),
|
|
175
|
+
})
|
|
176
|
+
.refine((data) => data.body.newPassword === data.body.confirmPassword, {
|
|
177
|
+
message: "Passwords do not match",
|
|
178
|
+
path: ["confirmPassword"],
|
|
179
|
+
});
|