@authhero/react-admin 0.10.0

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.
Files changed (110) hide show
  1. package/.eslintrc.js +21 -0
  2. package/.vercelignore +4 -0
  3. package/CHANGELOG.md +56 -0
  4. package/LICENSE +21 -0
  5. package/README.md +50 -0
  6. package/index.html +125 -0
  7. package/package.json +61 -0
  8. package/prettier.config.js +1 -0
  9. package/public/favicon.ico +0 -0
  10. package/public/manifest.json +15 -0
  11. package/src/App.spec.tsx +42 -0
  12. package/src/App.tsx +232 -0
  13. package/src/AuthCallback.tsx +138 -0
  14. package/src/Layout.tsx +12 -0
  15. package/src/TenantsApp.tsx +115 -0
  16. package/src/auth0DataProvider.ts +1242 -0
  17. package/src/authProvider.ts +521 -0
  18. package/src/components/CertificateErrorDialog.tsx +116 -0
  19. package/src/components/DomainSelector.tsx +401 -0
  20. package/src/components/TenantAppBar.tsx +83 -0
  21. package/src/components/TenantLayout.tsx +25 -0
  22. package/src/components/TenantsAppBar.tsx +21 -0
  23. package/src/components/TenantsLayout.tsx +28 -0
  24. package/src/components/activity/ActivityDashboard.tsx +381 -0
  25. package/src/components/activity/index.ts +1 -0
  26. package/src/components/branding/BrandingList.tsx +0 -0
  27. package/src/components/branding/BrandingShow.tsx +0 -0
  28. package/src/components/branding/ThemesTab.tsx +286 -0
  29. package/src/components/branding/edit.tsx +149 -0
  30. package/src/components/branding/hooks/useThemesData.ts +123 -0
  31. package/src/components/branding/index.ts +2 -0
  32. package/src/components/branding/list.tsx +12 -0
  33. package/src/components/clients/create.tsx +12 -0
  34. package/src/components/clients/edit.tsx +1285 -0
  35. package/src/components/clients/index.ts +3 -0
  36. package/src/components/clients/list.tsx +37 -0
  37. package/src/components/common/DateAgo.tsx +6 -0
  38. package/src/components/common/JsonOutput.tsx +26 -0
  39. package/src/components/common/index.ts +1 -0
  40. package/src/components/connections/create.tsx +35 -0
  41. package/src/components/connections/edit.tsx +212 -0
  42. package/src/components/connections/index.ts +3 -0
  43. package/src/components/connections/list.tsx +15 -0
  44. package/src/components/custom-domains/create.tsx +26 -0
  45. package/src/components/custom-domains/edit.tsx +101 -0
  46. package/src/components/custom-domains/index.ts +3 -0
  47. package/src/components/custom-domains/list.tsx +16 -0
  48. package/src/components/flows/create.tsx +30 -0
  49. package/src/components/flows/edit.tsx +238 -0
  50. package/src/components/flows/index.ts +3 -0
  51. package/src/components/flows/list.tsx +15 -0
  52. package/src/components/forms/FlowEditor.tsx +1363 -0
  53. package/src/components/forms/NodeEditor.tsx +1119 -0
  54. package/src/components/forms/RichTextEditor.tsx +145 -0
  55. package/src/components/forms/create.tsx +30 -0
  56. package/src/components/forms/edit.tsx +256 -0
  57. package/src/components/forms/index.ts +3 -0
  58. package/src/components/forms/list.tsx +16 -0
  59. package/src/components/hooks/create.tsx +96 -0
  60. package/src/components/hooks/edit.tsx +114 -0
  61. package/src/components/hooks/index.ts +3 -0
  62. package/src/components/hooks/list.tsx +17 -0
  63. package/src/components/listActions/PostListActions.tsx +10 -0
  64. package/src/components/logs/LogIcon.tsx +32 -0
  65. package/src/components/logs/LogShow.tsx +82 -0
  66. package/src/components/logs/LogType.tsx +38 -0
  67. package/src/components/logs/index.ts +4 -0
  68. package/src/components/logs/list.tsx +41 -0
  69. package/src/components/organizations/create.tsx +13 -0
  70. package/src/components/organizations/edit.tsx +682 -0
  71. package/src/components/organizations/index.ts +3 -0
  72. package/src/components/organizations/list.tsx +21 -0
  73. package/src/components/resource-servers/create.tsx +87 -0
  74. package/src/components/resource-servers/edit.tsx +121 -0
  75. package/src/components/resource-servers/index.ts +3 -0
  76. package/src/components/resource-servers/list.tsx +47 -0
  77. package/src/components/roles/create.tsx +12 -0
  78. package/src/components/roles/edit.tsx +426 -0
  79. package/src/components/roles/index.ts +3 -0
  80. package/src/components/roles/list.tsx +24 -0
  81. package/src/components/sessions/edit.tsx +101 -0
  82. package/src/components/sessions/index.ts +3 -0
  83. package/src/components/sessions/list.tsx +20 -0
  84. package/src/components/sessions/show.tsx +113 -0
  85. package/src/components/settings/edit.tsx +236 -0
  86. package/src/components/settings/index.ts +2 -0
  87. package/src/components/settings/list.tsx +14 -0
  88. package/src/components/tenants/create.tsx +20 -0
  89. package/src/components/tenants/edit.tsx +54 -0
  90. package/src/components/tenants/index.ts +2 -0
  91. package/src/components/tenants/list.tsx +67 -0
  92. package/src/components/themes/edit.tsx +200 -0
  93. package/src/components/themes/index.ts +2 -0
  94. package/src/components/themes/list.tsx +12 -0
  95. package/src/components/users/create.tsx +144 -0
  96. package/src/components/users/edit.tsx +1711 -0
  97. package/src/components/users/index.ts +3 -0
  98. package/src/components/users/list.tsx +35 -0
  99. package/src/data.json +121 -0
  100. package/src/dataProvider.ts +97 -0
  101. package/src/index.tsx +106 -0
  102. package/src/lib/logs.ts +21 -0
  103. package/src/types/reactflow.d.ts +86 -0
  104. package/src/utils/domainUtils.ts +169 -0
  105. package/src/utils/tokenUtils.ts +75 -0
  106. package/src/vite-env.d.ts +1 -0
  107. package/tsconfig.json +37 -0
  108. package/tsconfig.node.json +10 -0
  109. package/vercel.json +17 -0
  110. package/vite.config.ts +30 -0
