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":"
|
|
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
|
}
|