PageSourceSearch

https://wyber.ai/chunk-5PIXT7LD.js

js wyber.ai collected 2026-10-05 13:22:10 UTC 7,992 bytes, 244 lines download raw bytes

1import {
2  UserManagementService,
3  init_permission_config,
4  permission_config_exports
5} from "./chunk-IMGOCUIU.js";
6import {
7  BehaviorSubject,
8  Injectable,
9  forkJoin,
10  retry,
11  setClassMetadata,
12  shareReplay,
13  timer,
14  ɵɵdefineInjectable,
15  ɵɵinject
16} from "./chunk-6GJQIPT2.js";
17import {
18  __toCommonJS
19} from "./chunk-RK4NW2NR.js";
20
21// src/app/utils/retry-transient.ts
22function isTransientHttpError(error) {
23  const status = error?.status ?? 0;
24  return status === 0 || status === 408 || status === 429 || status >= 500;
25}
26function retryTransient(count = 2, baseDelayMs = 800) {
27  return retry({
28    count,
29    delay: (error, attempt) => {
30      if (!isTransientHttpError(error)) {
31        throw error;
32      }
33      return timer(attempt * baseDelayMs);
34    }
35  });
36}
37
38// src/app/services/permission.service.ts
39var normalizeCode = (input) => (input ?? "").toUpperCase().trim().replace(/[\s-]+/g, "_");
40var normalizePermissions = (raw) => {
41  const set = /* @__PURE__ */ new Set();
42  for (const p of raw || []) {
43    const normalized = normalizeCode(p);
44    if (normalized) {
45      set.add(normalized);
46    }
47  }
48  return Array.from(set);
49};
50var currentRoles = /* @__PURE__ */ new Set();
51var currentPermissions = /* @__PURE__ */ new Set();
52var currentGroups = /* @__PURE__ */ new Set();
53var setPermissionContext = (input) => {
54  const roleCodes = new Set(normalizePermissions(input.roles ?? []));
55  const groupCodes = new Set(normalizePermissions(input.permissionGroups ?? []));
56  const permissionCodes = new Set(normalizePermissions(input.permissions ?? []));
57  currentRoles = roleCodes;
58  currentGroups = groupCodes;
59  currentPermissions = permissionCodes;
60};
61var hasPermission = (permission) => {
62  const isSuperAdminUser = ["SUPER_ADMIN", "SUPERADMIN"].some((r) => currentRoles.has(r));
63  if (isSuperAdminUser)
64    return true;
65  const code = normalizeCode(permission);
66  if (!code)
67    return false;
68  if (currentPermissions.has(code))
69    return true;
70  if (code.includes("PERMISSIONGROUP")) {
71    const fallbackCode = code.replace("PERMISSIONGROUP", "PERMISSION_GROUP");
72    if (currentPermissions.has(fallbackCode))
73      return true;
74  }
75  if (code.includes("PERMISSION_GROUP")) {
76    const fallbackCode = code.replace("PERMISSION_GROUP", "PERMISSIONGROUP");
77    if (currentPermissions.has(fallbackCode))
78      return true;
79  }
80  return false;
81};
82var hasAny = (permissions) => {
83  for (const p of permissions || []) {
84    if (hasPermission(p))
85      return true;
86  }
87  return false;
88};
89var hasGroup = (group) => {
90  const code = normalizeCode(group);
91  if (!code)
92    return false;
93  return currentGroups.has(code);
94};
95var hasRole = (role) => {
96  const code = normalizeCode(role);
97  if (!code) {
98    return false;
99  }
100  const result = currentRoles.has(code);
101  return result;
102};
103var PermissionService = class _PermissionService {
104  userManagementService;
105  currentUserProfile$ = new BehaviorSubject(null);
106  isSessionReady$ = new BehaviorSubject(false);
107  // Layout, PageHeader and other shells all bootstrap the profile from the same
108  // users+roles pair on load. Without sharing the in-flight request each of them
109  // fires its own HTTP call, tripling the /api/users and /api/roles hits on every
110  // page load. Caching here collapses concurrent/duplicate callers onto one call.
111  usersAndRoles$ = null;
112  constructor(userManagementService) {
113    this.userManagementService = userManagementService;
114  }
115  loadUsersAndRoles() {
116    if (!this.usersAndRoles$) {
117      this.usersAndRoles$ = forkJoin({
118        users: this.userManagementService.getUsers(),
119        roles: this.userManagementService.getRoles()
120      }).pipe(retryTransient(), shareReplay(1));
121    }
122    return this.usersAndRoles$;
123  }
124  /** Call before loadUsersAndRoles() when a caller needs a guaranteed-fresh fetch (e.g. after an IAM change push). */
125  invalidateUsersAndRolesCache() {
126    this.usersAndRoles$ = null;
127  }
128  setSessionReady(ready) {
129    this.isSessionReady$.next(ready);
130  }
131  setUserProfile(user) {
132    this.currentUserProfile$.next(user);
133    if (!user) {
134      this.setSessionReady(false);
135    }
136    if (user) {
137      const roles = user.roles.map((r) => normalizeCode(r.name));
138      const roleGroups = user.roles.flatMap((r) => r.permissionGroups?.map((g) => normalizeCode(g.name)) ?? []);
139      const directGroups = user.permissionGroups?.map((g) => normalizeCode(g.name)) ?? [];
140      const permissionGroups = [...roleGroups, ...directGroups];
141      const rolePermissions = user.roles.flatMap((r) => [
142        ...r.permissions.map((p) => normalizeCode(p.name)),
143        ...r.permissionGroups.flatMap((g) => g.permissions.map((p) => normalizeCode(p.name)))
144      ]);
145      const directPermissions = user.permissionGroups?.flatMap((g) => g.permissions?.map((p) => normalizeCode(p.name)) ?? []) ?? [];
146      const permissions = [...rolePermissions, ...directPermissions];
147      setPermissionContext({ roles, permissionGroups, permissions });
148    } else {
149      setPermissionContext({ roles: [], permissionGroups: [], permissions: [] });
150    }
151  }
152  getUserProfile() {
153    return this.currentUserProfile$.asObservable();
154  }
155  getCurrentUserProfile() {
156    return this.currentUserProfile$.value;
157  }
158  hasPermission(permissionName) {
159    return hasPermission(permissionName);
160  }
161  hasAnyPermission(permissionNames) {
162    return hasAny(permissionNames);
163  }
164  hasRole(roleName) {
165    return hasRole(roleName);
166  }
167  hasGroup(groupName) {
168    return hasGroup(groupName);
169  }
170  isSuperAdmin() {
171    const { ROLE_TYPES } = (init_permission_config(), __toCommonJS(permission_config_exports
171));
172    return ROLE_TYPES.SUPER_ADMIN.some((roleName) => hasRole(roleName));
173  }
174  isAdmin() {
175    const { ROLE_TYPES } = (init_permission_config(), __toCommonJS(permission_config_exports));
176    return ROLE_TYPES.ADMIN.some((roleName) => hasRole(roleName));
177  }
178  isViewer() {
179    const { ROLE_TYPES } = (init_permission_config(), __toCommonJS(permission_config_exports));
180    return ROLE_TYPES.VIEWER.some((roleName) => hasRole(roleName));
181  }
182  /**
183   * Check if user has a specific role type (configured in permission-config)
184   */
185  hasRoleType(roleType) {
186    const { ROLE_TYPES } = (init_permission_config(), __toCommonJS(permission_config_exports));
187    const roleNames = ROLE_TYPES[roleType];
188    if (!roleNames)
189      return false;
190    return roleNames.some((roleName) => hasRole(roleName));
191  }
192  /**
193   * Get all permissions for the current user
194   */
195  getAllPermissions() {
196    return Array.from(currentPermissions);
197  }
198  /**
199   * Get all permission groups for the current user
200   */
201  getAllGroups() {
202    return Array.from(currentGroups);
203  }
204  /**
205   * Get all roles for the current user
206   */
207  getAllRoles() {
208    return Array.from(currentRoles);
209  }
210  /**
211   * Debug helper: Get detailed permission information
212   * Useful for troubleshooting permission issues
213   */
214  getPermissionDebugInfo() {
215    const profile = this.getCurrentUserProfile();
216    return {
217      roles: this.getAllRoles(),
218      permissionGroups: this.getAllGroups(),
219      permissions: this.getAllPermissions(),
220      userProfile: profile,
221      hasDeleteRfpCard: this.hasPermission("DELETE_RFP_CARD"),
222      hasDeleteRole: this.hasPermission("DELETE_ROLE"),
223      hasDeletePermission: this.hasPermission("DELETE_PERMISSION")
224    };
225  }
226  static \u0275fac = function PermissionService_Factory(__ngFactoryType__) {
227    return new (__ngFactoryType__ || _PermissionService)(\u0275\u0275inject(UserManagementService));
228  };
229  static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _PermissionService, factory: _PermissionService.\u0275fac, providedIn: "root" });
230};
231(() => {
232  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PermissionService, [{
233    type: Injectable,
234    args: [{
235      providedIn: "root"
236    }]
237  }], () => [{ type: UserManagementService }], null);
238})();
239
240export {
241  isTransientHttpError,
242  PermissionService
243};
244//# sourceMappingURL=chunk-5PIXT7LD.js.map

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.