vr-commons 1.0.22 → 1.0.23
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/index.d.ts +4 -0
- package/dist/index.js +23 -0
- package/dist/middlewares/auth.middlewares.d.ts +3 -0
- package/dist/middlewares/auth.middlewares.js +57 -0
- package/dist/middlewares/index.d.ts +1 -0
- package/dist/middlewares/index.js +5 -0
- package/dist/utils/account.utils.d.ts +9 -0
- package/dist/utils/account.utils.js +46 -0
- package/dist/utils/authTokens.utils.d.ts +11 -0
- package/dist/utils/authTokens.utils.js +32 -0
- package/dist/utils/eventLog.utils.d.ts +13 -0
- package/dist/utils/eventLog.utils.js +22 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.js +29 -0
- package/dist/utils/profiles.utils.d.ts +52 -0
- package/dist/utils/profiles.utils.js +198 -0
- package/dist/utils/response.utils.d.ts +3 -0
- package/dist/utils/response.utils.js +22 -0
- package/dist/validations/auth.validations.d.ts +32 -0
- package/dist/validations/auth.validations.js +17 -0
- package/dist/validations/index.d.ts +2 -0
- package/dist/validations/index.js +7 -0
- package/dist/validations/profiles.validations.d.ts +287 -0
- package/dist/validations/profiles.validations.js +141 -0
- package/dist/validations/validate.validations.d.ts +13 -0
- package/dist/validations/validate.validations.js +38 -0
- package/package.json +1 -1
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.validate = void 0;
|
|
18
|
+
// Core Functionality
|
|
19
|
+
__exportStar(require("./middlewares"), exports);
|
|
20
|
+
__exportStar(require("./validations"), exports);
|
|
21
|
+
__exportStar(require("./utils"), exports);
|
|
22
|
+
var validate_validations_1 = require("./validations/validate.validations");
|
|
23
|
+
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validate_validations_1.validate; } });
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from "express";
|
|
2
|
+
import { UserRole } from "vr-models";
|
|
3
|
+
export declare const checkUserAuthentication: (allowedRoles: UserRole[]) => (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/middlewares/auth/checkUserAuthentication.middleware.ts
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.checkUserAuthentication = void 0;
|
|
8
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
9
|
+
const vr_models_1 = require("vr-models");
|
|
10
|
+
const checkUserAuthentication = (allowedRoles) => async (req, res, next) => {
|
|
11
|
+
try {
|
|
12
|
+
const authHeader = req.headers.authorization;
|
|
13
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
14
|
+
return res.status(401).json({ message: "Missing or invalid token" });
|
|
15
|
+
}
|
|
16
|
+
const token = authHeader.split(" ")[1];
|
|
17
|
+
let payload;
|
|
18
|
+
try {
|
|
19
|
+
payload = jsonwebtoken_1.default.verify(token, process.env.JWT_SECRET);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return res.status(401).json({ message: "Token expired or invalid" });
|
|
23
|
+
}
|
|
24
|
+
const user = await vr_models_1.User.findOne({
|
|
25
|
+
where: { id: payload.userId },
|
|
26
|
+
include: [
|
|
27
|
+
{
|
|
28
|
+
model: vr_models_1.SecurityClearance,
|
|
29
|
+
as: "securityClearance"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
});
|
|
33
|
+
if (!user || !user.securityClearance) {
|
|
34
|
+
return res.status(401).json({ message: "User not found" });
|
|
35
|
+
}
|
|
36
|
+
// 🔐 Token versioning (logout all devices)
|
|
37
|
+
if (user.tokenVersion !== payload.tokenVersion) {
|
|
38
|
+
return res.status(401).json({ message: "Session expired" });
|
|
39
|
+
}
|
|
40
|
+
// 🧱 Role enforcement
|
|
41
|
+
if (!allowedRoles.includes(user.securityClearance.role)) {
|
|
42
|
+
return res.status(403).json({ message: "Access denied" });
|
|
43
|
+
}
|
|
44
|
+
// ✅ Extend req
|
|
45
|
+
req.userId = user.id;
|
|
46
|
+
req.firstName = user.firstName;
|
|
47
|
+
req.lastName = user.lastName;
|
|
48
|
+
req.scRole = user.securityClearance.role;
|
|
49
|
+
req.scLevel = user.securityClearance.level;
|
|
50
|
+
req.tokenVersion = user.tokenVersion;
|
|
51
|
+
next();
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
next(error);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
exports.checkUserAuthentication = checkUserAuthentication;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { checkUserAuthentication } from "./auth.middlewares";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkUserAuthentication = void 0;
|
|
4
|
+
var auth_middlewares_1 = require("./auth.middlewares");
|
|
5
|
+
Object.defineProperty(exports, "checkUserAuthentication", { enumerable: true, get: function () { return auth_middlewares_1.checkUserAuthentication; } });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Transaction } from "sequelize";
|
|
2
|
+
export declare const checkAccountDependencies: (userId: string, transaction?: any) => Promise<{
|
|
3
|
+
hasDependencies: boolean;
|
|
4
|
+
activeDevicePlans: number;
|
|
5
|
+
pendingPayments: number;
|
|
6
|
+
activeSubscriptions: number;
|
|
7
|
+
messages: string[];
|
|
8
|
+
}>;
|
|
9
|
+
export declare const hasActiveDependencies: (userId: string, transaction?: Transaction) => Promise<boolean>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasActiveDependencies = exports.checkAccountDependencies = void 0;
|
|
4
|
+
const vr_models_1 = require("vr-models");
|
|
5
|
+
// Import other models as needed
|
|
6
|
+
const checkAccountDependencies = async (userId, transaction) => {
|
|
7
|
+
const messages = [];
|
|
8
|
+
// 1. Check for active device payment plans
|
|
9
|
+
const activeDevicePlans = await vr_models_1.DevicePaymentPlan.count({
|
|
10
|
+
where: {
|
|
11
|
+
userId,
|
|
12
|
+
status: "ACTIVE", // Adjust based on your status enum
|
|
13
|
+
},
|
|
14
|
+
transaction,
|
|
15
|
+
});
|
|
16
|
+
if (activeDevicePlans > 0) {
|
|
17
|
+
messages.push(`You have ${activeDevicePlans} active device payment plan(s)`);
|
|
18
|
+
}
|
|
19
|
+
// 2. Check for pending payments
|
|
20
|
+
const pendingPayments = await vr_models_1.Transaction.count({
|
|
21
|
+
where: {
|
|
22
|
+
userId,
|
|
23
|
+
status: "PENDING", // Adjust based on your status enum
|
|
24
|
+
},
|
|
25
|
+
transaction,
|
|
26
|
+
});
|
|
27
|
+
if (pendingPayments > 0) {
|
|
28
|
+
messages.push(`You have ${pendingPayments} pending payment(s)`);
|
|
29
|
+
}
|
|
30
|
+
// 3. Add more checks as needed (subscriptions, etc.)
|
|
31
|
+
const hasDependencies = activeDevicePlans > 0 || pendingPayments > 0;
|
|
32
|
+
return {
|
|
33
|
+
hasDependencies,
|
|
34
|
+
activeDevicePlans,
|
|
35
|
+
pendingPayments,
|
|
36
|
+
activeSubscriptions: 0, // Implement if needed
|
|
37
|
+
messages,
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
exports.checkAccountDependencies = checkAccountDependencies;
|
|
41
|
+
// Then update the hasActiveDependencies function in passengerUser.utils.ts:
|
|
42
|
+
const hasActiveDependencies = async (userId, transaction) => {
|
|
43
|
+
const result = await (0, exports.checkAccountDependencies)(userId, transaction);
|
|
44
|
+
return result.hasDependencies;
|
|
45
|
+
};
|
|
46
|
+
exports.hasActiveDependencies = hasActiveDependencies;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { UserRole } from "vr-models";
|
|
2
|
+
export interface JWTPayload {
|
|
3
|
+
userId: string;
|
|
4
|
+
role: UserRole;
|
|
5
|
+
level: number;
|
|
6
|
+
tokenVersion: number;
|
|
7
|
+
}
|
|
8
|
+
export declare const generateAdminToken: (userId: string, role: UserRole, level: number, tokenVersion: number, expiresIn: number) => string;
|
|
9
|
+
export declare const generatePassengerToken: (userId: string, role: UserRole, level: number, tokenVersion: number, expiresIn: number) => string;
|
|
10
|
+
export declare const generateRiderToken: (userId: string, role: UserRole, level: number, tokenVersion: number, expiresIn: number) => string;
|
|
11
|
+
export declare const verifyToken: (token: string) => Promise<JWTPayload>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.verifyToken = exports.generateRiderToken = exports.generatePassengerToken = exports.generateAdminToken = void 0;
|
|
7
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
8
|
+
const generateAdminToken = (userId, role, level, tokenVersion, expiresIn) => {
|
|
9
|
+
const payload = { userId, role, level, tokenVersion };
|
|
10
|
+
return jsonwebtoken_1.default.sign(payload, process.env.JWT_SECRET, {
|
|
11
|
+
expiresIn: expiresIn || Number(process.env.ADMIN_TOKEN_LIFE_SPAN)
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
exports.generateAdminToken = generateAdminToken;
|
|
15
|
+
const generatePassengerToken = (userId, role, level, tokenVersion, expiresIn) => {
|
|
16
|
+
const payload = { userId, role, level, tokenVersion };
|
|
17
|
+
return jsonwebtoken_1.default.sign(payload, process.env.JWT_SECRET, {
|
|
18
|
+
expiresIn: expiresIn || Number(process.env.PASSENGER_TOKEN_LIFE_SPAN)
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
exports.generatePassengerToken = generatePassengerToken;
|
|
22
|
+
const generateRiderToken = (userId, role, level, tokenVersion, expiresIn) => {
|
|
23
|
+
const payload = { userId, role, level, tokenVersion };
|
|
24
|
+
return jsonwebtoken_1.default.sign(payload, process.env.JWT_SECRET, {
|
|
25
|
+
expiresIn: expiresIn || Number(process.env.RIDER_TOKEN_LIFE_SPAN)
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
exports.generateRiderToken = generateRiderToken;
|
|
29
|
+
const verifyToken = async (token) => {
|
|
30
|
+
return jsonwebtoken_1.default.verify(token, process.env.JWT_SECRET);
|
|
31
|
+
};
|
|
32
|
+
exports.verifyToken = verifyToken;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EventAction, EventActorType } from "vr-models";
|
|
2
|
+
interface LogEventInput {
|
|
3
|
+
actorId?: string | null;
|
|
4
|
+
actorType?: EventActorType;
|
|
5
|
+
action: EventAction;
|
|
6
|
+
entity: string;
|
|
7
|
+
entityId?: string | null;
|
|
8
|
+
metadata?: Record<string, any>;
|
|
9
|
+
ipAddress?: string | null;
|
|
10
|
+
userAgent?: string | null;
|
|
11
|
+
}
|
|
12
|
+
export declare const logEvent: ({ actorId, actorType, action, entity, entityId, metadata, ipAddress, userAgent }: LogEventInput) => Promise<void>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logEvent = void 0;
|
|
4
|
+
const vr_models_1 = require("vr-models");
|
|
5
|
+
const logEvent = async ({ actorId = null, actorType = "SYSTEM", action, entity, entityId = null, metadata = {}, ipAddress = null, userAgent = null }) => {
|
|
6
|
+
try {
|
|
7
|
+
await vr_models_1.EventLog.create({
|
|
8
|
+
actorId,
|
|
9
|
+
actorType,
|
|
10
|
+
action,
|
|
11
|
+
entity,
|
|
12
|
+
entityId,
|
|
13
|
+
metadata,
|
|
14
|
+
ipAddress,
|
|
15
|
+
userAgent
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
console.log("Error Logging event ::::::", err);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
exports.logEvent = logEvent;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { checkAccountDependencies, hasActiveDependencies, } from "./account.utils";
|
|
2
|
+
export { generateAdminToken, generatePassengerToken, generateRiderToken, verifyToken, } from "./authTokens.utils";
|
|
3
|
+
export { logEvent } from "./eventLog.utils";
|
|
4
|
+
export { sendSuccessResponse, sendErrorResponse } from "./response.utils";
|
|
5
|
+
export { formatUserForAdmin, formatAdminProfile, isUserAdmin, isUserAdminOrSuperAdmin, isUserSuperAdmin, getAdminWithClearance, getUserById, findSecurityClearanceByRole, hashPassword, validateUniqueFields, canAdminModifyUser, generateSearchConditions, } from "./profiles.utils";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSearchConditions = exports.canAdminModifyUser = exports.validateUniqueFields = exports.hashPassword = exports.findSecurityClearanceByRole = exports.getUserById = exports.getAdminWithClearance = exports.isUserSuperAdmin = exports.isUserAdminOrSuperAdmin = exports.isUserAdmin = exports.formatAdminProfile = exports.formatUserForAdmin = exports.sendErrorResponse = exports.sendSuccessResponse = exports.logEvent = exports.verifyToken = exports.generateRiderToken = exports.generatePassengerToken = exports.generateAdminToken = exports.hasActiveDependencies = exports.checkAccountDependencies = void 0;
|
|
4
|
+
var account_utils_1 = require("./account.utils");
|
|
5
|
+
Object.defineProperty(exports, "checkAccountDependencies", { enumerable: true, get: function () { return account_utils_1.checkAccountDependencies; } });
|
|
6
|
+
Object.defineProperty(exports, "hasActiveDependencies", { enumerable: true, get: function () { return account_utils_1.hasActiveDependencies; } });
|
|
7
|
+
var authTokens_utils_1 = require("./authTokens.utils");
|
|
8
|
+
Object.defineProperty(exports, "generateAdminToken", { enumerable: true, get: function () { return authTokens_utils_1.generateAdminToken; } });
|
|
9
|
+
Object.defineProperty(exports, "generatePassengerToken", { enumerable: true, get: function () { return authTokens_utils_1.generatePassengerToken; } });
|
|
10
|
+
Object.defineProperty(exports, "generateRiderToken", { enumerable: true, get: function () { return authTokens_utils_1.generateRiderToken; } });
|
|
11
|
+
Object.defineProperty(exports, "verifyToken", { enumerable: true, get: function () { return authTokens_utils_1.verifyToken; } });
|
|
12
|
+
var eventLog_utils_1 = require("./eventLog.utils");
|
|
13
|
+
Object.defineProperty(exports, "logEvent", { enumerable: true, get: function () { return eventLog_utils_1.logEvent; } });
|
|
14
|
+
var response_utils_1 = require("./response.utils");
|
|
15
|
+
Object.defineProperty(exports, "sendSuccessResponse", { enumerable: true, get: function () { return response_utils_1.sendSuccessResponse; } });
|
|
16
|
+
Object.defineProperty(exports, "sendErrorResponse", { enumerable: true, get: function () { return response_utils_1.sendErrorResponse; } });
|
|
17
|
+
var profiles_utils_1 = require("./profiles.utils");
|
|
18
|
+
Object.defineProperty(exports, "formatUserForAdmin", { enumerable: true, get: function () { return profiles_utils_1.formatUserForAdmin; } });
|
|
19
|
+
Object.defineProperty(exports, "formatAdminProfile", { enumerable: true, get: function () { return profiles_utils_1.formatAdminProfile; } });
|
|
20
|
+
Object.defineProperty(exports, "isUserAdmin", { enumerable: true, get: function () { return profiles_utils_1.isUserAdmin; } });
|
|
21
|
+
Object.defineProperty(exports, "isUserAdminOrSuperAdmin", { enumerable: true, get: function () { return profiles_utils_1.isUserAdminOrSuperAdmin; } });
|
|
22
|
+
Object.defineProperty(exports, "isUserSuperAdmin", { enumerable: true, get: function () { return profiles_utils_1.isUserSuperAdmin; } });
|
|
23
|
+
Object.defineProperty(exports, "getAdminWithClearance", { enumerable: true, get: function () { return profiles_utils_1.getAdminWithClearance; } });
|
|
24
|
+
Object.defineProperty(exports, "getUserById", { enumerable: true, get: function () { return profiles_utils_1.getUserById; } });
|
|
25
|
+
Object.defineProperty(exports, "findSecurityClearanceByRole", { enumerable: true, get: function () { return profiles_utils_1.findSecurityClearanceByRole; } });
|
|
26
|
+
Object.defineProperty(exports, "hashPassword", { enumerable: true, get: function () { return profiles_utils_1.hashPassword; } });
|
|
27
|
+
Object.defineProperty(exports, "validateUniqueFields", { enumerable: true, get: function () { return profiles_utils_1.validateUniqueFields; } });
|
|
28
|
+
Object.defineProperty(exports, "canAdminModifyUser", { enumerable: true, get: function () { return profiles_utils_1.canAdminModifyUser; } });
|
|
29
|
+
Object.defineProperty(exports, "generateSearchConditions", { enumerable: true, get: function () { return profiles_utils_1.generateSearchConditions; } });
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { User, SecurityClearance, UserRole } from "vr-models";
|
|
2
|
+
export interface AdminUserDetailResponse {
|
|
3
|
+
id: string;
|
|
4
|
+
firstName: string;
|
|
5
|
+
lastName: string;
|
|
6
|
+
phoneNumber: string;
|
|
7
|
+
email: string | null;
|
|
8
|
+
nationalId: string;
|
|
9
|
+
jacketId: string;
|
|
10
|
+
plateNumber: string | null;
|
|
11
|
+
isActive: boolean;
|
|
12
|
+
isSuspended: boolean;
|
|
13
|
+
isDeactivated: boolean;
|
|
14
|
+
deactivatedAt: Date | null;
|
|
15
|
+
lastLoginAt: Date | null;
|
|
16
|
+
createdAt: Date;
|
|
17
|
+
role?: string;
|
|
18
|
+
level?: number;
|
|
19
|
+
permissions: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface AdminProfileResponse {
|
|
22
|
+
id: string;
|
|
23
|
+
firstName: string;
|
|
24
|
+
lastName: string;
|
|
25
|
+
phoneNumber: string;
|
|
26
|
+
email: string | null;
|
|
27
|
+
nationalId: string;
|
|
28
|
+
isActive: boolean;
|
|
29
|
+
lastLoginAt: Date | null;
|
|
30
|
+
createdAt: Date;
|
|
31
|
+
role?: string;
|
|
32
|
+
level?: number;
|
|
33
|
+
permissions: string[];
|
|
34
|
+
}
|
|
35
|
+
export declare const formatUserForAdmin: (user: User) => AdminUserDetailResponse;
|
|
36
|
+
export declare const formatAdminProfile: (user: User) => AdminProfileResponse;
|
|
37
|
+
export declare const isUserAdmin: (user: User) => boolean;
|
|
38
|
+
export declare const isUserSuperAdmin: (user: User) => boolean;
|
|
39
|
+
export declare const isUserAdminOrSuperAdmin: (user: User) => boolean;
|
|
40
|
+
export declare const getAdminWithClearance: (userId: string) => Promise<User | null>;
|
|
41
|
+
export declare const getUserById: (userId: string) => Promise<User | null>;
|
|
42
|
+
export declare const findSecurityClearanceByRole: (role: UserRole) => Promise<SecurityClearance | null>;
|
|
43
|
+
export declare const hashPassword: (password: string) => Promise<string>;
|
|
44
|
+
export declare const validateUniqueFields: (phoneNumber: string, nationalId: string, email?: string | null) => Promise<{
|
|
45
|
+
field: string;
|
|
46
|
+
message: string;
|
|
47
|
+
}[]>;
|
|
48
|
+
export declare const canAdminModifyUser: (admin: User, targetUser: User) => {
|
|
49
|
+
canModify: boolean;
|
|
50
|
+
reason?: string;
|
|
51
|
+
};
|
|
52
|
+
export declare const generateSearchConditions: (role?: UserRole, isActive?: boolean, search?: string) => any;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateSearchConditions = exports.canAdminModifyUser = exports.validateUniqueFields = exports.hashPassword = exports.findSecurityClearanceByRole = exports.getUserById = exports.getAdminWithClearance = exports.isUserAdminOrSuperAdmin = exports.isUserSuperAdmin = exports.isUserAdmin = exports.formatAdminProfile = exports.formatUserForAdmin = void 0;
|
|
7
|
+
const vr_models_1 = require("vr-models");
|
|
8
|
+
const bcryptjs_1 = __importDefault(require("bcryptjs"));
|
|
9
|
+
const sequelize_1 = require("sequelize");
|
|
10
|
+
const formatUserForAdmin = (user) => {
|
|
11
|
+
return {
|
|
12
|
+
id: user.id,
|
|
13
|
+
firstName: user.firstName,
|
|
14
|
+
lastName: user.lastName,
|
|
15
|
+
phoneNumber: user.phoneNumber,
|
|
16
|
+
email: user.email,
|
|
17
|
+
nationalId: user.nationalId,
|
|
18
|
+
jacketId: user.jacketId,
|
|
19
|
+
plateNumber: user.plateNumber,
|
|
20
|
+
isActive: user.isActive,
|
|
21
|
+
isSuspended: user.isSuspended,
|
|
22
|
+
isDeactivated: user.isDeactivated,
|
|
23
|
+
deactivatedAt: user.deactivatedAt,
|
|
24
|
+
lastLoginAt: user.lastLoginAt,
|
|
25
|
+
createdAt: user.createdAt,
|
|
26
|
+
role: user.securityClearance?.role,
|
|
27
|
+
level: user.securityClearance?.level,
|
|
28
|
+
permissions: user.securityClearance?.permissions || [],
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
exports.formatUserForAdmin = formatUserForAdmin;
|
|
32
|
+
// Format admin profile
|
|
33
|
+
const formatAdminProfile = (user) => {
|
|
34
|
+
return {
|
|
35
|
+
id: user.id,
|
|
36
|
+
firstName: user.firstName,
|
|
37
|
+
lastName: user.lastName,
|
|
38
|
+
phoneNumber: user.phoneNumber,
|
|
39
|
+
email: user.email,
|
|
40
|
+
nationalId: user.nationalId,
|
|
41
|
+
isActive: user.isActive,
|
|
42
|
+
lastLoginAt: user.lastLoginAt,
|
|
43
|
+
createdAt: user.createdAt,
|
|
44
|
+
role: user.securityClearance?.role,
|
|
45
|
+
level: user.securityClearance?.level,
|
|
46
|
+
permissions: user.securityClearance?.permissions || [],
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
exports.formatAdminProfile = formatAdminProfile;
|
|
50
|
+
// Check if user is an admin
|
|
51
|
+
const isUserAdmin = (user) => {
|
|
52
|
+
return user.securityClearance?.role === "ADMIN";
|
|
53
|
+
};
|
|
54
|
+
exports.isUserAdmin = isUserAdmin;
|
|
55
|
+
// Check if user is a super admin
|
|
56
|
+
const isUserSuperAdmin = (user) => {
|
|
57
|
+
return user.securityClearance?.role === "SUPER_ADMIN";
|
|
58
|
+
};
|
|
59
|
+
exports.isUserSuperAdmin = isUserSuperAdmin;
|
|
60
|
+
// Check if user is an admin or super admin
|
|
61
|
+
const isUserAdminOrSuperAdmin = (user) => {
|
|
62
|
+
const role = user.securityClearance?.role;
|
|
63
|
+
return role === "ADMIN" || role === "SUPER_ADMIN";
|
|
64
|
+
};
|
|
65
|
+
exports.isUserAdminOrSuperAdmin = isUserAdminOrSuperAdmin;
|
|
66
|
+
// Get admin with security clearance
|
|
67
|
+
const getAdminWithClearance = async (userId) => {
|
|
68
|
+
return await vr_models_1.User.findOne({
|
|
69
|
+
where: { id: userId },
|
|
70
|
+
include: [
|
|
71
|
+
{
|
|
72
|
+
model: vr_models_1.SecurityClearance,
|
|
73
|
+
as: "securityClearance",
|
|
74
|
+
attributes: ["role", "level", "permissions"],
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
attributes: {
|
|
78
|
+
exclude: [
|
|
79
|
+
"password",
|
|
80
|
+
"otp",
|
|
81
|
+
"otpExpiresAt",
|
|
82
|
+
"tokenVersion",
|
|
83
|
+
"forgotPassword",
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
exports.getAdminWithClearance = getAdminWithClearance;
|
|
89
|
+
// Get user by ID with security clearance
|
|
90
|
+
const getUserById = async (userId) => {
|
|
91
|
+
return await vr_models_1.User.findOne({
|
|
92
|
+
where: { id: userId },
|
|
93
|
+
include: [
|
|
94
|
+
{
|
|
95
|
+
model: vr_models_1.SecurityClearance,
|
|
96
|
+
as: "securityClearance",
|
|
97
|
+
attributes: ["role", "level", "permissions"],
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
attributes: {
|
|
101
|
+
exclude: [
|
|
102
|
+
"password",
|
|
103
|
+
"otp",
|
|
104
|
+
"otpExpiresAt",
|
|
105
|
+
"tokenVersion",
|
|
106
|
+
"forgotPassword",
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
exports.getUserById = getUserById;
|
|
112
|
+
// Find security clearance by role
|
|
113
|
+
const findSecurityClearanceByRole = async (role) => {
|
|
114
|
+
return await vr_models_1.SecurityClearance.findOne({
|
|
115
|
+
where: { role, isDefault: true },
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
exports.findSecurityClearanceByRole = findSecurityClearanceByRole;
|
|
119
|
+
// Hash password
|
|
120
|
+
const hashPassword = async (password) => {
|
|
121
|
+
return await bcryptjs_1.default.hash(password, 10);
|
|
122
|
+
};
|
|
123
|
+
exports.hashPassword = hashPassword;
|
|
124
|
+
// Validate unique fields
|
|
125
|
+
const validateUniqueFields = async (phoneNumber, nationalId, email) => {
|
|
126
|
+
const errors = [];
|
|
127
|
+
// Check phone number
|
|
128
|
+
const existingPhone = await vr_models_1.User.findOne({ where: { phoneNumber } });
|
|
129
|
+
if (existingPhone) {
|
|
130
|
+
errors.push({
|
|
131
|
+
field: "phoneNumber",
|
|
132
|
+
message: "Phone number already registered",
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
// Check national ID
|
|
136
|
+
const existingNationalId = await vr_models_1.User.findOne({ where: { nationalId } });
|
|
137
|
+
if (existingNationalId) {
|
|
138
|
+
errors.push({
|
|
139
|
+
field: "nationalId",
|
|
140
|
+
message: "National ID already registered",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// Check email if provided
|
|
144
|
+
if (email) {
|
|
145
|
+
const existingEmail = await vr_models_1.User.findOne({ where: { email } });
|
|
146
|
+
if (existingEmail) {
|
|
147
|
+
errors.push({ field: "email", message: "Email already registered" });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return errors;
|
|
151
|
+
};
|
|
152
|
+
exports.validateUniqueFields = validateUniqueFields;
|
|
153
|
+
// Check if admin can modify target user
|
|
154
|
+
const canAdminModifyUser = (admin, targetUser) => {
|
|
155
|
+
const adminRole = admin.securityClearance?.role;
|
|
156
|
+
const targetRole = targetUser.securityClearance?.role;
|
|
157
|
+
// Admins cannot modify super admins
|
|
158
|
+
if (targetRole === "SUPER_ADMIN") {
|
|
159
|
+
return { canModify: false, reason: "Cannot modify super admin accounts" };
|
|
160
|
+
}
|
|
161
|
+
// Admins cannot modify other admins (only super admins can)
|
|
162
|
+
if (targetRole === "ADMIN" && adminRole !== "SUPER_ADMIN") {
|
|
163
|
+
return {
|
|
164
|
+
canModify: false,
|
|
165
|
+
reason: "Admins cannot modify other admin accounts",
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
// Cannot modify self through this route
|
|
169
|
+
if (admin.id === targetUser.id) {
|
|
170
|
+
return {
|
|
171
|
+
canModify: false,
|
|
172
|
+
reason: "Use profile update route for self-updates",
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return { canModify: true };
|
|
176
|
+
};
|
|
177
|
+
exports.canAdminModifyUser = canAdminModifyUser;
|
|
178
|
+
// Generate search conditions
|
|
179
|
+
const generateSearchConditions = (role, isActive, search) => {
|
|
180
|
+
const where = {};
|
|
181
|
+
if (role) {
|
|
182
|
+
where["$securityClearance.role$"] = role;
|
|
183
|
+
}
|
|
184
|
+
if (isActive !== undefined) {
|
|
185
|
+
where.isActive = isActive;
|
|
186
|
+
}
|
|
187
|
+
if (search) {
|
|
188
|
+
where[sequelize_1.Op.or] = [
|
|
189
|
+
{ firstName: { [sequelize_1.Op.iLike]: `%${search}%` } },
|
|
190
|
+
{ lastName: { [sequelize_1.Op.iLike]: `%${search}%` } },
|
|
191
|
+
{ phoneNumber: { [sequelize_1.Op.iLike]: `%${search}%` } },
|
|
192
|
+
{ email: { [sequelize_1.Op.iLike]: `%${search}%` } },
|
|
193
|
+
{ nationalId: { [sequelize_1.Op.iLike]: `%${search}%` } },
|
|
194
|
+
];
|
|
195
|
+
}
|
|
196
|
+
return where;
|
|
197
|
+
};
|
|
198
|
+
exports.generateSearchConditions = generateSearchConditions;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendErrorResponse = exports.sendSuccessResponse = void 0;
|
|
4
|
+
// Success response
|
|
5
|
+
const sendSuccessResponse = (res, message, data = null, statusCode = 200) => {
|
|
6
|
+
res.status(statusCode).json({
|
|
7
|
+
success: true,
|
|
8
|
+
message,
|
|
9
|
+
data
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
exports.sendSuccessResponse = sendSuccessResponse;
|
|
13
|
+
// Error response
|
|
14
|
+
const sendErrorResponse = (res, message, statusCode = 400, error = null) => {
|
|
15
|
+
console.error("Error sent to client::::::", error);
|
|
16
|
+
res.status(statusCode).json({
|
|
17
|
+
success: false,
|
|
18
|
+
message,
|
|
19
|
+
error: error?.message || error
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
exports.sendErrorResponse = sendErrorResponse;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const userLoginSchema: z.ZodObject<{
|
|
3
|
+
body: z.ZodObject<{
|
|
4
|
+
phoneNumber: z.ZodString;
|
|
5
|
+
nationalId: z.ZodString;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
phoneNumber: string;
|
|
8
|
+
nationalId: string;
|
|
9
|
+
}, {
|
|
10
|
+
phoneNumber: string;
|
|
11
|
+
nationalId: string;
|
|
12
|
+
}>;
|
|
13
|
+
query: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
14
|
+
params: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
15
|
+
headers: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
16
|
+
}, "strip", z.ZodTypeAny, {
|
|
17
|
+
body: {
|
|
18
|
+
phoneNumber: string;
|
|
19
|
+
nationalId: string;
|
|
20
|
+
};
|
|
21
|
+
query?: {} | undefined;
|
|
22
|
+
params?: {} | undefined;
|
|
23
|
+
headers?: {} | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
body: {
|
|
26
|
+
phoneNumber: string;
|
|
27
|
+
nationalId: string;
|
|
28
|
+
};
|
|
29
|
+
query?: {} | undefined;
|
|
30
|
+
params?: {} | undefined;
|
|
31
|
+
headers?: {} | undefined;
|
|
32
|
+
}>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.userLoginSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
exports.userLoginSchema = zod_1.z.object({
|
|
6
|
+
body: zod_1.z.object({
|
|
7
|
+
phoneNumber: zod_1.z
|
|
8
|
+
.string()
|
|
9
|
+
.trim()
|
|
10
|
+
.min(10, "Phone number must be at least 10 digits")
|
|
11
|
+
.max(15, "Phone number must be at most 15 digits"),
|
|
12
|
+
nationalId: zod_1.z.string().min(16, "National ID must be atleast 16 digits")
|
|
13
|
+
}),
|
|
14
|
+
query: zod_1.z.object({}).optional(),
|
|
15
|
+
params: zod_1.z.object({}).optional(),
|
|
16
|
+
headers: zod_1.z.object({}).optional()
|
|
17
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.userLoginSchema = exports.validate = void 0;
|
|
4
|
+
var validate_validations_1 = require("./validate.validations");
|
|
5
|
+
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validate_validations_1.validate; } });
|
|
6
|
+
var auth_validations_1 = require("./auth.validations");
|
|
7
|
+
Object.defineProperty(exports, "userLoginSchema", { enumerable: true, get: function () { return auth_validations_1.userLoginSchema; } });
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const createUserSchema: z.ZodObject<{
|
|
3
|
+
body: z.ZodObject<{
|
|
4
|
+
firstName: z.ZodString;
|
|
5
|
+
lastName: z.ZodString;
|
|
6
|
+
phoneNumber: z.ZodString;
|
|
7
|
+
nationalId: z.ZodString;
|
|
8
|
+
email: z.ZodUnion<[z.ZodNullable<z.ZodOptional<z.ZodString>>, z.ZodLiteral<"">]>;
|
|
9
|
+
password: z.ZodString;
|
|
10
|
+
role: z.ZodEnum<["AGENT", "RIDER"]>;
|
|
11
|
+
plateNumber: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
firstName: string;
|
|
14
|
+
lastName: string;
|
|
15
|
+
phoneNumber: string;
|
|
16
|
+
password: string;
|
|
17
|
+
nationalId: string;
|
|
18
|
+
role: "RIDER" | "AGENT";
|
|
19
|
+
email?: string | null | undefined;
|
|
20
|
+
plateNumber?: string | null | undefined;
|
|
21
|
+
}, {
|
|
22
|
+
firstName: string;
|
|
23
|
+
lastName: string;
|
|
24
|
+
phoneNumber: string;
|
|
25
|
+
password: string;
|
|
26
|
+
nationalId: string;
|
|
27
|
+
role: "RIDER" | "AGENT";
|
|
28
|
+
email?: string | null | undefined;
|
|
29
|
+
plateNumber?: string | null | undefined;
|
|
30
|
+
}>;
|
|
31
|
+
params: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
32
|
+
query: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
33
|
+
headers: z.ZodObject<{
|
|
34
|
+
authorization: z.ZodString;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
authorization: string;
|
|
37
|
+
}, {
|
|
38
|
+
authorization: string;
|
|
39
|
+
}>;
|
|
40
|
+
}, "strip", z.ZodTypeAny, {
|
|
41
|
+
body: {
|
|
42
|
+
firstName: string;
|
|
43
|
+
lastName: string;
|
|
44
|
+
phoneNumber: string;
|
|
45
|
+
password: string;
|
|
46
|
+
nationalId: string;
|
|
47
|
+
role: "RIDER" | "AGENT";
|
|
48
|
+
email?: string | null | undefined;
|
|
49
|
+
plateNumber?: string | null | undefined;
|
|
50
|
+
};
|
|
51
|
+
headers: {
|
|
52
|
+
authorization: string;
|
|
53
|
+
};
|
|
54
|
+
query?: {} | undefined;
|
|
55
|
+
params?: {} | undefined;
|
|
56
|
+
}, {
|
|
57
|
+
body: {
|
|
58
|
+
firstName: string;
|
|
59
|
+
lastName: string;
|
|
60
|
+
phoneNumber: string;
|
|
61
|
+
password: string;
|
|
62
|
+
nationalId: string;
|
|
63
|
+
role: "RIDER" | "AGENT";
|
|
64
|
+
email?: string | null | undefined;
|
|
65
|
+
plateNumber?: string | null | undefined;
|
|
66
|
+
};
|
|
67
|
+
headers: {
|
|
68
|
+
authorization: string;
|
|
69
|
+
};
|
|
70
|
+
query?: {} | undefined;
|
|
71
|
+
params?: {} | undefined;
|
|
72
|
+
}>;
|
|
73
|
+
export declare const getUserByIdSchema: z.ZodObject<{
|
|
74
|
+
params: z.ZodObject<{
|
|
75
|
+
userId: z.ZodString;
|
|
76
|
+
}, "strip", z.ZodTypeAny, {
|
|
77
|
+
userId: string;
|
|
78
|
+
}, {
|
|
79
|
+
userId: string;
|
|
80
|
+
}>;
|
|
81
|
+
body: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
82
|
+
query: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
83
|
+
headers: z.ZodObject<{
|
|
84
|
+
authorization: z.ZodString;
|
|
85
|
+
}, "strip", z.ZodTypeAny, {
|
|
86
|
+
authorization: string;
|
|
87
|
+
}, {
|
|
88
|
+
authorization: string;
|
|
89
|
+
}>;
|
|
90
|
+
}, "strip", z.ZodTypeAny, {
|
|
91
|
+
params: {
|
|
92
|
+
userId: string;
|
|
93
|
+
};
|
|
94
|
+
headers: {
|
|
95
|
+
authorization: string;
|
|
96
|
+
};
|
|
97
|
+
body?: {} | undefined;
|
|
98
|
+
query?: {} | undefined;
|
|
99
|
+
}, {
|
|
100
|
+
params: {
|
|
101
|
+
userId: string;
|
|
102
|
+
};
|
|
103
|
+
headers: {
|
|
104
|
+
authorization: string;
|
|
105
|
+
};
|
|
106
|
+
body?: {} | undefined;
|
|
107
|
+
query?: {} | undefined;
|
|
108
|
+
}>;
|
|
109
|
+
export declare const getAdminProfileSchema: z.ZodObject<{
|
|
110
|
+
params: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
111
|
+
body: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
112
|
+
query: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
113
|
+
headers: z.ZodObject<{
|
|
114
|
+
authorization: z.ZodString;
|
|
115
|
+
}, "strip", z.ZodTypeAny, {
|
|
116
|
+
authorization: string;
|
|
117
|
+
}, {
|
|
118
|
+
authorization: string;
|
|
119
|
+
}>;
|
|
120
|
+
}, "strip", z.ZodTypeAny, {
|
|
121
|
+
headers: {
|
|
122
|
+
authorization: string;
|
|
123
|
+
};
|
|
124
|
+
body?: {} | undefined;
|
|
125
|
+
query?: {} | undefined;
|
|
126
|
+
params?: {} | undefined;
|
|
127
|
+
}, {
|
|
128
|
+
headers: {
|
|
129
|
+
authorization: string;
|
|
130
|
+
};
|
|
131
|
+
body?: {} | undefined;
|
|
132
|
+
query?: {} | undefined;
|
|
133
|
+
params?: {} | undefined;
|
|
134
|
+
}>;
|
|
135
|
+
export declare const updateUserProfileSchema: z.ZodObject<{
|
|
136
|
+
params: z.ZodObject<{
|
|
137
|
+
userId: z.ZodString;
|
|
138
|
+
}, "strip", z.ZodTypeAny, {
|
|
139
|
+
userId: string;
|
|
140
|
+
}, {
|
|
141
|
+
userId: string;
|
|
142
|
+
}>;
|
|
143
|
+
body: z.ZodEffects<z.ZodObject<{
|
|
144
|
+
firstName: z.ZodOptional<z.ZodString>;
|
|
145
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
146
|
+
email: z.ZodUnion<[z.ZodNullable<z.ZodOptional<z.ZodString>>, z.ZodLiteral<"">]>;
|
|
147
|
+
plateNumber: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
148
|
+
isActive: z.ZodOptional<z.ZodBoolean>;
|
|
149
|
+
isSuspended: z.ZodOptional<z.ZodBoolean>;
|
|
150
|
+
password: z.ZodOptional<z.ZodString>;
|
|
151
|
+
}, "strip", z.ZodTypeAny, {
|
|
152
|
+
firstName?: string | undefined;
|
|
153
|
+
lastName?: string | undefined;
|
|
154
|
+
email?: string | null | undefined;
|
|
155
|
+
password?: string | undefined;
|
|
156
|
+
plateNumber?: string | null | undefined;
|
|
157
|
+
isActive?: boolean | undefined;
|
|
158
|
+
isSuspended?: boolean | undefined;
|
|
159
|
+
}, {
|
|
160
|
+
firstName?: string | undefined;
|
|
161
|
+
lastName?: string | undefined;
|
|
162
|
+
email?: string | null | undefined;
|
|
163
|
+
password?: string | undefined;
|
|
164
|
+
plateNumber?: string | null | undefined;
|
|
165
|
+
isActive?: boolean | undefined;
|
|
166
|
+
isSuspended?: boolean | undefined;
|
|
167
|
+
}>, {
|
|
168
|
+
firstName?: string | undefined;
|
|
169
|
+
lastName?: string | undefined;
|
|
170
|
+
email?: string | null | undefined;
|
|
171
|
+
password?: string | undefined;
|
|
172
|
+
plateNumber?: string | null | undefined;
|
|
173
|
+
isActive?: boolean | undefined;
|
|
174
|
+
isSuspended?: boolean | undefined;
|
|
175
|
+
}, {
|
|
176
|
+
firstName?: string | undefined;
|
|
177
|
+
lastName?: string | undefined;
|
|
178
|
+
email?: string | null | undefined;
|
|
179
|
+
password?: string | undefined;
|
|
180
|
+
plateNumber?: string | null | undefined;
|
|
181
|
+
isActive?: boolean | undefined;
|
|
182
|
+
isSuspended?: boolean | undefined;
|
|
183
|
+
}>;
|
|
184
|
+
query: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
185
|
+
headers: z.ZodObject<{
|
|
186
|
+
authorization: z.ZodString;
|
|
187
|
+
}, "strip", z.ZodTypeAny, {
|
|
188
|
+
authorization: string;
|
|
189
|
+
}, {
|
|
190
|
+
authorization: string;
|
|
191
|
+
}>;
|
|
192
|
+
}, "strip", z.ZodTypeAny, {
|
|
193
|
+
body: {
|
|
194
|
+
firstName?: string | undefined;
|
|
195
|
+
lastName?: string | undefined;
|
|
196
|
+
email?: string | null | undefined;
|
|
197
|
+
password?: string | undefined;
|
|
198
|
+
plateNumber?: string | null | undefined;
|
|
199
|
+
isActive?: boolean | undefined;
|
|
200
|
+
isSuspended?: boolean | undefined;
|
|
201
|
+
};
|
|
202
|
+
params: {
|
|
203
|
+
userId: string;
|
|
204
|
+
};
|
|
205
|
+
headers: {
|
|
206
|
+
authorization: string;
|
|
207
|
+
};
|
|
208
|
+
query?: {} | undefined;
|
|
209
|
+
}, {
|
|
210
|
+
body: {
|
|
211
|
+
firstName?: string | undefined;
|
|
212
|
+
lastName?: string | undefined;
|
|
213
|
+
email?: string | null | undefined;
|
|
214
|
+
password?: string | undefined;
|
|
215
|
+
plateNumber?: string | null | undefined;
|
|
216
|
+
isActive?: boolean | undefined;
|
|
217
|
+
isSuspended?: boolean | undefined;
|
|
218
|
+
};
|
|
219
|
+
params: {
|
|
220
|
+
userId: string;
|
|
221
|
+
};
|
|
222
|
+
headers: {
|
|
223
|
+
authorization: string;
|
|
224
|
+
};
|
|
225
|
+
query?: {} | undefined;
|
|
226
|
+
}>;
|
|
227
|
+
export declare const getAllUsersSchema: z.ZodObject<{
|
|
228
|
+
params: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
229
|
+
body: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
230
|
+
query: z.ZodObject<{
|
|
231
|
+
page: z.ZodOptional<z.ZodEffects<z.ZodDefault<z.ZodString>, number, string | undefined>>;
|
|
232
|
+
limit: z.ZodOptional<z.ZodEffects<z.ZodDefault<z.ZodString>, number, string | undefined>>;
|
|
233
|
+
role: z.ZodOptional<z.ZodEnum<["RIDER", "PASSENGER", "AGENT", "ADMIN"]>>;
|
|
234
|
+
isActive: z.ZodOptional<z.ZodEffects<z.ZodEnum<["true", "false"]>, boolean, "true" | "false">>;
|
|
235
|
+
search: z.ZodOptional<z.ZodString>;
|
|
236
|
+
}, "strip", z.ZodTypeAny, {
|
|
237
|
+
search?: string | undefined;
|
|
238
|
+
limit?: number | undefined;
|
|
239
|
+
isActive?: boolean | undefined;
|
|
240
|
+
role?: "RIDER" | "PASSENGER" | "ADMIN" | "AGENT" | undefined;
|
|
241
|
+
page?: number | undefined;
|
|
242
|
+
}, {
|
|
243
|
+
search?: string | undefined;
|
|
244
|
+
limit?: string | undefined;
|
|
245
|
+
isActive?: "true" | "false" | undefined;
|
|
246
|
+
role?: "RIDER" | "PASSENGER" | "ADMIN" | "AGENT" | undefined;
|
|
247
|
+
page?: string | undefined;
|
|
248
|
+
}>;
|
|
249
|
+
headers: z.ZodObject<{
|
|
250
|
+
authorization: z.ZodString;
|
|
251
|
+
}, "strip", z.ZodTypeAny, {
|
|
252
|
+
authorization: string;
|
|
253
|
+
}, {
|
|
254
|
+
authorization: string;
|
|
255
|
+
}>;
|
|
256
|
+
}, "strip", z.ZodTypeAny, {
|
|
257
|
+
query: {
|
|
258
|
+
search?: string | undefined;
|
|
259
|
+
limit?: number | undefined;
|
|
260
|
+
isActive?: boolean | undefined;
|
|
261
|
+
role?: "RIDER" | "PASSENGER" | "ADMIN" | "AGENT" | undefined;
|
|
262
|
+
page?: number | undefined;
|
|
263
|
+
};
|
|
264
|
+
headers: {
|
|
265
|
+
authorization: string;
|
|
266
|
+
};
|
|
267
|
+
body?: {} | undefined;
|
|
268
|
+
params?: {} | undefined;
|
|
269
|
+
}, {
|
|
270
|
+
query: {
|
|
271
|
+
search?: string | undefined;
|
|
272
|
+
limit?: string | undefined;
|
|
273
|
+
isActive?: "true" | "false" | undefined;
|
|
274
|
+
role?: "RIDER" | "PASSENGER" | "ADMIN" | "AGENT" | undefined;
|
|
275
|
+
page?: string | undefined;
|
|
276
|
+
};
|
|
277
|
+
headers: {
|
|
278
|
+
authorization: string;
|
|
279
|
+
};
|
|
280
|
+
body?: {} | undefined;
|
|
281
|
+
params?: {} | undefined;
|
|
282
|
+
}>;
|
|
283
|
+
export type CreateUserInput = z.infer<typeof createUserSchema>;
|
|
284
|
+
export type GetUserByIdInput = z.infer<typeof getUserByIdSchema>;
|
|
285
|
+
export type GetAdminProfileInput = z.infer<typeof getAdminProfileSchema>;
|
|
286
|
+
export type UpdateUserProfileInput = z.infer<typeof updateUserProfileSchema>;
|
|
287
|
+
export type GetAllUsersInput = z.infer<typeof getAllUsersSchema>;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAllUsersSchema = exports.updateUserProfileSchema = exports.getAdminProfileSchema = exports.getUserByIdSchema = exports.createUserSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
// Common validations
|
|
6
|
+
const phoneNumberRegex = /^(078|079|072|073)\d{7}$/;
|
|
7
|
+
const nationalIdRegex = /^\d{16}$/;
|
|
8
|
+
// Admin Create User Schema (for creating agents/riders)
|
|
9
|
+
exports.createUserSchema = zod_1.z.object({
|
|
10
|
+
body: zod_1.z.object({
|
|
11
|
+
firstName: zod_1.z
|
|
12
|
+
.string()
|
|
13
|
+
.min(2, "First name must be at least 2 characters")
|
|
14
|
+
.max(100, "First name cannot exceed 100 characters"),
|
|
15
|
+
lastName: zod_1.z
|
|
16
|
+
.string()
|
|
17
|
+
.min(2, "Last name must be at least 2 characters")
|
|
18
|
+
.max(100, "Last name cannot exceed 100 characters"),
|
|
19
|
+
phoneNumber: zod_1.z
|
|
20
|
+
.string()
|
|
21
|
+
.regex(phoneNumberRegex, "Phone number must be a valid Rwandan number (078/079/072/073) followed by 7 digits"),
|
|
22
|
+
nationalId: zod_1.z
|
|
23
|
+
.string()
|
|
24
|
+
.regex(nationalIdRegex, "National ID must be 16 digits"),
|
|
25
|
+
email: zod_1.z
|
|
26
|
+
.string()
|
|
27
|
+
.email("Invalid email address")
|
|
28
|
+
.optional()
|
|
29
|
+
.nullable()
|
|
30
|
+
.or(zod_1.z.literal("")),
|
|
31
|
+
password: zod_1.z
|
|
32
|
+
.string()
|
|
33
|
+
.min(6, "Password must be at least 6 characters")
|
|
34
|
+
.max(100, "Password cannot exceed 100 characters"),
|
|
35
|
+
role: zod_1.z.enum(["AGENT", "RIDER"], {
|
|
36
|
+
errorMap: () => ({ message: "Role must be either AGENT or RIDER" }),
|
|
37
|
+
}),
|
|
38
|
+
plateNumber: zod_1.z
|
|
39
|
+
.string()
|
|
40
|
+
.max(20, "Plate number cannot exceed 20 characters")
|
|
41
|
+
.optional()
|
|
42
|
+
.nullable(),
|
|
43
|
+
}),
|
|
44
|
+
params: zod_1.z.object({}).optional(),
|
|
45
|
+
query: zod_1.z.object({}).optional(),
|
|
46
|
+
headers: zod_1.z.object({
|
|
47
|
+
authorization: zod_1.z.string().regex(/^Bearer /, {
|
|
48
|
+
message: "Authorization header must start with 'Bearer '",
|
|
49
|
+
}),
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
// Get User by ID Schema
|
|
53
|
+
exports.getUserByIdSchema = zod_1.z.object({
|
|
54
|
+
params: zod_1.z.object({
|
|
55
|
+
userId: zod_1.z.string().uuid("Invalid user ID format"),
|
|
56
|
+
}),
|
|
57
|
+
body: zod_1.z.object({}).optional(),
|
|
58
|
+
query: zod_1.z.object({}).optional(),
|
|
59
|
+
headers: zod_1.z.object({
|
|
60
|
+
authorization: zod_1.z.string().regex(/^Bearer /, {
|
|
61
|
+
message: "Authorization header must start with 'Bearer '",
|
|
62
|
+
}),
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
// Get Admin Profile Schema
|
|
66
|
+
exports.getAdminProfileSchema = zod_1.z.object({
|
|
67
|
+
params: zod_1.z.object({}).optional(),
|
|
68
|
+
body: zod_1.z.object({}).optional(),
|
|
69
|
+
query: zod_1.z.object({}).optional(),
|
|
70
|
+
headers: zod_1.z.object({
|
|
71
|
+
authorization: zod_1.z.string().regex(/^Bearer /, {
|
|
72
|
+
message: "Authorization header must start with 'Bearer '",
|
|
73
|
+
}),
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
// Update User Profile Schema
|
|
77
|
+
exports.updateUserProfileSchema = zod_1.z.object({
|
|
78
|
+
params: zod_1.z.object({
|
|
79
|
+
userId: zod_1.z.string().uuid("Invalid user ID format"),
|
|
80
|
+
}),
|
|
81
|
+
body: zod_1.z
|
|
82
|
+
.object({
|
|
83
|
+
firstName: zod_1.z
|
|
84
|
+
.string()
|
|
85
|
+
.min(2, "First name must be at least 2 characters")
|
|
86
|
+
.max(100, "First name cannot exceed 100 characters")
|
|
87
|
+
.optional(),
|
|
88
|
+
lastName: zod_1.z
|
|
89
|
+
.string()
|
|
90
|
+
.min(2, "Last name must be at least 2 characters")
|
|
91
|
+
.max(100, "Last name cannot exceed 100 characters")
|
|
92
|
+
.optional(),
|
|
93
|
+
email: zod_1.z
|
|
94
|
+
.string()
|
|
95
|
+
.email("Invalid email address")
|
|
96
|
+
.optional()
|
|
97
|
+
.nullable()
|
|
98
|
+
.or(zod_1.z.literal("")),
|
|
99
|
+
plateNumber: zod_1.z
|
|
100
|
+
.string()
|
|
101
|
+
.max(20, "Plate number cannot exceed 20 characters")
|
|
102
|
+
.optional()
|
|
103
|
+
.nullable(),
|
|
104
|
+
isActive: zod_1.z.boolean().optional(),
|
|
105
|
+
isSuspended: zod_1.z.boolean().optional(),
|
|
106
|
+
password: zod_1.z
|
|
107
|
+
.string()
|
|
108
|
+
.min(6, "Password must be at least 6 characters")
|
|
109
|
+
.max(100, "Password cannot exceed 100 characters")
|
|
110
|
+
.optional(),
|
|
111
|
+
})
|
|
112
|
+
.refine((data) => Object.keys(data).length > 0, {
|
|
113
|
+
message: "At least one field must be provided for update",
|
|
114
|
+
}),
|
|
115
|
+
query: zod_1.z.object({}).optional(),
|
|
116
|
+
headers: zod_1.z.object({
|
|
117
|
+
authorization: zod_1.z.string().regex(/^Bearer /, {
|
|
118
|
+
message: "Authorization header must start with 'Bearer '",
|
|
119
|
+
}),
|
|
120
|
+
}),
|
|
121
|
+
});
|
|
122
|
+
// Get All Users Schema (with pagination/filtering)
|
|
123
|
+
exports.getAllUsersSchema = zod_1.z.object({
|
|
124
|
+
params: zod_1.z.object({}).optional(),
|
|
125
|
+
body: zod_1.z.object({}).optional(),
|
|
126
|
+
query: zod_1.z.object({
|
|
127
|
+
page: zod_1.z.string().regex(/^\d+$/).default("1").transform(Number).optional(),
|
|
128
|
+
limit: zod_1.z.string().regex(/^\d+$/).default("20").transform(Number).optional(),
|
|
129
|
+
role: zod_1.z.enum(["RIDER", "PASSENGER", "AGENT", "ADMIN"]).optional(),
|
|
130
|
+
isActive: zod_1.z
|
|
131
|
+
.enum(["true", "false"])
|
|
132
|
+
.transform((val) => val === "true")
|
|
133
|
+
.optional(),
|
|
134
|
+
search: zod_1.z.string().optional(),
|
|
135
|
+
}),
|
|
136
|
+
headers: zod_1.z.object({
|
|
137
|
+
authorization: zod_1.z.string().regex(/^Bearer /, {
|
|
138
|
+
message: "Authorization header must start with 'Bearer '",
|
|
139
|
+
}),
|
|
140
|
+
}),
|
|
141
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from "express";
|
|
2
|
+
import { AnyZodObject } from "zod";
|
|
3
|
+
declare global {
|
|
4
|
+
namespace Express {
|
|
5
|
+
interface Request {
|
|
6
|
+
validatedQuery?: any;
|
|
7
|
+
validatedParams?: any;
|
|
8
|
+
validatedBody?: any;
|
|
9
|
+
validatedHeaders?: any;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export declare const validate: (schema: AnyZodObject) => (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validate = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const validate = (schema) => async (req, res, next) => {
|
|
6
|
+
try {
|
|
7
|
+
// Validate all parts of the request against the schema
|
|
8
|
+
const result = await schema.parseAsync({
|
|
9
|
+
body: req.body,
|
|
10
|
+
query: req.query,
|
|
11
|
+
params: req.params,
|
|
12
|
+
headers: req.headers // Add headers to validation
|
|
13
|
+
});
|
|
14
|
+
// Store validated values in custom properties
|
|
15
|
+
req.validatedBody = result.body;
|
|
16
|
+
req.validatedQuery = result.query;
|
|
17
|
+
req.validatedParams = result.params;
|
|
18
|
+
req.validatedHeaders = result.headers;
|
|
19
|
+
// Only replace body (other parts should remain read-only)
|
|
20
|
+
req.body = result.body || req.body;
|
|
21
|
+
return next();
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.error(" validate middleware function Error::::::", error);
|
|
25
|
+
if (error instanceof zod_1.ZodError) {
|
|
26
|
+
res.status(400).json({
|
|
27
|
+
status: "fail",
|
|
28
|
+
errors: error.errors.map((err) => ({
|
|
29
|
+
path: err.path.join("."),
|
|
30
|
+
message: err.message
|
|
31
|
+
}))
|
|
32
|
+
});
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
next(error);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
exports.validate = validate;
|