hazo_auth 5.1.9 → 5.1.10

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.
@@ -5,8 +5,10 @@ export type AppUserDataEditorProps = {
5
5
  currentData: Record<string, unknown> | null;
6
6
  /** Callback when data is saved */
7
7
  onSave?: (newData: Record<string, unknown>) => void;
8
+ /** Callback when data is cleared */
9
+ onClear?: () => void;
8
10
  /** Whether the editor is read-only (no edit button) */
9
11
  readOnly?: boolean;
10
12
  };
11
- export declare function AppUserDataEditor({ userId, currentData, onSave, readOnly, }: AppUserDataEditorProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function AppUserDataEditor({ userId, currentData, onSave, onClear, readOnly, }: AppUserDataEditorProps): import("react/jsx-runtime").JSX.Element;
12
14
  //# sourceMappingURL=app_user_data_editor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app_user_data_editor.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/user_management/components/app_user_data_editor.tsx"],"names":[],"mappings":"AAmCA,MAAM,MAAM,sBAAsB,GAAG;IACnC,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,kCAAkC;IAClC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACpD,uDAAuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAgDF,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,WAAW,EACX,MAAM,EACN,QAAgB,GACjB,EAAE,sBAAsB,2CAwSxB"}
1
+ {"version":3,"file":"app_user_data_editor.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/user_management/components/app_user_data_editor.tsx"],"names":[],"mappings":"AA6CA,MAAM,MAAM,sBAAsB,GAAG;IACnC,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,kCAAkC;IAClC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACpD,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAgDF,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,WAAW,EACX,MAAM,EACN,OAAO,EACP,QAAgB,GACjB,EAAE,sBAAsB,2CAkXxB"}
@@ -2,14 +2,15 @@
2
2
  // Renders form fields based on JSON schema from config
3
3
  // section: client_directive
4
4
  "use client";
5
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
6
6
  // section: imports
7
7
  import { useState, useEffect, useCallback } from "react";
8
8
  import { Button } from "../../../ui/button.js";
9
9
  import { Input } from "../../../ui/input.js";
10
10
  import { Label } from "../../../ui/label.js";
11
11
  import { Switch } from "../../../ui/switch.js";
12
- import { ChevronDown, ChevronRight, Edit, Loader2, Save, X } from "lucide-react";
12
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "../../../ui/alert-dialog.js";
13
+ import { ChevronDown, ChevronRight, Edit, Loader2, Save, Trash2, X } from "lucide-react";
13
14
  import { toast } from "sonner";
14
15
  import { useHazoAuthConfig } from "../../../../contexts/hazo_auth_provider.js";
15
16
  // section: helpers
@@ -49,13 +50,15 @@ function setNestedValue(obj, path, value) {
49
50
  return result;
50
51
  }
51
52
  // section: component
