hazo_auth 4.5.3 → 4.5.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/user_management/index.tsx"],"names":[],"mappings":"AA0DA,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,4DAA4D;IAC5D,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,cAAc,EAAE,CAAC;CACvC,CAAC;AA8BF;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,SAAS,EAAE,YAAoB,EAAE,mBAA2B,EAAE,gBAAwB,EAAE,kBAAuB,EAAE,EAAE,yBAAyB,2CAq8ClL"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/user_management/index.tsx"],"names":[],"mappings":"AA2DA,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,4DAA4D;IAC5D,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,cAAc,EAAE,CAAC;CACvC,CAAC;AA+BF;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,SAAS,EAAE,YAAoB,EAAE,mBAA2B,EAAE,gBAAwB,EAAE,kBAAuB,EAAE,EAAE,yBAAyB,2CA+nDlL"}
@@ -20,7 +20,8 @@ import { ScopeHierarchyTab } from "./components/scope_hierarchy_tab";
20
20
  import { ScopeLabelsTab } from "./components/scope_labels_tab";
21
21
  import { UserScopesTab } from "./components/user_scopes_tab";
22
22
  import { OrgHierarchyTab } from "./components/org_hierarchy_tab";
23
- import { UserX, KeyRound, Edit, Trash2, Loader2, CircleCheck, CircleX, Plus, UserPlus } from "lucide-react";
23
+ import { UserX, KeyRound, Edit, Trash2, Loader2, CircleCheck, CircleX, Plus, UserPlus, Building2 } from "lucide-react";
24
+ import { TreeView } from "../../ui/tree-view";
24
25
  import { toast } from "sonner";
25
26
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../../ui/tooltip";
26
27
  import { useHazoAuthConfig } from "../../../contexts/hazo_auth_provider";