@@ -0,0 +1,238 @@
1
+ import {
2
+ Edit,
3
+ SimpleForm,
4
+ TextInput,
5
+ required,
6
+ ArrayInput,
7
+ SimpleFormIterator,
8
+ SelectInput,
9
+ FormDataConsumer,
10
+ DateField,
11
+ Labeled,
12
+ BooleanInput,
13
+ } from "react-admin";
14
+ import { Typography, Box, Alert } from "@mui/material";
15
+
16
+ const ACTION_TYPE_CHOICES = [
17
+ { id: "REDIRECT", name: "Redirect" },
18
+ { id: "AUTH0", name: "Auth0" },
19
+ { id: "EMAIL", name: "Email" },
20
+ ];
21
+
22
+ const AUTH0_ACTION_CHOICES = [
23
+ { id: "UPDATE_USER", name: "Update User" },
24
+ { id: "CREATE_USER", name: "Create User" },
25
+ { id: "GET_USER", name: "Get User" },
26
+ { id: "SEND_REQUEST", name: "Send Request" },
27
+ { id: "SEND_EMAIL", name: "Send Email" },
28
+ ];
29
+
30
+ const EMAIL_ACTION_CHOICES = [{ id: "VERIFY_EMAIL", name: "Verify Email" }];
31
+
32
+ const REDIRECT_TARGET_CHOICES = [
33
+ {
34
+ id: "change-email",
35
+ name: "Change Email",
36
+ },
37
+ {
38
+ id: "account",
39
+ name: "Account Settings",
40
+ },
41
+ {
42
+ id: "custom",
43
+ name: "Custom URL",
44
+ },
45
+ ];
46
+
47
+ // Generate Auth0-style action IDs like "verify_email_address_YrOx"
48
+ const generateActionId = (type: string, action?: string) => {
49
+ const suffix = Math.random().toString(36).substring(2, 6);
50
+
51
+ if (type === "REDIRECT") {
52
+ return `redirect_user_${suffix}`;
53
+ }
54
+ if (type === "EMAIL" && action === "VERIFY_EMAIL") {
55
+ return `verify_email_address_${suffix}`;
56
+ }
57
+ if (type === "AUTH0") {
58
+ const actionName = (action || "action").toLowerCase();
59
+ return `${actionName}_${suffix}`;
60
+ }
61
+
62
+ return `action_${suffix}`;
63
+ };
64
+
65
+ // Parse function to extract params into form fields when loading
66
+ const parseFlowData = (data: Record<string, unknown>) => {
67
+ if (data.actions && Array.isArray(data.actions)) {
68
+ data.actions = data.actions.map((action: Record<string, unknown>) => {
69
+ const parsed = { ...action };
70
+
71
+ // Extract REDIRECT params into form fields
72
+ if (parsed.type === "REDIRECT" && parsed.params) {
73
+ const params = parsed.params as Record<string, unknown>;
74
+ if (params.target) {
75
+ parsed.redirect_target = params.target;
76
+ }
77
+ if (params.custom_url) {
78
+ parsed.redirect_custom_url = params.custom_url;
79
+ }
80
+ }
81
+
82
+ return parsed;
83
+ });
84
+ }
85
+ return data;
86
+ };
87
+
88
+ export const FlowEdit = () => {
89
+ return (
90
+ <Edit
91
+ queryOptions={{
92
+ select: (data) => ({
93
+ data: parseFlowData(data.data as Record<string, unknown>),
94
+ }),
95
+ }}
96
+ transform={(data: Record<string, unknown>) => {
97
+ // Transform actions to include required fields
98
+ if (data.actions && Array.isArray(data.actions)) {
99
+ data.actions = data.actions.map((action: Record<string, unknown>) => {
100
+ const transformed = { ...action };
101
+
102
+ // Remove any nested actions array (form bug workaround)
103
+ delete transformed.actions;
104
+
105
+ // Add action type for REDIRECT
106
+ if (transformed.type === "REDIRECT") {
107
+ transformed.action = "REDIRECT_USER";
108
+ // Build params with target and optional custom_url
109
+ // Prioritize form fields over existing params (user edits should take effect)
110
+ const target =
111
+ (transformed.redirect_target as string) ||
112
+ (transformed.params as Record<string, unknown>)?.target ||
113
+ "change-email";
114
+ const params: Record<string, unknown> = { target };
115
+
116
+ // Include custom_url when target is "custom"
117
+ if (target === "custom") {
118
+ const customUrl =
119
+ (transformed.redirect_custom_url as string) ||
120
+ (transformed.params as Record<string, unknown>)?.custom_url;
121
+ if (customUrl) {
122
+ params.custom_url = customUrl;
123
+ }
124
+ }
125
+
126
+ transformed.params = params;
127
+ // Clean up temporary fields
128
+ delete transformed.redirect_target;
129
+ delete transformed.redirect_custom_url;
130
+ }
131
+
132
+ // Auto-generate ID if not provided (Auth0-style)
133
+ if (!transformed.id) {
134
+ transformed.id = generateActionId(
135
+ transformed.type as string,
136
+ transformed.action as string | undefined,
137
+ );
138
+ }
139
+
140
+ return transformed;
141
+ });
142
+ }
143
+ return data;
144
+ }}
145
+ >
146
+ <SimpleForm>
147
+ <TextInput source="name" validate={[required()]} fullWidth />
148
+
149
+ <Box sx={{ mt: 3, mb: 2 }}>
150
+ <Typography variant="h6">Actions</Typography>
151
+ <Typography variant="body2" color="text.secondary">
152
+ Define the sequence of actions to execute in this flow.
153
+ </Typography>
154
+ </Box>
155
+
156
+ <Alert severity="info" sx={{ mb: 2 }}>
157
+ <strong>Quick Tip:</strong> To redirect users to the change email
158
+ page, add a REDIRECT action with target "Change Email".
159
+ </Alert>
160
+
161
+ <ArrayInput source="actions">
162
+ <SimpleFormIterator inline>
163
+ <SelectInput
164
+ source="type"
165
+ label="Type"
166
+ choices={ACTION_TYPE_CHOICES}
167
+ validate={[required()]}
168
+ defaultValue="REDIRECT"
169
+ />
170
+
171
+ <FormDataConsumer>
172
+ {({ scopedFormData }) => {
173
+ if (scopedFormData?.type === "AUTH0") {
174
+ return (
175
+ <SelectInput
176
+ source="action"
177
+ label="Action"
178
+ choices={AUTH0_ACTION_CHOICES}
179
+ validate={[required()]}
180
+ />
181
+ );
182
+ }
183
+
184
+ if (scopedFormData?.type === "EMAIL") {
185
+ return (
186
+ <SelectInput
187
+ source="action"
188
+ label="Action"
189
+ choices={EMAIL_ACTION_CHOICES}
190
+ validate={[required()]}
191
+ />
192
+ );
193
+ }
194
+
195
+ if (scopedFormData?.type === "REDIRECT") {
196
+ return (
197
+ <Box sx={{ display: "flex", gap: 2, flexWrap: "wrap" }}>
198
+ <SelectInput
199
+ source="redirect_target"
200
+ label="Redirect To"
201
+ choices={REDIRECT_TARGET_CHOICES}
202
+ validate={[required()]}
203
+ helperText="Select where to redirect the user"
204
+ defaultValue="change-email"
205
+ />
206
+ {scopedFormData?.redirect_target === "custom" && (
207
+ <TextInput
208
+ source="redirect_custom_url"
209
+ label="Custom URL"
210
+ validate={[required()]}
211
+ helperText="Enter the full URL to redirect to"
212
+ fullWidth
213
+ />
214
+ )}
215
+ </Box>
216
+ );
217
+ }
218
+
219
+ return null;
220
+ }}
221
+ </FormDataConsumer>
222
+
223
+ <BooleanInput source="allow_failure" label="Allow Failure" />
224
+ </SimpleFormIterator>
225
+ </ArrayInput>
226
+
227
+ <Box sx={{ mt: 3 }}>
228
+ <Labeled label="Created At">
229
+ <DateField source="created_at" showTime={true} />
230
+ </Labeled>
231
+ <Labeled label="Updated At">
232
+ <DateField source="updated_at" showTime={true} />
233
+ </Labeled>
234
+ </Box>
235
+ </SimpleForm>
236
+ </Edit>
237
+ );
238
+ };
@@ -0,0 +1,3 @@
1
+ export { FlowCreate } from "./create";
2
+ export { FlowsList } from "./list";
3
+ export { FlowEdit } from "./edit";
@@ -0,0 +1,15 @@
1
+ import { List, Datagrid, TextField, DateField } from "react-admin";
2
+ import { PostListActions } from "../listActions/PostListActions";
3
+
4
+ export const FlowsList = () => {
5
+ return (
6
+ <List actions={<PostListActions />}>
7
+ <Datagrid rowClick="edit" bulkActionButtons={false}>
8
+ <TextField source="id" />
9
+ <TextField source="name" />
10
+ <DateField source="created_at" showTime={true} />
11
+ <DateField source="updated_at" showTime={true} />
12
+ </Datagrid>
13
+ </List>
14
+ );
15
+ };