52
- export function AppUserDataEditor({ userId, currentData, onSave, readOnly = false, }) {
53
+ export function AppUserDataEditor({ userId, currentData, onSave, onClear, readOnly = false, }) {
53
54
  const { apiBasePath } = useHazoAuthConfig();
54
55
  const [schemaResponse, setSchemaResponse] = useState(null);
55
56
  const [schemaLoading, setSchemaLoading] = useState(true);
56
57
  const [isEditing, setIsEditing] = useState(false);
57
58
  const [editData, setEditData] = useState({});
58
59
  const [saving, setSaving] = useState(false);
60
+ const [clearing, setClearing] = useState(false);
61
+ const [showClearConfirmation, setShowClearConfirmation] = useState(false);
59
62
  const [expandedSections, setExpandedSections] = useState(new Set());
60
63
  // Load schema on mount
61
64
  useEffect(() => {
@@ -121,6 +124,36 @@ export function AppUserDataEditor({ userId, currentData, onSave, readOnly = fals
121
124
  setSaving(false);
122
125
  }
123
126
  }, [apiBasePath, userId, editData, onSave]);
127
+ // Clear app_user_data - uses user_management/users PATCH endpoint with null
128
+ const handleClear = useCallback(async () => {
129
+ setClearing(true);
130
+ try {
131
+ const response = await fetch(`${apiBasePath}/user_management/users`, {
132
+ method: "PATCH",
133
+ headers: { "Content-Type": "application/json" },
134
+ body: JSON.stringify({
135
+ user_id: userId,
136
+ app_user_data: null,
137
+ }),
138
+ });
139
+ const data = await response.json();
140
+ if (data.success) {
141
+ toast.success("App user data cleared");
142
+ setShowClearConfirmation(false);
143
+ onClear === null || onClear === void 0 ? void 0 : onClear();
144
+ }
145
+ else {
146
+ toast.error(data.error || "Failed to clear");
147
+ }
148
+ }
149
+ catch (error) {
150
+ toast.error("Failed to clear app user data");
151
+ console.error("Clear error:", error);
152
+ }
153
+ finally {
154
+ setClearing(false);
155
+ }
156
+ }, [apiBasePath, userId, onClear]);
124
157
  // Update field value
125
158
  const updateField = useCallback((path, value) => {
126
159
  setEditData((prev) => setNestedValue(prev, path, value));
@@ -200,5 +233,5 @@ export function AppUserDataEditor({ userId, currentData, onSave, readOnly = fals
200
233
  return (_jsx("div", { className: "text-sm", children: currentData && Object.keys(currentData).length > 0 ? (_jsx("pre", { className: "border rounded-lg p-2 bg-slate-50 overflow-x-auto text-xs", children: JSON.stringify(currentData, null, 2) })) : (_jsx("span", { className: "text-muted-foreground", children: "No app user data" })) }));
201
234
  }
202
235
  // Render schema-based editor
203
- return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h3", { className: "text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: "App User Data" }), !readOnly && !isEditing && (_jsxs(Button, { variant: "outline", size: "sm", onClick: handleEdit, className: "h-8", children: [_jsx(Edit, { className: "h-3.5 w-3.5 mr-1.5" }), "Edit"] }))] }), _jsx("div", { className: "flex flex-col gap-3", children: Object.entries(schemaResponse.schema.properties).map(([sectionKey, sectionSchema]) => renderSection(sectionKey, sectionSchema)) }), isEditing && (_jsxs("div", { className: "flex justify-end gap-2 pt-3 border-t", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: handleCancel, disabled: saving, className: "h-9", children: [_jsx(X, { className: "h-4 w-4 mr-1.5" }), "Cancel"] }), _jsxs(Button, { size: "sm", onClick: handleSave, disabled: saving, className: "h-9", children: [saving ? (_jsx(Loader2, { className: "h-4 w-4 mr-1.5 animate-spin" })) : (_jsx(Save, { className: "h-4 w-4 mr-1.5" })), "Save"] })] }))] }));
236
+ return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h3", { className: "text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: "App User Data" }), !readOnly && !isEditing && (_jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: handleEdit, className: "h-8", children: [_jsx(Edit, { className: "h-3.5 w-3.5 mr-1.5" }), "Edit"] }), currentData && Object.keys(currentData).length > 0 && (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setShowClearConfirmation(true), className: "h-8 text-destructive hover:text-destructive hover:bg-destructive/10", children: [_jsx(Trash2, { className: "h-3.5 w-3.5 mr-1.5" }), "Clear"] }))] }))] }), _jsx("div", { className: "flex flex-col gap-3", children: Object.entries(schemaResponse.schema.properties).map(([sectionKey, sectionSchema]) => renderSection(sectionKey, sectionSchema)) }), isEditing && (_jsxs("div", { className: "flex justify-end gap-2 pt-3 border-t", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: handleCancel, disabled: saving, className: "h-9", children: [_jsx(X, { className: "h-4 w-4 mr-1.5" }), "Cancel"] }), _jsxs(Button, { size: "sm", onClick: handleSave, disabled: saving, className: "h-9", children: [saving ? (_jsx(Loader2, { className: "h-4 w-4 mr-1.5 animate-spin" })) : (_jsx(Save, { className: "h-4 w-4 mr-1.5" })), "Save"] })] })), _jsx(AlertDialog, { open: showClearConfirmation, onOpenChange: setShowClearConfirmation, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Clear App User Data?" }), _jsx(AlertDialogDescription, { children: "This will permanently delete all app user data for this user. This action cannot be undone." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: clearing, children: "Cancel" }), _jsx(AlertDialogAction, { onClick: handleClear, disabled: clearing, className: "bg-destructive text-destructive-foreground hover:bg-destructive/90", children: clearing ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 mr-1.5 animate-spin" }), "Clearing..."] })) : ("Clear Data") })] })] }) })] }));
204
237
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/user_management/index.tsx"],"names":[],"mappings":"AAyDA,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,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,cAAc,EAAE,CAAC;CACvC,CAAC;AAuJF;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,SAAS,EAAE,YAAoB,EAAE,gBAAwB,EAAE,kBAAuB,EAAE,EAAE,yBAAyB,2CAi2CrJ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/user_management/index.tsx"],"names":[],"mappings":"AAyDA,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,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,cAAc,EAAE,CAAC;CACvC,CAAC;AAuJF;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,SAAS,EAAE,YAAoB,EAAE,gBAAwB,EAAE,kBAAuB,EAAE,EAAE,yBAAyB,2CA82CrJ"}
@@ -582,6 +582,11 @@ export function UserManagementLayout({ className, hrbacEnabled = false, userType
582
582
  // Also update in the users list
583
583
  setUsers((prevUsers) => prevUsers.map((u) => u.id === selectedUser.id
584
584
  ? Object.assign(Object.assign({}, u), { app_user_data: newData }) : u));
585
+ }, onClear: () => {
586
+ // Clear app_user_data in both selectedUser and users list
587
+ setSelectedUser((prev) => prev ? Object.assign(Object.assign({}, prev), { app_user_data: null }) : null);
588
+ setUsers((prevUsers) => prevUsers.map((u) => u.id === selectedUser.id
589
+ ? Object.assign(Object.assign({}, u), { app_user_data: null }) : u));
585
590
  } }) }) })] })) }), _jsx(DialogFooter, { className: "cls_user_management_user_detail_dialog_footer", children: _jsx(Button, { onClick: () => setUserDetailDialogOpen(false), variant: "outline", className: "cls_user_management_user_detail_dialog_close", children: "Close" }) })] }) }), _jsx(Dialog, { open: assignRolesDialogOpen, onOpenChange: setAssignRolesDialogOpen, children: _jsxs(DialogContent, { className: "cls_user_management_assign_roles_dialog max-w-4xl max-h-[80vh] overflow-y-auto", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Assign Roles to User" }), _jsxs(DialogDescription, { children: ["Select roles to assign to ", (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name) || (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.email_address), ". Check the roles you want to assign, then click Save."] })] }), _jsx("div", { className: "cls_user_management_assign_roles_dialog_content py-4", children: _jsx(RolesMatrix, { add_button_enabled: false, role_name_selection_enabled: true, permissions_read_only: true, show_save_cancel: true, user_id: selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id, onSave: (data) => {
586
591
  // Data is already saved by RolesMatrix component
587
592
  console.log("User roles saved:", data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_auth",
3
- "version": "5.1.9",
3
+ "version": "5.1.10",
4
4
  "description": "Zero-config authentication UI components for Next.js with RBAC, OAuth, scope-based multi-tenancy, and invitations",
5
5
  "keywords": [
6
6
  "authentication",