PageSourceSearch

https://smart-odpady.ai/src/data/accessControl.js?v=0.1.821

js smart-odpady.ai collected 2026-10-05 14:39:31 UTC 5,846 bytes, 184 lines download raw bytes

1import { ROLE_DEFINITIONS, isFullAccessRole, normalizeRole } from "../permissions.js?v=0.1.821";
2
3export function cloneRoleDefinitions() {
4  return ROLE_DEFINITIONS.map((role) => ({
5    ...role,
6    defaultPermissions: role.defaultPermissions.map((permission) => ({ ...permission }))
7  }));
8}
9
10function normalizePermission(permission) {
11  return {
12    moduleId: String(permission?.moduleId || ""),
13    action: String(permission?.action || "view"),
14    allowed: permission?.allowed !== false
15  };
16}
17
18export function normalizeRoleDefinition(role) {
19  const roleId = normalizeRole(role?.id || role?.name);
20  const fallback = ROLE_DEFINITIONS.find((item) => item.id === roleId) || ROLE_DEFINITIONS.at(-1);
21  const defaultPermissions = isFullAccessRole({ role: roleId, active: true })
22    ? fallback.defaultPermissions.map((permission) => ({ ...permission }))
23    : Array.isArray(role?.defaultPermissions)
24      ? role.defaultPermissions.map(normalizePermission)
25      : fallback.defaultPermissions.map((permission) => ({ ...permission }));
26
27  return {
28    id: normalizeRole(role?.id || role?.name || fallback.id),
29    name: normalizeRole(role?.name || role?.id || fallback.name),
30    label: String(role?.label || fallback.label),
31    description: String(role?.description || fallback.description),
32    defaultPermissions
33  };
34}
35
36export function normalizeAccessUser(user) {
37  const active = user?.active === false || String(user?.status || "").toLowerCase() === "disabled"
38    ? false
39    : true;
40
41  return {
42    id: String(user?.id || ""),
43    name: String(user?.name || ""),
44    email: String(user?.email || ""),
45    phone: String(user?.phone || ""),
46    role: normalizeRole(user?.role || "readonly"),
47    department: String(user?.department || ""),
48    position: String(user?.position || ""),
49    managerId: String(user?.managerId || ""),
50    managerName: String(user?.managerName || ""),
51    active,
52    status: active ? "active" : "disabled",
53    permissions: Array.isArray(user?.permissions) ? user.permissions.map(normalizePermission) : [],
54    modules: Array.isArray(user?.modules) ? [...user.modules] : undefined,
55    allowedModules: Array.isArray(user?.allowedModules) ? [...user.allowedModules] : undefined,
56    deniedModules: Array.isArray(user?.deniedModules) ? [...user.deniedModules] : undefined,
57    createdAt: user?.createdAt || new Date().toISOString(),
58    updatedAt: user?.updatedAt || new Date().toISOString(),
59    lastLoginAt: user?.lastLoginAt || null
60  };
61}
62
63export function defaultAccessState() {
64  return {
65    users: [],
66    roles: cloneRoleDefinitions(),
67    selectedUserId: "",
68    selectedRoleId: "ridic",
69    message: "",
70    error: "",
71    feedbackTarget: ""
72  };
73}
74
75export function loadAccessState() {
76  return defaultAccessState();
77}
78
79export function saveAccessState(state) {
80  return {
81    ...defaultAccessState(),
82    ...state,
83    users: Array.isArray(state.users) ? state.users.map(normalizeAccessUser) : [],
84    roles: Array.isArray(state.roles) ? state.roles.map(normalizeRoleDefinition) : cloneRoleDefinitions()
85  };
86}
87
88function userKey(user) {
89  const email = String(user?.email || "").trim().toLowerCase();
90  return email || String(user?.id || "").trim().toLowerCase();
91}
92
93function userId(user) {
94  return String(user?.id || "").trim().toLowerCase();
95}
96
97export function mergeAccessUsers(baseUsers, accessUsers) {
98  const users = new Map();
99  const idToKey = new Map();
100
101  function upsert(user) {
102    const normalized = normalizeAccessUser(user);
103    const key = userKey(normalized);
104    const id = userId(normalized);
105
106    if (!key && !id) {
107      return;
108    }
109
110    const existingKey = (key && users.has(key) ? key : "") || (id ? idToKey.get(id) : "");
111    const nextUser = existingKey ? { ...users.get(existingKey), ...normalized } : normalized;
112    const nextKey = userKey(nextUser) || key || id;
113
114    if (existingKey && existingKey !== nextKey) {
115      users.delete(existingKey);
116    }
117
118    users.set(nextKey, nextUser);
119    if (id) {
120      idToKey.set(id, nextKey);
121    }
122  }
123
124  baseUsers.forEach(upsert);
125  accessUsers.forEach(upsert);
126
127  return [...users.values()].sort((a, b) => a.name.localeCompare(b.name, "cs"));
128}
129
130export function rolePermissionContext(roles) {
131  return Object.fromEntries(roles.map((role) => [
132    role.id,
133    role.defaultPermissions.map((permission) => ({ ...permission }))
134  ]));
135}
136
137export function withAccessContext(user, accessState) {
138  if (!user) {
139    return null;
140  }
141
142  const normalizedUser = normalizeAccessUser(user);
143  const mergedUsers = mergeAccessUsers([normalizedUser], accessState.users);
144  const normalizedEmail = normalizedUser.email.trim().toLowerCase();
145  const normalizedId = normalizedUser.id.trim().toLowerCase();
146  const merged = mergedUsers.find((item) => (
147    (normalizedEmail && item.email.trim().toLowerCase() === normalizedEmail) ||
148    (normalizedId && item.id.trim().toLowerCase() === normalizedId)
149  )) || normalizedUser;
150
151  return {
152    ...merged,
153    rolePermissions: rolePermissionContext(accessState.roles)
154  };
155}
156
157export function permissionMap(permissions) {
158  const map = new Map();
159  permissions.forEach((permission) => {
160    map.set(`${permission.moduleId}:${permission.action}`, permission.allowed !== false);
161  });
162  return map;
163}
164
165export function rolePermissionsFor(roleId, roles) {
166  const role = roles.find((item) => item.id === normalizeRole(roleId));
167  return role ? role.defaultPermissions.map((permission) => ({ ...permission })) : [];
168}
169
170export function makePermissionsFromMatrix(moduleItems, actions, formData, prefix) {
171  const permissions = [];
172
173  moduleItems.forEach((moduleItem) => {
174    actions.forEach((action) => {
175      permissions.push({
176        moduleId: moduleItem.id,
177        action,
178        allowed: formData.get(`${prefix}-${moduleItem.id}-${action}`) === "on"
179      });
180    });
181  });
182
183  return permissions;
184}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.