vr-commons 1.0.47 → 1.0.48
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/utils/bans.utils.d.ts +36 -0
- package/dist/utils/bans.utils.js +55 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +10 -1
- package/dist/utils/moderation.utils.d.ts +25 -0
- package/dist/utils/moderation.utils.js +100 -0
- package/dist/utils/suspension.utils.d.ts +41 -0
- package/dist/utils/suspension.utils.js +79 -0
- package/package.json +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Ban } from "vr-models";
|
|
2
|
+
export declare const banUtil: {
|
|
3
|
+
formatBanForResponse: (ban: any) => {
|
|
4
|
+
id: any;
|
|
5
|
+
user: {
|
|
6
|
+
id: any;
|
|
7
|
+
name: string;
|
|
8
|
+
phoneNumber: any;
|
|
9
|
+
email: any;
|
|
10
|
+
} | null;
|
|
11
|
+
admin: {
|
|
12
|
+
id: any;
|
|
13
|
+
name: string;
|
|
14
|
+
} | null;
|
|
15
|
+
reason: any;
|
|
16
|
+
bannedAt: any;
|
|
17
|
+
isPermanent: any;
|
|
18
|
+
appeal: {
|
|
19
|
+
appealedAt: any;
|
|
20
|
+
appealReason: any;
|
|
21
|
+
appealStatus: any;
|
|
22
|
+
} | null;
|
|
23
|
+
revocation: {
|
|
24
|
+
revokedAt: any;
|
|
25
|
+
revokingAdmin: {
|
|
26
|
+
id: any;
|
|
27
|
+
name: string;
|
|
28
|
+
} | null;
|
|
29
|
+
revocationReason: any;
|
|
30
|
+
} | null;
|
|
31
|
+
createdAt: any;
|
|
32
|
+
updatedAt: any;
|
|
33
|
+
};
|
|
34
|
+
isBanActive: (ban: Ban) => boolean;
|
|
35
|
+
canAppeal: (ban: Ban) => boolean;
|
|
36
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.banUtil = void 0;
|
|
4
|
+
exports.banUtil = {
|
|
5
|
+
formatBanForResponse: (ban) => {
|
|
6
|
+
const banJson = ban.toJSON ? ban.toJSON() : ban;
|
|
7
|
+
return {
|
|
8
|
+
id: banJson.id,
|
|
9
|
+
user: banJson.user
|
|
10
|
+
? {
|
|
11
|
+
id: banJson.user.id,
|
|
12
|
+
name: `${banJson.user.firstName} ${banJson.user.lastName}`,
|
|
13
|
+
phoneNumber: banJson.user.phoneNumber,
|
|
14
|
+
email: banJson.user.email,
|
|
15
|
+
}
|
|
16
|
+
: null,
|
|
17
|
+
admin: banJson.admin
|
|
18
|
+
? {
|
|
19
|
+
id: banJson.admin.id,
|
|
20
|
+
name: `${banJson.admin.firstName} ${banJson.admin.lastName}`,
|
|
21
|
+
}
|
|
22
|
+
: null,
|
|
23
|
+
reason: banJson.reason,
|
|
24
|
+
bannedAt: banJson.bannedAt,
|
|
25
|
+
isPermanent: banJson.isPermanent,
|
|
26
|
+
appeal: banJson.appealedAt
|
|
27
|
+
? {
|
|
28
|
+
appealedAt: banJson.appealedAt,
|
|
29
|
+
appealReason: banJson.appealReason,
|
|
30
|
+
appealStatus: banJson.appealStatus,
|
|
31
|
+
}
|
|
32
|
+
: null,
|
|
33
|
+
revocation: banJson.revokedAt
|
|
34
|
+
? {
|
|
35
|
+
revokedAt: banJson.revokedAt,
|
|
36
|
+
revokingAdmin: banJson.revokingAdmin
|
|
37
|
+
? {
|
|
38
|
+
id: banJson.revokingAdmin.id,
|
|
39
|
+
name: `${banJson.revokingAdmin.firstName} ${banJson.revokingAdmin.lastName}`,
|
|
40
|
+
}
|
|
41
|
+
: null,
|
|
42
|
+
revocationReason: banJson.revocationReason,
|
|
43
|
+
}
|
|
44
|
+
: null,
|
|
45
|
+
createdAt: banJson.createdAt,
|
|
46
|
+
updatedAt: banJson.updatedAt,
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
isBanActive: (ban) => {
|
|
50
|
+
return !ban.revokedAt;
|
|
51
|
+
},
|
|
52
|
+
canAppeal: (ban) => {
|
|
53
|
+
return !ban.appealedAt && !ban.revokedAt && ban.isPermanent;
|
|
54
|
+
},
|
|
55
|
+
};
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -3,3 +3,6 @@ export { generateAdminToken, generatePassengerToken, generateRiderToken, verifyT
|
|
|
3
3
|
export { logEvent } from "./eventLog.utils";
|
|
4
4
|
export { sendSuccessResponse, sendErrorResponse } from "./response.utils";
|
|
5
5
|
export { formatUserProfile, formatUserListResponse, hasRole, hasPermission, hasAnyPermission, hasAllPermissions, canModifyAccount, isAccountAccessible, getUserById, getUsersByRole, findSecurityClearanceByRole, generateUserSearchConditions, generateEventSearchConditions, getSortOrder, generateJacketId, validateUniqueFields, validatePassword, hashPassword, softDeleteUser, } from "./profiles.utils";
|
|
6
|
+
export { canModerate, canModerateUser, getModeratableRoles, hasHigherAuthority, } from "./moderation.utils";
|
|
7
|
+
export { banUtil } from "./bans.utils";
|
|
8
|
+
export { suspensionUtil } from "./suspension.utils";
|
package/dist/utils/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
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.verifyToken = exports.generateRiderToken = exports.generatePassengerToken = exports.generateAdminToken = exports.checkSuspensionStatus = exports.checkIsUserBannedOrSuspended = exports.checkBanStatus = exports.hasActiveDependencies = exports.checkAccountDependencies = void 0;
|
|
3
|
+
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.verifyToken = exports.generateRiderToken = exports.generatePassengerToken = exports.generateAdminToken = exports.checkSuspensionStatus = exports.checkIsUserBannedOrSuspended = exports.checkBanStatus = exports.hasActiveDependencies = exports.checkAccountDependencies = void 0;
|
|
4
4
|
var account_utils_1 = require("./account.utils");
|
|
5
5
|
Object.defineProperty(exports, "checkAccountDependencies", { enumerable: true, get: function () { return account_utils_1.checkAccountDependencies; } });
|
|
6
6
|
Object.defineProperty(exports, "hasActiveDependencies", { enumerable: true, get: function () { return account_utils_1.hasActiveDependencies; } });
|
|
@@ -44,3 +44,12 @@ Object.defineProperty(exports, "validatePassword", { enumerable: true, get: func
|
|
|
44
44
|
Object.defineProperty(exports, "hashPassword", { enumerable: true, get: function () { return profiles_utils_1.hashPassword; } });
|
|
45
45
|
// Account management functions
|
|
46
46
|
Object.defineProperty(exports, "softDeleteUser", { enumerable: true, get: function () { return profiles_utils_1.softDeleteUser; } });
|
|
47
|
+
var moderation_utils_1 = require("./moderation.utils");
|
|
48
|
+
Object.defineProperty(exports, "canModerate", { enumerable: true, get: function () { return moderation_utils_1.canModerate; } });
|
|
49
|
+
Object.defineProperty(exports, "canModerateUser", { enumerable: true, get: function () { return moderation_utils_1.canModerateUser; } });
|
|
50
|
+
Object.defineProperty(exports, "getModeratableRoles", { enumerable: true, get: function () { return moderation_utils_1.getModeratableRoles; } });
|
|
51
|
+
Object.defineProperty(exports, "hasHigherAuthority", { enumerable: true, get: function () { return moderation_utils_1.hasHigherAuthority; } });
|
|
52
|
+
var bans_utils_1 = require("./bans.utils");
|
|
53
|
+
Object.defineProperty(exports, "banUtil", { enumerable: true, get: function () { return bans_utils_1.banUtil; } });
|
|
54
|
+
var suspension_utils_1 = require("./suspension.utils");
|
|
55
|
+
Object.defineProperty(exports, "suspensionUtil", { enumerable: true, get: function () { return suspension_utils_1.suspensionUtil; } });
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { User } from "vr-models";
|
|
2
|
+
import { UserRole } from "vr-models";
|
|
3
|
+
interface HierarchyCheckResult {
|
|
4
|
+
allowed: boolean;
|
|
5
|
+
reason?: string;
|
|
6
|
+
code?: "INSUFFICIENT_HIERARCHY" | "SAME_LEVEL_RESTRICTION" | "CANNOT_ACT_ON_HIGHER" | "CANNOT_ACT_ON_SELF";
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Check if an actor can perform moderation actions on a target user
|
|
10
|
+
* based on role hierarchy and security clearance levels
|
|
11
|
+
*/
|
|
12
|
+
export declare function canModerateUser(actorUser: User, targetUser: User): Promise<HierarchyCheckResult>;
|
|
13
|
+
/**
|
|
14
|
+
* Simplified version that just returns boolean
|
|
15
|
+
*/
|
|
16
|
+
export declare function canModerate(actorUser: User, targetUser: User): Promise<boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* Get list of roles that actor can moderate
|
|
19
|
+
*/
|
|
20
|
+
export declare function getModeratableRoles(actorRole: UserRole): UserRole[];
|
|
21
|
+
/**
|
|
22
|
+
* Check if actor has higher authority than target
|
|
23
|
+
*/
|
|
24
|
+
export declare function hasHigherAuthority(actorRole: UserRole, actorLevel: number, targetRole: UserRole, targetLevel: number): boolean;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canModerateUser = canModerateUser;
|
|
4
|
+
exports.canModerate = canModerate;
|
|
5
|
+
exports.getModeratableRoles = getModeratableRoles;
|
|
6
|
+
exports.hasHigherAuthority = hasHigherAuthority;
|
|
7
|
+
// Role hierarchy levels (higher number = more authority)
|
|
8
|
+
const ROLE_HIERARCHY = {
|
|
9
|
+
RIDER: 0,
|
|
10
|
+
PASSENGER: 0,
|
|
11
|
+
AGENT: 1,
|
|
12
|
+
ADMIN: 2,
|
|
13
|
+
SUPER_ADMIN: 3,
|
|
14
|
+
};
|
|
15
|
+
// Who can act on whom matrix
|
|
16
|
+
const CAN_ACT_ON = {
|
|
17
|
+
RIDER: [], // Riders cannot act on anyone
|
|
18
|
+
PASSENGER: [], // Passengers cannot act on anyone
|
|
19
|
+
AGENT: ["RIDER", "PASSENGER"], // Agents can act on riders and passengers
|
|
20
|
+
ADMIN: ["RIDER", "PASSENGER", "AGENT"], // Admins can act on riders, passengers, and agents
|
|
21
|
+
SUPER_ADMIN: ["RIDER", "PASSENGER", "AGENT", "ADMIN", "SUPER_ADMIN"], // Super admin can act on everyone
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Check if an actor can perform moderation actions on a target user
|
|
25
|
+
* based on role hierarchy and security clearance levels
|
|
26
|
+
*/
|
|
27
|
+
async function canModerateUser(actorUser, targetUser) {
|
|
28
|
+
try {
|
|
29
|
+
// Cannot act on self
|
|
30
|
+
if (actorUser.id === targetUser.id) {
|
|
31
|
+
return {
|
|
32
|
+
allowed: false,
|
|
33
|
+
reason: "You cannot moderate your own account",
|
|
34
|
+
code: "CANNOT_ACT_ON_SELF",
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// Get roles
|
|
38
|
+
const actorRole = actorUser.securityClearance?.role || "RIDER";
|
|
39
|
+
const targetRole = targetUser.securityClearance?.role || "RIDER";
|
|
40
|
+
// Get hierarchy levels
|
|
41
|
+
const actorLevel = ROLE_HIERARCHY[actorRole];
|
|
42
|
+
const targetLevel = ROLE_HIERARCHY[targetRole];
|
|
43
|
+
// Check if actor can act on target based on role matrix
|
|
44
|
+
const allowedTargets = CAN_ACT_ON[actorRole] || [];
|
|
45
|
+
if (!allowedTargets.includes(targetRole)) {
|
|
46
|
+
return {
|
|
47
|
+
allowed: false,
|
|
48
|
+
reason: `${actorRole === targetRole
|
|
49
|
+
? `Cannot moderate another ${actorRole.toLowerCase()}`
|
|
50
|
+
: `${actorRole} cannot moderate ${targetRole}`}`,
|
|
51
|
+
code: "CANNOT_ACT_ON_HIGHER",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// If same role, check levels
|
|
55
|
+
if (actorRole === targetRole) {
|
|
56
|
+
// For same role, only higher level can moderate lower level
|
|
57
|
+
if (actorLevel <= targetLevel) {
|
|
58
|
+
return {
|
|
59
|
+
allowed: false,
|
|
60
|
+
reason: `Cannot moderate another ${actorRole.toLowerCase()} with equal or higher security level`,
|
|
61
|
+
code: "SAME_LEVEL_RESTRICTION",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// All checks passed
|
|
66
|
+
return { allowed: true };
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error("Error in canModerateUser:", error);
|
|
70
|
+
return {
|
|
71
|
+
allowed: false,
|
|
72
|
+
reason: "Error checking moderation permissions",
|
|
73
|
+
code: "INSUFFICIENT_HIERARCHY",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Simplified version that just returns boolean
|
|
79
|
+
*/
|
|
80
|
+
async function canModerate(actorUser, targetUser) {
|
|
81
|
+
const result = await canModerateUser(actorUser, targetUser);
|
|
82
|
+
return result.allowed;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get list of roles that actor can moderate
|
|
86
|
+
*/
|
|
87
|
+
function getModeratableRoles(actorRole) {
|
|
88
|
+
return CAN_ACT_ON[actorRole] || [];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if actor has higher authority than target
|
|
92
|
+
*/
|
|
93
|
+
function hasHigherAuthority(actorRole, actorLevel, targetRole, targetLevel) {
|
|
94
|
+
if (actorRole !== targetRole) {
|
|
95
|
+
// Different roles - check if actor can act on target
|
|
96
|
+
return (CAN_ACT_ON[actorRole] || []).includes(targetRole);
|
|
97
|
+
}
|
|
98
|
+
// Same role - compare levels
|
|
99
|
+
return actorLevel > targetLevel;
|
|
100
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Suspension } from "vr-models";
|
|
2
|
+
export declare const suspensionUtil: {
|
|
3
|
+
formatSuspensionForResponse: (suspension: any) => {
|
|
4
|
+
id: any;
|
|
5
|
+
user: {
|
|
6
|
+
id: any;
|
|
7
|
+
name: string;
|
|
8
|
+
phoneNumber: any;
|
|
9
|
+
email: any;
|
|
10
|
+
} | null;
|
|
11
|
+
admin: {
|
|
12
|
+
id: any;
|
|
13
|
+
name: string;
|
|
14
|
+
} | null;
|
|
15
|
+
reason: any;
|
|
16
|
+
startedAt: any;
|
|
17
|
+
endsAt: any;
|
|
18
|
+
isActive: any;
|
|
19
|
+
daysRemaining: number;
|
|
20
|
+
status: string;
|
|
21
|
+
appeal: {
|
|
22
|
+
appealedAt: any;
|
|
23
|
+
appealReason: any;
|
|
24
|
+
appealStatus: any;
|
|
25
|
+
} | null;
|
|
26
|
+
revocation: {
|
|
27
|
+
revokedAt: any;
|
|
28
|
+
revokingAdmin: {
|
|
29
|
+
id: any;
|
|
30
|
+
name: string;
|
|
31
|
+
} | null;
|
|
32
|
+
revocationReason: any;
|
|
33
|
+
} | null;
|
|
34
|
+
extensions: any;
|
|
35
|
+
createdAt: any;
|
|
36
|
+
updatedAt: any;
|
|
37
|
+
};
|
|
38
|
+
isSuspensionActive: (suspension: Suspension) => boolean;
|
|
39
|
+
canAppeal: (suspension: Suspension) => boolean;
|
|
40
|
+
getTimeRemaining: (suspension: Suspension) => number;
|
|
41
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.suspensionUtil = void 0;
|
|
4
|
+
exports.suspensionUtil = {
|
|
5
|
+
formatSuspensionForResponse: (suspension) => {
|
|
6
|
+
const suspensionJson = suspension.toJSON ? suspension.toJSON() : suspension;
|
|
7
|
+
const now = new Date();
|
|
8
|
+
const endDate = new Date(suspensionJson.endsAt);
|
|
9
|
+
const isCurrentlyActive = suspensionJson.isActive && endDate > now;
|
|
10
|
+
return {
|
|
11
|
+
id: suspensionJson.id,
|
|
12
|
+
user: suspensionJson.user
|
|
13
|
+
? {
|
|
14
|
+
id: suspensionJson.user.id,
|
|
15
|
+
name: `${suspensionJson.user.firstName} ${suspensionJson.user.lastName}`,
|
|
16
|
+
phoneNumber: suspensionJson.user.phoneNumber,
|
|
17
|
+
email: suspensionJson.user.email,
|
|
18
|
+
}
|
|
19
|
+
: null,
|
|
20
|
+
admin: suspensionJson.admin
|
|
21
|
+
? {
|
|
22
|
+
id: suspensionJson.admin.id,
|
|
23
|
+
name: `${suspensionJson.admin.firstName} ${suspensionJson.admin.lastName}`,
|
|
24
|
+
}
|
|
25
|
+
: null,
|
|
26
|
+
reason: suspensionJson.reason,
|
|
27
|
+
startedAt: suspensionJson.startedAt,
|
|
28
|
+
endsAt: suspensionJson.endsAt,
|
|
29
|
+
isActive: isCurrentlyActive,
|
|
30
|
+
daysRemaining: isCurrentlyActive
|
|
31
|
+
? Math.ceil((endDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24))
|
|
32
|
+
: 0,
|
|
33
|
+
status: isCurrentlyActive
|
|
34
|
+
? "ACTIVE"
|
|
35
|
+
: suspensionJson.revokedAt
|
|
36
|
+
? "REVOKED"
|
|
37
|
+
: "EXPIRED",
|
|
38
|
+
appeal: suspensionJson.appealedAt
|
|
39
|
+
? {
|
|
40
|
+
appealedAt: suspensionJson.appealedAt,
|
|
41
|
+
appealReason: suspensionJson.appealReason,
|
|
42
|
+
appealStatus: suspensionJson.appealStatus,
|
|
43
|
+
}
|
|
44
|
+
: null,
|
|
45
|
+
revocation: suspensionJson.revokedAt
|
|
46
|
+
? {
|
|
47
|
+
revokedAt: suspensionJson.revokedAt,
|
|
48
|
+
revokingAdmin: suspensionJson.revokingAdmin
|
|
49
|
+
? {
|
|
50
|
+
id: suspensionJson.revokingAdmin.id,
|
|
51
|
+
name: `${suspensionJson.revokingAdmin.firstName} ${suspensionJson.revokingAdmin.lastName}`,
|
|
52
|
+
}
|
|
53
|
+
: null,
|
|
54
|
+
revocationReason: suspensionJson.revocationReason,
|
|
55
|
+
}
|
|
56
|
+
: null,
|
|
57
|
+
extensions: suspensionJson.metadata?.extensions || [],
|
|
58
|
+
createdAt: suspensionJson.createdAt,
|
|
59
|
+
updatedAt: suspensionJson.updatedAt,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
isSuspensionActive: (suspension) => {
|
|
63
|
+
return suspension.isActive && new Date(suspension.endsAt) > new Date();
|
|
64
|
+
},
|
|
65
|
+
canAppeal: (suspension) => {
|
|
66
|
+
return (!suspension.appealedAt &&
|
|
67
|
+
!suspension.revokedAt &&
|
|
68
|
+
new Date(suspension.endsAt) > new Date());
|
|
69
|
+
},
|
|
70
|
+
getTimeRemaining: (suspension) => {
|
|
71
|
+
if (!suspension.isActive)
|
|
72
|
+
return 0;
|
|
73
|
+
const endDate = new Date(suspension.endsAt);
|
|
74
|
+
const now = new Date();
|
|
75
|
+
if (endDate <= now)
|
|
76
|
+
return 0;
|
|
77
|
+
return Math.ceil((endDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
|
78
|
+
},
|
|
79
|
+
};
|