@@ -75,6 +76,11 @@ export function UserManagementLayout({ className, hrbacEnabled = false, multiTen
75
76
  const [userTypeUpdateLoading, setUserTypeUpdateLoading] = useState(false);
76
77
  const [orgUpdateLoading, setOrgUpdateLoading] = useState(false);
77
78
  const [availableOrgs, setAvailableOrgs] = useState([]);
79
+ // Org assignment dialog state
80
+ const [orgAssignDialogOpen, setOrgAssignDialogOpen] = useState(false);
81
+ const [orgAssignUser, setOrgAssignUser] = useState(null);
82
+ const [selectedOrgForAssign, setSelectedOrgForAssign] = useState(null);
83
+ const [orgAssignLoading, setOrgAssignLoading] = useState(false);
78
84
  // Tab 3: Permissions state
79
85
  const [permissions, setPermissions] = useState([]);
80
86
  const [permissionsLoading, setPermissionsLoading] = useState(true);
@@ -127,6 +133,7 @@ export function UserManagementLayout({ className, hrbacEnabled = false, multiTen
127
133
  setAvailableOrgs(data.orgs.map((org) => ({
128
134
  id: org.id,
129
135
  name: org.name,
136
+ parent_org_id: org.parent_org_id,
130
137
  })));
131
138
  }
132
139
  }
@@ -327,6 +334,83 @@ export function UserManagementLayout({ className, hrbacEnabled = false, multiTen
327
334
  setOrgUpdateLoading(false);
328
335
  }
329
336
  };
337
+ // Build org tree from flat list for TreeView component
338
+ const buildOrgTree = (orgs) => {
339
+ // Create a map for quick lookup
340
+ const orgMap = new Map();
341
+ orgs.forEach((org) => {
342
+ orgMap.set(org.id, Object.assign(Object.assign({}, org), { children: [] }));
343
+ });
344
+ const rootNodes = [];
345
+ // Build tree structure
346
+ orgs.forEach((org) => {
347
+ const node = orgMap.get(org.id);
348
+ const treeItem = {
349
+ id: org.id,
350
+ name: org.name,
351
+ children: node.children.length > 0 ? node.children : undefined,
352
+ };
353
+ if (org.parent_org_id && orgMap.has(org.parent_org_id)) {
354
+ const parent = orgMap.get(org.parent_org_id);
355
+ parent.children.push(treeItem);
356
+ }
357
+ else {
358
+ rootNodes.push(treeItem);
359
+ }
360
+ });
361
+ // Update children in the tree
362
+ const updateChildren = (nodes) => {
363
+ return nodes.map((node) => {
364
+ const orgNode = orgMap.get(node.id);
365
+ if (orgNode && orgNode.children.length > 0) {
366
+ return Object.assign(Object.assign({}, node), { children: updateChildren(orgNode.children) });
367
+ }
368
+ return node;
369
+ });
370
+ };
371
+ return updateChildren(rootNodes);
372
+ };
373
+ // Handle org assignment from dialog
374
+ const handleOrgAssignFromDialog = async () => {
375
+ if (!orgAssignUser)
376
+ return;
377
+ setOrgAssignLoading(true);
378
+ try {
379
+ const orgIdValue = selectedOrgForAssign;
380
+ const response = await fetch(`${apiBasePath}/user_management/users`, {
381
+ method: "PATCH",
382
+ headers: {
383
+ "Content-Type": "application/json",
384
+ },
385
+ body: JSON.stringify({
386
+ user_id: orgAssignUser.id,
387
+ org_id: orgIdValue,
388
+ }),
389
+ });
390
+ const data = await response.json();
391
+ if (data.success) {
392
+ toast.success("Organization updated successfully");
393
+ setOrgAssignDialogOpen(false);
394
+ // Reload users list to get updated org info
395
+ await loadUsers();
396
+ }
397
+ else {
398
+ toast.error(data.error || "Failed to update organization");
399
+ }
400
+ }
401
+ catch (error) {
402
+ toast.error("Failed to update organization");
403
+ }
404
+ finally {
405
+ setOrgAssignLoading(false);
406
+ }
407
+ };
408
+ // Open org assignment dialog for a user
409
+ const openOrgAssignDialog = (user) => {
410
+ setOrgAssignUser(user);
411
+ setSelectedOrgForAssign(user.org_id);
412
+ setOrgAssignDialogOpen(true);
413
+ };
330
414
  // Handle migrate permissions
331
415
  const handleMigratePermissions = async () => {
332
416
  var _a, _b;
@@ -563,7 +647,7 @@ export function UserManagementLayout({ className, hrbacEnabled = false, multiTen
563
647
  })() })), _jsx(TableCell, { className: "cls_user_management_users_table_cell_actions text-right", children: _jsx(TooltipProvider, { children: _jsxs("div", { className: "cls_user_management_users_table_actions flex items-center justify-end gap-2", onClick: (e) => e.stopPropagation(), children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { onClick: () => {
564
648
  setSelectedUser(user);
565
649
  setAssignRolesDialogOpen(true);
566
- }, variant: "outline", size: "sm", className: "cls_user_management_users_table_action_assign_roles", children: _jsx(UserPlus, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: _jsx("p", { children: "Assign Roles" }) })] }), user.is_active && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { onClick: () => {
650
+ }, variant: "outline", size: "sm", className: "cls_user_management_users_table_action_assign_roles", children: _jsx(UserPlus, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: _jsx("p", { children: "Assign Roles" }) })] }), multiTenancyEnabled && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { onClick: () => openOrgAssignDialog(user), variant: "outline", size: "sm", className: "cls_user_management_users_table_action_assign_org", children: _jsx(Building2, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: _jsx("p", { children: "Assign Organization" }) })] })), user.is_active && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { onClick: () => {
567
651
  setSelectedUser(user);
568
652
  setDeactivateDialogOpen(true);
569
653
  }, variant: "outline", size: "sm", className: "cls_user_management_users_table_action_deactivate", children: _jsx(UserX, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: _jsx("p", { children: "Deactivate" }) })] })), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { onClick: () => {
@@ -600,7 +684,7 @@ export function UserManagementLayout({ className, hrbacEnabled = false, multiTen
600
684
  setAddPermissionDialogOpen(false);
601
685
  setNewPermissionName("");
602
686
  setNewPermissionDescription("");
603
- }, variant: "outline", className: "cls_user_management_add_permission_dialog_cancel", children: [_jsx(CircleX, { className: "h-4 w-4 mr-2" }), "Cancel"] })] })] }) }), _jsx(Dialog, { open: userDetailDialogOpen, onOpenChange: setUserDetailDialogOpen, children: _jsxs(DialogContent, { className: "cls_user_management_user_detail_dialog max-w-2xl", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "User Details" }), _jsxs(DialogDescription, { children: ["Complete information for ", (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name) || (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.email_address)] })] }), _jsx("div", { className: "cls_user_management_user_detail_dialog_content flex flex-col gap-4 py-4", children: selectedUser && (_jsxs("div", { className: "cls_user_management_user_detail_fields grid grid-cols-1 gap-4", children: [_jsxs("div", { className: "cls_user_management_user_detail_field_profile_pic flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Profile Picture" }), _jsxs("div", { className: "cls_user_management_user_detail_profile_pic_container flex items-center gap-4", children: [_jsxs(Avatar, { className: "cls_user_management_user_detail_avatar h-16 w-16", children: [_jsx(AvatarImage, { src: selectedUser.profile_picture_url || undefined, alt: selectedUser.name ? `Profile picture of ${selectedUser.name}` : "Profile picture", className: "cls_user_management_user_detail_avatar_image" }), _jsx(AvatarFallback, { className: "cls_user_management_user_detail_avatar_fallback bg-slate-200 text-slate-600 text-lg", children: getUserInitials(selectedUser) })] }), _jsxs("div", { className: "cls_user_management_user_detail_profile_pic_info flex flex-col gap-1", children: [_jsx("span", { className: "cls_user_management_user_detail_profile_pic_url text-sm text-muted-foreground", children: selectedUser.profile_picture_url || "No profile picture" }), _jsxs("span", { className: "cls_user_management_user_detail_profile_pic_source text-xs text-muted-foreground", children: ["Source: ", selectedUser.profile_source || "N/A"] })] })] })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_id flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "User ID" }), _jsx("div", { className: "cls_user_management_user_detail_id_value font-mono text-sm bg-muted p-2 rounded", children: selectedUser.id })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_name flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Name" }), _jsx("div", { className: "cls_user_management_user_detail_name_value text-sm", children: selectedUser.name || "-" })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_email flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Email Address" }), _jsx("div", { className: "cls_user_management_user_detail_email_value text-sm", children: selectedUser.email_address })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_email_verified flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Email Verified" }), _jsx("div", { className: "cls_user_management_user_detail_email_verified_value", children: selectedUser.email_verified ? (_jsx("span", { className: "text-green-600 font-medium", children: "Yes" })) : (_jsx("span", { className: "text-red-600 font-medium", children: "No" })) })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_is_active flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Active Status" }), _jsx("div", { className: "cls_user_management_user_detail_is_active_value", children: selectedUser.is_active ? (_jsx("span", { className: "text-green-600 font-medium", children: "Active" })) : (_jsx("span", { className: "text-red-600 font-medium", children: "Inactive" })) })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_last_logon flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Last Logon" }), _jsx("div", { className: "cls_user_management_user_detail_last_logon_value text-sm", children: selectedUser.last_logon ? (_jsx("span", { className: "font-medium", children: new Date(selectedUser.last_logon).toLocaleString(undefined, {
687
+ }, variant: "outline", className: "cls_user_management_add_permission_dialog_cancel", children: [_jsx(CircleX, { className: "h-4 w-4 mr-2" }), "Cancel"] })] })] }) }), _jsx(Dialog, { open: userDetailDialogOpen, onOpenChange: setUserDetailDialogOpen, children: _jsxs(DialogContent, { className: "cls_user_management_user_detail_dialog max-w-2xl max-h-[80vh] overflow-y-auto", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "User Details" }), _jsxs(DialogDescription, { children: ["Complete information for ", (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name) || (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.email_address)] })] }), _jsx("div", { className: "cls_user_management_user_detail_dialog_content flex flex-col gap-4 py-4", children: selectedUser && (_jsxs("div", { className: "cls_user_management_user_detail_fields grid grid-cols-1 gap-4", children: [_jsxs("div", { className: "cls_user_management_user_detail_field_profile_pic flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Profile Picture" }), _jsxs("div", { className: "cls_user_management_user_detail_profile_pic_container flex items-center gap-4", children: [_jsxs(Avatar, { className: "cls_user_management_user_detail_avatar h-16 w-16", children: [_jsx(AvatarImage, { src: selectedUser.profile_picture_url || undefined, alt: selectedUser.name ? `Profile picture of ${selectedUser.name}` : "Profile picture", className: "cls_user_management_user_detail_avatar_image" }), _jsx(AvatarFallback, { className: "cls_user_management_user_detail_avatar_fallback bg-slate-200 text-slate-600 text-lg", children: getUserInitials(selectedUser) })] }), _jsxs("div", { className: "cls_user_management_user_detail_profile_pic_info flex flex-col gap-1", children: [_jsx("span", { className: "cls_user_management_user_detail_profile_pic_url text-sm text-muted-foreground", children: selectedUser.profile_picture_url || "No profile picture" }), _jsxs("span", { className: "cls_user_management_user_detail_profile_pic_source text-xs text-muted-foreground", children: ["Source: ", selectedUser.profile_source || "N/A"] })] })] })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_id flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "User ID" }), _jsx("div", { className: "cls_user_management_user_detail_id_value font-mono text-sm bg-muted p-2 rounded", children: selectedUser.id })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_name flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Name" }), _jsx("div", { className: "cls_user_management_user_detail_name_value text-sm", children: selectedUser.name || "-" })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_email flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Email Address" }), _jsx("div", { className: "cls_user_management_user_detail_email_value text-sm", children: selectedUser.email_address })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_email_verified flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Email Verified" }), _jsx("div", { className: "cls_user_management_user_detail_email_verified_value", children: selectedUser.email_verified ? (_jsx("span", { className: "text-green-600 font-medium", children: "Yes" })) : (_jsx("span", { className: "text-red-600 font-medium", children: "No" })) })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_is_active flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Active Status" }), _jsx("div", { className: "cls_user_management_user_detail_is_active_value", children: selectedUser.is_active ? (_jsx("span", { className: "text-green-600 font-medium", children: "Active" })) : (_jsx("span", { className: "text-red-600 font-medium", children: "Inactive" })) })] }), _jsxs("div", { className: "cls_user_management_user_detail_field_last_logon flex flex-col gap-2", children: [_jsx(Label, { className: "cls_user_management_user_detail_label font-semibold", children: "Last Logon" }), _jsx("div", { className: "cls_user_management_user_detail_last_logon_value text-sm", children: selectedUser.last_logon ? (_jsx("span", { className: "font-medium", children: new Date(selectedUser.last_logon).toLocaleString(undefined, {
604
688
  year: "numeric",
605
689
  month: "long",
606
690
  day: "numeric",
@@ -626,5 +710,11 @@ export function UserManagementLayout({ className, hrbacEnabled = false, multiTen
626
710
  }, onCancel: () => {
627
711
  setAssignRolesDialogOpen(false);
628
712
  setSelectedUser(null);
629
- }, className: "cls_user_management_assign_roles_matrix" }) })] }) })] }));
713
+ }, className: "cls_user_management_assign_roles_matrix" }) })] }) }), _jsx(Dialog, { open: orgAssignDialogOpen, onOpenChange: setOrgAssignDialogOpen, children: _jsxs(DialogContent, { className: "cls_user_management_org_assign_dialog max-w-lg max-h-[80vh] flex flex-col", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Assign Organization" }), _jsxs(DialogDescription, { children: ["Select an organization for ", (orgAssignUser === null || orgAssignUser === void 0 ? void 0 : orgAssignUser.name) || (orgAssignUser === null || orgAssignUser === void 0 ? void 0 : orgAssignUser.email_address)] })] }), _jsxs("div", { className: "cls_user_management_org_assign_dialog_content flex-1 overflow-y-auto py-4 min-h-0", children: [_jsxs("div", { className: `cls_user_management_org_assign_none p-3 mb-2 rounded-lg border cursor-pointer transition-colors ${selectedOrgForAssign === null
714
+ ? "border-primary bg-primary/10"
715
+ : "border-border hover:bg-muted"}`, onClick: () => setSelectedOrgForAssign(null), children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CircleX, { className: "h-4 w-4 text-muted-foreground" }), _jsx("span", { className: "font-medium", children: "None" })] }), _jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Remove organization assignment" })] }), availableOrgs.length > 0 ? (_jsx("div", { className: "cls_user_management_org_assign_tree border rounded-lg overflow-auto min-h-[200px]", children: _jsx(TreeView, { data: buildOrgTree(availableOrgs), expandAll: true, defaultNodeIcon: Building2, defaultLeafIcon: Building2, onSelectChange: (item) => {
716
+ if (item) {
717
+ setSelectedOrgForAssign(item.id);
718
+ }
719
+ }, initialSelectedItemId: selectedOrgForAssign || undefined, className: "w-full p-2" }) })) : (_jsx("div", { className: "cls_user_management_org_assign_empty text-center py-8 text-muted-foreground", children: "No organizations available" }))] }), _jsxs(DialogFooter, { className: "cls_user_management_org_assign_dialog_footer", children: [_jsx(Button, { variant: "outline", onClick: () => setOrgAssignDialogOpen(false), disabled: orgAssignLoading, children: "Cancel" }), _jsx(Button, { onClick: handleOrgAssignFromDialog, disabled: orgAssignLoading, children: orgAssignLoading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Saving..."] })) : ("Save") })] })] }) })] }));
630
720
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_auth",
3
- "version": "4.5.3",
3
+ "version": "4.5.5",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",