@solidxai/core-ui 0.1.7-beta.6 → 0.1.7-beta.7

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 (100) hide show
  1. package/dist/components/auth/SolidOTPVerify.d.ts +3 -0
  2. package/dist/components/auth/SolidOTPVerify.d.ts.map +1 -0
  3. package/dist/components/auth/SolidOTPVerify.js +67 -0
  4. package/dist/components/auth/SolidOTPVerify.js.map +1 -0
  5. package/dist/components/auth/SolidOTPVerify.tsx +133 -0
  6. package/dist/components/common/AuthBanner.js.map +1 -1
  7. package/dist/components/core/common/LoadDynamicJsxComponent.d.ts +2 -0
  8. package/dist/components/core/common/LoadDynamicJsxComponent.d.ts.map +1 -0
  9. package/dist/components/core/common/LoadDynamicJsxComponent.js +50 -0
  10. package/dist/components/core/common/LoadDynamicJsxComponent.js.map +1 -0
  11. package/dist/components/core/common/LoadDynamicJsxComponent.tsx +70 -0
  12. package/dist/components/core/kanban/SolidManyToOneFilterElement.d.ts.map +1 -1
  13. package/dist/components/core/kanban/SolidManyToOneFilterElement.js.map +1 -1
  14. package/dist/components/core/kanban/SolidManyToOneFilterElement.tsx +2 -1
  15. package/dist/components/core/kanban/kanban-fields/SolidMediaMultipleKanbanField.d.ts.map +1 -1
  16. package/dist/components/core/kanban/kanban-fields/SolidMediaMultipleKanbanField.js +2 -2
  17. package/dist/components/core/kanban/kanban-fields/SolidMediaMultipleKanbanField.js.map +1 -1
  18. package/dist/components/core/kanban/kanban-fields/SolidMediaMultipleKanbanField.tsx +10 -21
  19. package/dist/components/core/kanban/kanban-fields/SolidMediaSingleKanbanField.d.ts.map +1 -1
  20. package/dist/components/core/kanban/kanban-fields/SolidMediaSingleKanbanField.js +2 -2
  21. package/dist/components/core/kanban/kanban-fields/SolidMediaSingleKanbanField.js.map +1 -1
  22. package/dist/components/core/kanban/kanban-fields/SolidMediaSingleKanbanField.tsx +10 -18
  23. package/dist/components/core/kanban/kanban-fields/SolidShortTextKanbanField.d.ts.map +1 -1
  24. package/dist/components/core/kanban/kanban-fields/SolidShortTextKanbanField.js +6 -3
  25. package/dist/components/core/kanban/kanban-fields/SolidShortTextKanbanField.js.map +1 -1
  26. package/dist/components/core/kanban/kanban-fields/SolidShortTextKanbanField.tsx +24 -30
  27. package/dist/components/core/kanban/kanban-fields/relations/SolidRelationManyToOneKanbanField.js.map +1 -1
  28. package/dist/components/core/kanban/kanban-fields/relations/SolidRelationManyToOneKanbanField.tsx +2 -2
  29. package/dist/components/core/list/SolidListViewRowButtonContextMenu.d.ts +1 -1
  30. package/dist/components/core/list/SolidListViewRowButtonContextMenu.d.ts.map +1 -1
  31. package/dist/components/core/list/SolidListViewRowButtonContextMenu.js +7 -6
  32. package/dist/components/core/list/SolidListViewRowButtonContextMenu.js.map +1 -1
  33. package/dist/components/core/list/SolidListViewRowButtonContextMenu.tsx +10 -9
  34. package/dist/components/core/users/ApiKeysTab/ApiKeysTab.d.ts +7 -0
  35. package/dist/components/core/users/ApiKeysTab/ApiKeysTab.d.ts.map +1 -0
  36. package/dist/components/core/users/ApiKeysTab/ApiKeysTab.js +138 -0
  37. package/dist/components/core/users/ApiKeysTab/ApiKeysTab.js.map +1 -0
  38. package/dist/components/core/users/ApiKeysTab/ApiKeysTab.tsx +246 -0
  39. package/dist/components/core/users/ApiKeysTab/GenerateApiKeyModal.d.ts +8 -0
  40. package/dist/components/core/users/ApiKeysTab/GenerateApiKeyModal.d.ts.map +1 -0
  41. package/dist/components/core/users/ApiKeysTab/GenerateApiKeyModal.js +156 -0
  42. package/dist/components/core/users/ApiKeysTab/GenerateApiKeyModal.js.map +1 -0
  43. package/dist/components/core/users/ApiKeysTab/GenerateApiKeyModal.tsx +184 -0
  44. package/dist/components/core/users/ApiKeysTab/RevealApiKeyModal.d.ts +9 -0
  45. package/dist/components/core/users/ApiKeysTab/RevealApiKeyModal.d.ts.map +1 -0
  46. package/dist/components/core/users/ApiKeysTab/RevealApiKeyModal.js +37 -0
  47. package/dist/components/core/users/ApiKeysTab/RevealApiKeyModal.js.map +1 -0
  48. package/dist/components/core/users/ApiKeysTab/RevealApiKeyModal.tsx +111 -0
  49. package/dist/components/core/users/ApiKeysTab/index.d.ts +4 -0
  50. package/dist/components/core/users/ApiKeysTab/index.d.ts.map +1 -0
  51. package/dist/components/core/users/ApiKeysTab/index.js +4 -0
  52. package/dist/components/core/users/ApiKeysTab/index.js.map +1 -0
  53. package/dist/components/core/users/ApiKeysTab/index.ts +3 -0
  54. package/dist/helpers/# no such endpoints exist, need to calle +3 -0
  55. package/dist/nextAuth/authProviders.d.ts +4 -0
  56. package/dist/nextAuth/authProviders.d.ts.map +1 -0
  57. package/dist/nextAuth/authProviders.js +198 -0
  58. package/dist/nextAuth/authProviders.js.map +1 -0
  59. package/dist/nextAuth/authProviders.tsx +232 -0
  60. package/dist/nextAuth/handleLogout.d.ts +2 -0
  61. package/dist/nextAuth/handleLogout.d.ts.map +1 -0
  62. package/dist/nextAuth/handleLogout.js +36 -0
  63. package/dist/nextAuth/handleLogout.js.map +1 -0
  64. package/dist/nextAuth/handleLogout.tsx +39 -0
  65. package/dist/nextAuth/refreshAccessToken.d.ts +2 -0
  66. package/dist/nextAuth/refreshAccessToken.d.ts.map +1 -0
  67. package/dist/nextAuth/refreshAccessToken.js +24 -0
  68. package/dist/nextAuth/refreshAccessToken.js.map +1 -0
  69. package/dist/nextAuth/refreshAccessToken.tsx +28 -0
  70. package/dist/redux/api/apiKeyApi.d.ts +40 -0
  71. package/dist/redux/api/apiKeyApi.d.ts.map +1 -0
  72. package/dist/redux/api/apiKeyApi.js +36 -0
  73. package/dist/redux/api/apiKeyApi.js.map +1 -0
  74. package/dist/redux/api/apiKeyApi.ts +60 -0
  75. package/dist/redux/features/settingsSlice.d.ts +20 -0
  76. package/dist/redux/features/settingsSlice.d.ts.map +1 -0
  77. package/dist/redux/features/settingsSlice.js +39 -0
  78. package/dist/redux/features/settingsSlice.js.map +1 -0
  79. package/dist/redux/features/settingsSlice.ts +60 -0
  80. package/package.json +1 -1
  81. package/dist/components/core/list/SolidDataTablePagination.d.ts +0 -15
  82. package/dist/components/core/list/SolidDataTablePagination.d.ts.map +0 -1
  83. package/dist/components/core/list/SolidDataTablePagination.js +0 -22
  84. package/dist/components/core/list/SolidDataTablePagination.js.map +0 -1
  85. package/dist/components/core/list/SolidDataTablePagination.tsx +0 -71
  86. package/dist/components/solid-ui/SolidButton.d.ts +0 -14
  87. package/dist/components/solid-ui/SolidButton.d.ts.map +0 -1
  88. package/dist/components/solid-ui/SolidButton.js +0 -36
  89. package/dist/components/solid-ui/SolidButton.js.map +0 -1
  90. package/dist/components/solid-ui/SolidButton.tsx +0 -54
  91. package/dist/components/solid-ui/SolidTabs.d.ts +0 -18
  92. package/dist/components/solid-ui/SolidTabs.d.ts.map +0 -1
  93. package/dist/components/solid-ui/SolidTabs.js +0 -22
  94. package/dist/components/solid-ui/SolidTabs.js.map +0 -1
  95. package/dist/components/solid-ui/SolidTabs.tsx +0 -73
  96. package/dist/components/solid-ui/index.d.ts +0 -3
  97. package/dist/components/solid-ui/index.d.ts.map +0 -1
  98. package/dist/components/solid-ui/index.js +0 -3
  99. package/dist/components/solid-ui/index.js.map +0 -1
  100. package/dist/components/solid-ui/index.ts +0 -2
@@ -0,0 +1,184 @@
1
+ import { useEffect, useState } from "react";
2
+ import { useDispatch } from "react-redux";
3
+ import { useFormik } from "formik";
4
+ import * as Yup from "yup";
5
+ import {
6
+ SolidButton,
7
+ SolidDatePicker,
8
+ SolidDialog,
9
+ SolidDialogBody,
10
+ SolidDialogFooter,
11
+ SolidDialogHeader,
12
+ SolidDialogSeparator,
13
+ SolidDialogTitle,
14
+ SolidInput,
15
+ SolidMessage,
16
+ SolidSelect,
17
+ } from "../../../shad-cn-ui";
18
+ import { showToast } from "../../../../redux/features/toastSlice";
19
+ import { useCreateApiKeyMutation } from "../../../../redux/api/apiKeyApi";
20
+
21
+ const EXPIRY_OPTIONS = [
22
+ { label: "30 days", value: "30d" },
23
+ { label: "60 days", value: "60d" },
24
+ { label: "90 days", value: "90d" },
25
+ { label: "Never", value: "never" },
26
+ { label: "Custom date", value: "custom" },
27
+ ];
28
+
29
+ function addDays(days: number): string {
30
+ const d = new Date();
31
+ d.setDate(d.getDate() + days);
32
+ return d.toISOString();
33
+ }
34
+
35
+ function resolveExpiresAt(expiryOption: string, customDate: Date | null): string | undefined {
36
+ switch (expiryOption) {
37
+ case "30d":
38
+ return addDays(30);
39
+ case "60d":
40
+ return addDays(60);
41
+ case "90d":
42
+ return addDays(90);
43
+ case "never":
44
+ return undefined;
45
+ case "custom":
46
+ return customDate ? customDate.toISOString() : undefined;
47
+ default:
48
+ return undefined;
49
+ }
50
+ }
51
+
52
+ interface GenerateApiKeyModalProps {
53
+ open: boolean;
54
+ onClose: () => void;
55
+ onCreated: (rawApiKey: string, keyName: string) => void;
56
+ }
57
+
58
+ export function GenerateApiKeyModal({ open, onClose, onCreated }: GenerateApiKeyModalProps) {
59
+ const dispatch = useDispatch();
60
+ const [createApiKey, { isLoading }] = useCreateApiKeyMutation();
61
+ const [customDate, setCustomDate] = useState<Date | null>(null);
62
+
63
+ const formik = useFormik({
64
+ initialValues: {
65
+ name: "",
66
+ expiryOption: "30d",
67
+ },
68
+ validationSchema: Yup.object({
69
+ name: Yup.string()
70
+ .trim()
71
+ .min(2, "Name must be at least 2 characters")
72
+ .max(64, "Name must be 64 characters or fewer")
73
+ .required("Key name is required"),
74
+ expiryOption: Yup.string().required("Expiry is required"),
75
+ }),
76
+ onSubmit: async (values, helpers) => {
77
+ if (values.expiryOption === "custom" && !customDate) {
78
+ helpers.setFieldError("expiryOption", "Please select a custom expiry date");
79
+ return;
80
+ }
81
+
82
+ const expiresAt = resolveExpiresAt(values.expiryOption, customDate);
83
+
84
+ try {
85
+ const response = await createApiKey({
86
+ name: values.name.trim(),
87
+ ...(expiresAt ? { expiresAt } : {}),
88
+ }).unwrap();
89
+
90
+ onCreated(response.data.apiKey, values.name.trim());
91
+ handleClose();
92
+ } catch (err: any) {
93
+ const detail = err?.data?.message || "Failed to generate API key. Please try again.";
94
+ dispatch(showToast({ severity: "error", summary: "Error", detail }));
95
+ }
96
+ },
97
+ });
98
+
99
+ const handleClose = () => {
100
+ formik.resetForm();
101
+ setCustomDate(null);
102
+ onClose();
103
+ };
104
+
105
+ // Reset form when modal opens
106
+ useEffect(() => {
107
+ if (open) {
108
+ formik.resetForm();
109
+ setCustomDate(null);
110
+ }
111
+ }, [open]);
112
+
113
+ const nameError =
114
+ formik.touched.name && formik.errors.name ? String(formik.errors.name) : "";
115
+ const expiryError =
116
+ formik.touched.expiryOption && formik.errors.expiryOption
117
+ ? String(formik.errors.expiryOption)
118
+ : "";
119
+
120
+ return (
121
+ <SolidDialog open={open} onOpenChange={handleClose} style={{ maxWidth: 480 }}>
122
+ <SolidDialogHeader>
123
+ <SolidDialogTitle>Generate API Key</SolidDialogTitle>
124
+ </SolidDialogHeader>
125
+ <SolidDialogSeparator />
126
+ <SolidDialogBody>
127
+ <form id="generate-api-key-form" onSubmit={formik.handleSubmit}>
128
+ <div className="flex flex-column gap-3">
129
+ <div className="flex flex-column gap-2">
130
+ <label htmlFor="api-key-name" className="form-field-label">
131
+ Key Name <span style={{ color: "var(--solid-danger-color, #ef4444)" }}>*</span>
132
+ </label>
133
+ <SolidInput
134
+ id="api-key-name"
135
+ name="name"
136
+ autoComplete="off"
137
+ placeholder="e.g. CI/CD pipeline, Mobile app"
138
+ value={formik.values.name}
139
+ onChange={formik.handleChange}
140
+ onBlur={formik.handleBlur}
141
+ />
142
+ {nameError && <SolidMessage severity="error" text={nameError} />}
143
+ </div>
144
+
145
+ <div className="flex flex-column gap-2">
146
+ <label htmlFor="api-key-expiry" className="form-field-label">
147
+ Expires
148
+ </label>
149
+ <SolidSelect
150
+ value={formik.values.expiryOption}
151
+ options={EXPIRY_OPTIONS}
152
+ optionLabel="label"
153
+ optionValue="value"
154
+ onChange={({ value }) => {
155
+ formik.setFieldValue("expiryOption", value);
156
+ if (value !== "custom") setCustomDate(null);
157
+ }}
158
+ />
159
+ {formik.values.expiryOption === "custom" && (
160
+ <SolidDatePicker
161
+ selected={customDate}
162
+ onChange={(date: Date | null) => setCustomDate(date)}
163
+ minDate={new Date()}
164
+ placeholderText="Select expiry date"
165
+ dateFormat="dd/MM/yyyy"
166
+ />
167
+ )}
168
+ {expiryError && <SolidMessage severity="error" text={expiryError} />}
169
+ </div>
170
+ </div>
171
+ </form>
172
+ </SolidDialogBody>
173
+ <SolidDialogSeparator />
174
+ <SolidDialogFooter>
175
+ <SolidButton variant="outline" type="button" onClick={handleClose} disabled={isLoading}>
176
+ Cancel
177
+ </SolidButton>
178
+ <SolidButton type="submit" form="generate-api-key-form" loading={isLoading}>
179
+ Generate Key
180
+ </SolidButton>
181
+ </SolidDialogFooter>
182
+ </SolidDialog>
183
+ );
184
+ }
@@ -0,0 +1,9 @@
1
+ interface RevealApiKeyModalProps {
2
+ open: boolean;
3
+ apiKey: string;
4
+ keyName: string;
5
+ onClose: () => void;
6
+ }
7
+ export declare function RevealApiKeyModal({ open, apiKey, keyName, onClose }: RevealApiKeyModalProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=RevealApiKeyModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RevealApiKeyModal.d.ts","sourceRoot":"","sources":["../../../../../src/components/core/users/ApiKeysTab/RevealApiKeyModal.tsx"],"names":[],"mappings":"AAYA,UAAU,sBAAsB;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,sBAAsB,2CA2F3F"}
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { AlertTriangle, CheckCircle, Copy } from "lucide-react";
4
+ import { SolidButton, SolidDialog, SolidDialogBody, SolidDialogFooter, SolidDialogHeader, SolidDialogSeparator, SolidDialogTitle, } from "../../../shad-cn-ui";
5
+ export function RevealApiKeyModal(_a) {
6
+ var open = _a.open, apiKey = _a.apiKey, keyName = _a.keyName, onClose = _a.onClose;
7
+ var _b = useState(false), copied = _b[0], setCopied = _b[1];
8
+ var handleCopy = function () {
9
+ navigator.clipboard.writeText(apiKey).then(function () {
10
+ setCopied(true);
11
+ setTimeout(function () { return setCopied(false); }, 3000);
12
+ });
13
+ };
14
+ var handleClose = function () {
15
+ setCopied(false);
16
+ onClose();
17
+ };
18
+ return (_jsxs(SolidDialog, { open: open, onOpenChange: handleClose, dismissible: false, style: { maxWidth: 520 }, children: [_jsx(SolidDialogHeader, { children: _jsx(SolidDialogTitle, { children: "API Key Created" }) }), _jsx(SolidDialogSeparator, {}), _jsxs(SolidDialogBody, { children: [_jsxs("div", { className: "solid-api-key-reveal-warning flex align-items-start gap-2 mb-4", children: [_jsx(AlertTriangle, { size: 16, className: "flex-shrink-0 mt-1" }), _jsxs("p", { className: "m-0", style: { fontSize: 13 }, children: [_jsx("strong", { children: "Copy this key now." }), " It will not be shown again once you close this dialog. Store it somewhere secure."] })] }), _jsx("p", { className: "form-field-label mb-2", children: keyName }), _jsxs("div", { className: "solid-api-key-reveal-box flex align-items-center gap-2 p-3", style: {
19
+ background: "var(--solid-surface-secondary, #f5f5f5)",
20
+ borderRadius: 6,
21
+ border: "1px solid var(--solid-border-color, #e0e0e0)",
22
+ }, children: [_jsx("code", { className: "flex-1", style: {
23
+ fontFamily: "monospace",
24
+ fontSize: 13,
25
+ wordBreak: "break-all",
26
+ userSelect: "all",
27
+ }, children: apiKey }), _jsx("button", { type: "button", title: copied ? "Copied!" : "Copy to clipboard", onClick: handleCopy, style: {
28
+ background: "none",
29
+ border: "none",
30
+ cursor: "pointer",
31
+ padding: "4px",
32
+ display: "flex",
33
+ alignItems: "center",
34
+ flexShrink: 0,
35
+ }, children: copied ? (_jsx(CheckCircle, { size: 16, style: { color: "var(--solid-success-color, #22c55e)" } })) : (_jsx(Copy, { size: 16 })) })] }), copied && (_jsx("p", { className: "m-0 mt-2", style: { fontSize: 12, color: "var(--solid-success-color, #22c55e)" }, children: "Copied to clipboard!" }))] }), _jsx(SolidDialogSeparator, {}), _jsxs(SolidDialogFooter, { children: [_jsx(SolidButton, { variant: "outline", onClick: handleClose, children: "Close" }), _jsx(SolidButton, { onClick: handleClose, children: "I've Saved This Key" })] })] }));
36
+ }
37
+ //# sourceMappingURL=RevealApiKeyModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RevealApiKeyModal.js","sourceRoot":"","sources":["../../../../../src/components/core/users/ApiKeysTab/RevealApiKeyModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\nimport { AlertTriangle, CheckCircle, Copy } from \"lucide-react\";\nimport {\n SolidButton,\n SolidDialog,\n SolidDialogBody,\n SolidDialogFooter,\n SolidDialogHeader,\n SolidDialogSeparator,\n SolidDialogTitle,\n} from \"../../../shad-cn-ui\";\n\ninterface RevealApiKeyModalProps {\n open: boolean;\n apiKey: string;\n keyName: string;\n onClose: () => void;\n}\n\nexport function RevealApiKeyModal({ open, apiKey, keyName, onClose }: RevealApiKeyModalProps) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = () => {\n navigator.clipboard.writeText(apiKey).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 3000);\n });\n };\n\n const handleClose = () => {\n setCopied(false);\n onClose();\n };\n\n return (\n <SolidDialog open={open} onOpenChange={handleClose} dismissible={false} style={{ maxWidth: 520 }}>\n <SolidDialogHeader>\n <SolidDialogTitle>API Key Created</SolidDialogTitle>\n </SolidDialogHeader>\n <SolidDialogSeparator />\n <SolidDialogBody>\n <div className=\"solid-api-key-reveal-warning flex align-items-start gap-2 mb-4\">\n <AlertTriangle size={16} className=\"flex-shrink-0 mt-1\" />\n <p className=\"m-0\" style={{ fontSize: 13 }}>\n <strong>Copy this key now.</strong> It will not be shown again once you close this dialog. Store it somewhere secure.\n </p>\n </div>\n\n <p className=\"form-field-label mb-2\">\n {keyName}\n </p>\n\n <div\n className=\"solid-api-key-reveal-box flex align-items-center gap-2 p-3\"\n style={{\n background: \"var(--solid-surface-secondary, #f5f5f5)\",\n borderRadius: 6,\n border: \"1px solid var(--solid-border-color, #e0e0e0)\",\n }}\n >\n <code\n className=\"flex-1\"\n style={{\n fontFamily: \"monospace\",\n fontSize: 13,\n wordBreak: \"break-all\",\n userSelect: \"all\",\n }}\n >\n {apiKey}\n </code>\n <button\n type=\"button\"\n title={copied ? \"Copied!\" : \"Copy to clipboard\"}\n onClick={handleCopy}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"4px\",\n display: \"flex\",\n alignItems: \"center\",\n flexShrink: 0,\n }}\n >\n {copied ? (\n <CheckCircle size={16} style={{ color: \"var(--solid-success-color, #22c55e)\" }} />\n ) : (\n <Copy size={16} />\n )}\n </button>\n </div>\n\n {copied && (\n <p className=\"m-0 mt-2\" style={{ fontSize: 12, color: \"var(--solid-success-color, #22c55e)\" }}>\n Copied to clipboard!\n </p>\n )}\n </SolidDialogBody>\n <SolidDialogSeparator />\n <SolidDialogFooter>\n <SolidButton variant=\"outline\" onClick={handleClose}>\n Close\n </SolidButton>\n <SolidButton onClick={handleClose}>\n I've Saved This Key\n </SolidButton>\n </SolidDialogFooter>\n </SolidDialog>\n );\n}\n"]}
@@ -0,0 +1,111 @@
1
+ import { useState } from "react";
2
+ import { AlertTriangle, CheckCircle, Copy } from "lucide-react";
3
+ import {
4
+ SolidButton,
5
+ SolidDialog,
6
+ SolidDialogBody,
7
+ SolidDialogFooter,
8
+ SolidDialogHeader,
9
+ SolidDialogSeparator,
10
+ SolidDialogTitle,
11
+ } from "../../../shad-cn-ui";
12
+
13
+ interface RevealApiKeyModalProps {
14
+ open: boolean;
15
+ apiKey: string;
16
+ keyName: string;
17
+ onClose: () => void;
18
+ }
19
+
20
+ export function RevealApiKeyModal({ open, apiKey, keyName, onClose }: RevealApiKeyModalProps) {
21
+ const [copied, setCopied] = useState(false);
22
+
23
+ const handleCopy = () => {
24
+ navigator.clipboard.writeText(apiKey).then(() => {
25
+ setCopied(true);
26
+ setTimeout(() => setCopied(false), 3000);
27
+ });
28
+ };
29
+
30
+ const handleClose = () => {
31
+ setCopied(false);
32
+ onClose();
33
+ };
34
+
35
+ return (
36
+ <SolidDialog open={open} onOpenChange={handleClose} dismissible={false} style={{ maxWidth: 520 }}>
37
+ <SolidDialogHeader>
38
+ <SolidDialogTitle>API Key Created</SolidDialogTitle>
39
+ </SolidDialogHeader>
40
+ <SolidDialogSeparator />
41
+ <SolidDialogBody>
42
+ <div className="solid-api-key-reveal-warning flex align-items-start gap-2 mb-4">
43
+ <AlertTriangle size={16} className="flex-shrink-0 mt-1" />
44
+ <p className="m-0" style={{ fontSize: 13 }}>
45
+ <strong>Copy this key now.</strong> It will not be shown again once you close this dialog. Store it somewhere secure.
46
+ </p>
47
+ </div>
48
+
49
+ <p className="form-field-label mb-2">
50
+ {keyName}
51
+ </p>
52
+
53
+ <div
54
+ className="solid-api-key-reveal-box flex align-items-center gap-2 p-3"
55
+ style={{
56
+ background: "var(--solid-surface-secondary, #f5f5f5)",
57
+ borderRadius: 6,
58
+ border: "1px solid var(--solid-border-color, #e0e0e0)",
59
+ }}
60
+ >
61
+ <code
62
+ className="flex-1"
63
+ style={{
64
+ fontFamily: "monospace",
65
+ fontSize: 13,
66
+ wordBreak: "break-all",
67
+ userSelect: "all",
68
+ }}
69
+ >
70
+ {apiKey}
71
+ </code>
72
+ <button
73
+ type="button"
74
+ title={copied ? "Copied!" : "Copy to clipboard"}
75
+ onClick={handleCopy}
76
+ style={{
77
+ background: "none",
78
+ border: "none",
79
+ cursor: "pointer",
80
+ padding: "4px",
81
+ display: "flex",
82
+ alignItems: "center",
83
+ flexShrink: 0,
84
+ }}
85
+ >
86
+ {copied ? (
87
+ <CheckCircle size={16} style={{ color: "var(--solid-success-color, #22c55e)" }} />
88
+ ) : (
89
+ <Copy size={16} />
90
+ )}
91
+ </button>
92
+ </div>
93
+
94
+ {copied && (
95
+ <p className="m-0 mt-2" style={{ fontSize: 12, color: "var(--solid-success-color, #22c55e)" }}>
96
+ Copied to clipboard!
97
+ </p>
98
+ )}
99
+ </SolidDialogBody>
100
+ <SolidDialogSeparator />
101
+ <SolidDialogFooter>
102
+ <SolidButton variant="outline" onClick={handleClose}>
103
+ Close
104
+ </SolidButton>
105
+ <SolidButton onClick={handleClose}>
106
+ I've Saved This Key
107
+ </SolidButton>
108
+ </SolidDialogFooter>
109
+ </SolidDialog>
110
+ );
111
+ }
@@ -0,0 +1,4 @@
1
+ export { ApiKeysTab } from "./ApiKeysTab";
2
+ export { GenerateApiKeyModal } from "./GenerateApiKeyModal";
3
+ export { RevealApiKeyModal } from "./RevealApiKeyModal";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/core/users/ApiKeysTab/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { ApiKeysTab } from "./ApiKeysTab";
2
+ export { GenerateApiKeyModal } from "./GenerateApiKeyModal";
3
+ export { RevealApiKeyModal } from "./RevealApiKeyModal";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/components/core/users/ApiKeysTab/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["export { ApiKeysTab } from \"./ApiKeysTab\";\nexport { GenerateApiKeyModal } from \"./GenerateApiKeyModal\";\nexport { RevealApiKeyModal } from \"./RevealApiKeyModal\";\n"]}
@@ -0,0 +1,3 @@
1
+ export { ApiKeysTab } from "./ApiKeysTab";
2
+ export { GenerateApiKeyModal } from "./GenerateApiKeyModal";
3
+ export { RevealApiKeyModal } from "./RevealApiKeyModal";
@@ -0,0 +1,3 @@
1
+ # no such endpoints exist, need to called user get with populate api key filter
2
+ useGetSelfApiKeysQuery() → GET /iam/api-keys (self mode)
3
+ useGetUserApiKeysQuery(userId) → GET /users/:id/api-keys (admin mode)
@@ -0,0 +1,4 @@
1
+ import { NextAuthOptions } from "next-auth";
2
+ declare const authProviders: NextAuthOptions;
3
+ export default authProviders;
4
+ //# sourceMappingURL=authProviders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authProviders.d.ts","sourceRoot":"./","sources":["nextAuth/authProviders.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAW5C,QAAA,MAAM,aAAa,EAAE,eAqNpB,CAAA;AAED,eAAe,aAAa,CAAA"}
@@ -0,0 +1,198 @@
1
+ import CredentialsProvider from "next-auth/providers/credentials";
2
+ import GoogleProvider from "next-auth/providers/google";
3
+ import { jwtDecode } from "jwt-decode";
4
+ import axios from "axios";
5
+ import { refreshAccessToken } from "./refreshAccessToken";
6
+ const authProviders = {
7
+ session: {
8
+ strategy: "jwt",
9
+ },
10
+ providers: [
11
+ GoogleProvider({
12
+ clientId: process.env.GOOGLE_ID,
13
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET
14
+ }),
15
+ CredentialsProvider({
16
+ // @ts-ignore
17
+ async authorize(credentials, req) {
18
+ const userAgent = req.headers['user-agent'];
19
+ const { username, email, password, identifier, accessToken, accessCode } = credentials;
20
+ console.log(credentials, '=========================');
21
+ try {
22
+ if (accessCode) {
23
+ let config = {
24
+ method: 'get',
25
+ url: `${process.env.API_URL}/api/iam/google/authenticate?accessCode=${accessCode}`,
26
+ headers: {
27
+ 'User-Agent': userAgent,
28
+ }
29
+ };
30
+ const loginResponse = await axios.request(config);
31
+ if (loginResponse.status == 400) {
32
+ throw new Error(loginResponse.data.message);
33
+ }
34
+ if (loginResponse.status == 401) {
35
+ throw new Error(loginResponse.data.message);
36
+ }
37
+ let base64decoded = jwtDecode(loginResponse.data.data.accessToken);
38
+ // let accessTokenExpires = base64decoded.exp;
39
+ let accessTokenExpires = base64decoded.exp && base64decoded.exp * 1000;
40
+ return {
41
+ accessToken: loginResponse.data.data.accessToken,
42
+ refreshToken: loginResponse.data.data.refreshToken,
43
+ accessTokenExpires: accessTokenExpires,
44
+ ...loginResponse.data.data,
45
+ };
46
+ }
47
+ else {
48
+ if (accessToken) {
49
+ let data = JSON.stringify({
50
+ username: identifier,
51
+ email: identifier.includes('@') ? identifier : null,
52
+ password: password
53
+ });
54
+ let config = {
55
+ method: 'get',
56
+ url: `${process.env.API_URL}/api/iam/me`,
57
+ headers: {
58
+ 'accept': '*/*',
59
+ 'Content-Type': 'application/json',
60
+ 'Authorization': `Bearer ${accessToken}`
61
+ }
62
+ };
63
+ const loginResponse = await axios.request(config);
64
+ if (loginResponse.status == 400) {
65
+ throw new Error(loginResponse.data.message);
66
+ }
67
+ if (loginResponse.status == 401) {
68
+ throw new Error(loginResponse.data.message);
69
+ }
70
+ let base64decoded = jwtDecode(accessToken);
71
+ // let accessTokenExpires = base64decoded.exp;
72
+ let accessTokenExpires = base64decoded.exp && base64decoded.exp * 1000;
73
+ return {
74
+ accessToken: accessToken,
75
+ refreshToken: loginResponse.data.data.refreshToken,
76
+ accessTokenExpires: accessTokenExpires,
77
+ ...loginResponse.data.data,
78
+ };
79
+ }
80
+ else {
81
+ let data = JSON.stringify({
82
+ username: identifier,
83
+ email: identifier.includes('@') ? identifier : null,
84
+ password: password
85
+ });
86
+ let config = {
87
+ method: 'post',
88
+ maxBodyLength: Infinity,
89
+ url: `${process.env.API_URL}/api/iam/authenticate`,
90
+ headers: {
91
+ 'accept': '*/*',
92
+ 'Content-Type': 'application/json',
93
+ 'User-Agent': userAgent,
94
+ },
95
+ data: data
96
+ };
97
+ const loginResponse = await axios.request(config);
98
+ // const authenticateResponse = await fetch(
99
+ // `${process.env.API_URL}/api/iam/authenticate`,
100
+ // {
101
+ // method: "Post",
102
+ // headers: {
103
+ // 'accept': '*/*',
104
+ // "Content-Type": "application/json"
105
+ // },
106
+ // body: JSON.stringify({
107
+ // username: email,
108
+ // email: email,
109
+ // password: password
110
+ // })
111
+ // }
112
+ // );
113
+ // const loginResponse = await authenticateResponse.json();
114
+ // const response = await fetch(
115
+ // `${process.env.API_URL}/api/iam/me`,
116
+ // {
117
+ // method: "Get",
118
+ // headers: {
119
+ // "Content-Type": "application/json",
120
+ // "Authorization": `Bearer ${loginResponse.data.accessToken}`,
121
+ // },
122
+ // }
123
+ // );
124
+ // const responseData = await response.json();
125
+ if (loginResponse.status == 400) {
126
+ throw new Error(loginResponse.data.message);
127
+ }
128
+ if (loginResponse.status == 401) {
129
+ throw new Error(loginResponse.data.data.message);
130
+ }
131
+ let base64decoded = jwtDecode(loginResponse.data.data.accessToken);
132
+ // let accessTokenExpires = base64decoded.exp;
133
+ let accessTokenExpires = base64decoded.exp && base64decoded.exp * 1000;
134
+ const returnResponse = {
135
+ accessToken: loginResponse.data.data.accessToken,
136
+ refreshToken: loginResponse.data.data.refreshToken,
137
+ accessTokenExpires: accessTokenExpires,
138
+ ...loginResponse.data.data,
139
+ };
140
+ return returnResponse;
141
+ }
142
+ }
143
+ }
144
+ catch (error) {
145
+ throw new Error(error?.response?.data?.message);
146
+ }
147
+ },
148
+ }),
149
+ ],
150
+ callbacks: {
151
+ // @ts-ignore
152
+ jwt: async ({ token, user }) => {
153
+ // console.log("JWT callback called");
154
+ const bufferTime = 60000;
155
+ if (Date.now() >= (token.accessTokenExpires - bufferTime)) {
156
+ // Call the refresh token function
157
+ return await refreshAccessToken(token);
158
+ }
159
+ // If there is no user (first time login or session), we return the user data
160
+ if (user) {
161
+ // const base64decoded = jwtDecode(user.accessToken);
162
+ // Convert from seconds to milliseconds
163
+ // const accessTokenExpires = base64decoded.exp && base64decoded.exp * 1000;
164
+ // const accessTokenExpires = user.accessTokenExpires * 1000;
165
+ return {
166
+ ...token,
167
+ accessToken: user.accessToken,
168
+ refreshToken: user.refreshToken,
169
+ accessTokenExpires: user.accessTokenExpires,
170
+ user: user, // Include the user data here
171
+ };
172
+ }
173
+ return token; // If no update needed, just return the existing token
174
+ },
175
+ // @ts-ignore
176
+ session: async ({ session, token }) => {
177
+ // console.log("Session callback called");
178
+ const user = token.user || {}; // Default to an empty object if user is undefined or null
179
+ session.error = token.error ? token.error : null;
180
+ // if (token.error) {
181
+ // return null
182
+ // }
183
+ session.user = {
184
+ ...user,
185
+ accessToken: token?.accessToken,
186
+ refreshToken: token?.refreshToken,
187
+ accessTokenExpires: token?.accessTokenExpires && token?.accessTokenExpires, // Store the expiry time
188
+ };
189
+ return session;
190
+ },
191
+ },
192
+ pages: {
193
+ signIn: "/auth/login",
194
+ },
195
+ secret: process.env.NEXTAUTH_SECRET,
196
+ };
197
+ export default authProviders;
198
+ //# sourceMappingURL=authProviders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authProviders.js","sourceRoot":"./","sources":["nextAuth/authProviders.tsx"],"names":[],"mappings":"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","sourcesContent":["import CredentialsProvider from \"next-auth/providers/credentials\";\nimport GoogleProvider from \"next-auth/providers/google\";\nimport { NextRequest } from \"next/server\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { JWT } from \"next-auth/jwt\";\nimport axios from \"axios\";\nimport { signOut } from \"next-auth/react\";\nimport { refreshAccessToken } from \"./refreshAccessToken\";\nimport { NextAuthOptions } from \"next-auth\";\n\ntype Credentials = {\n username: string,\n email: string,\n password: string,\n identifier:string,\n accessToken: string,\n accessCode: string,\n};\n\nconst authProviders: NextAuthOptions = {\n session: {\n strategy: \"jwt\",\n },\n providers: [\n GoogleProvider({\n clientId: process.env.GOOGLE_ID!,\n clientSecret: process.env.GOOGLE_CLIENT_SECRET!\n }),\n CredentialsProvider({\n // @ts-ignore\n async authorize(credentials: Credentials, req: any) {\n const userAgent = req.headers['user-agent'];\n\n const { username, email, password, identifier, accessToken, accessCode } = credentials;\n\n console.log(credentials , '=========================');\n \n try {\n if (accessCode) {\n let config = {\n method: 'get',\n url: `${process.env.API_URL}/api/iam/google/authenticate?accessCode=${accessCode}`,\n headers: {\n 'User-Agent': userAgent,\n }\n };\n const loginResponse = await axios.request(config);\n if (loginResponse.status == 400) {\n throw new Error(loginResponse.data.message);\n }\n if (loginResponse.status == 401) {\n throw new Error(loginResponse.data.message);\n }\n\n let base64decoded = jwtDecode(loginResponse.data.data.accessToken);\n // let accessTokenExpires = base64decoded.exp;\n let accessTokenExpires = base64decoded.exp && base64decoded.exp * 1000;\n\n return {\n accessToken: loginResponse.data.data.accessToken,\n refreshToken: loginResponse.data.data.refreshToken,\n accessTokenExpires: accessTokenExpires,\n ...loginResponse.data.data,\n };\n\n } else {\n if (accessToken) {\n let data = JSON.stringify({\n username: identifier,\n email: identifier.includes('@')? identifier : null,\n password: password\n });\n\n let config = {\n method: 'get',\n url: `${process.env.API_URL}/api/iam/me`,\n headers: {\n 'accept': '*/*',\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${accessToken}`\n }\n };\n\n\n const loginResponse = await axios.request(config);\n\n if (loginResponse.status == 400) {\n throw new Error(loginResponse.data.message);\n }\n if (loginResponse.status == 401) {\n throw new Error(loginResponse.data.message);\n }\n \n let base64decoded = jwtDecode(accessToken);\n // let accessTokenExpires = base64decoded.exp;\n let accessTokenExpires = base64decoded.exp && base64decoded.exp * 1000;\n\n return {\n accessToken: accessToken,\n refreshToken: loginResponse.data.data.refreshToken,\n accessTokenExpires: accessTokenExpires,\n ...loginResponse.data.data,\n };\n\n } else {\n\n let data = JSON.stringify({\n username: identifier,\n email: identifier.includes('@')? identifier : null,\n password: password\n });\n\n let config = {\n method: 'post',\n maxBodyLength: Infinity,\n url: `${process.env.API_URL}/api/iam/authenticate`,\n headers: {\n 'accept': '*/*',\n 'Content-Type': 'application/json',\n 'User-Agent': userAgent,\n },\n data: data\n };\n\n\n const loginResponse = await axios.request(config);\n\n // const authenticateResponse = await fetch(\n // `${process.env.API_URL}/api/iam/authenticate`,\n // {\n // method: \"Post\",\n // headers: {\n // 'accept': '*/*', \n // \"Content-Type\": \"application/json\"\n // },\n // body: JSON.stringify({\n // username: email,\n // email: email,\n // password: password\n // })\n // }\n // );\n\n // const loginResponse = await authenticateResponse.json();\n\n // const response = await fetch(\n // `${process.env.API_URL}/api/iam/me`,\n // {\n // method: \"Get\",\n // headers: {\n // \"Content-Type\": \"application/json\",\n // \"Authorization\": `Bearer ${loginResponse.data.accessToken}`,\n // },\n // }\n // );\n\n // const responseData = await response.json();\n\n if (loginResponse.status == 400) {\n throw new Error(loginResponse.data.message);\n }\n if (loginResponse.status == 401) {\n throw new Error(loginResponse.data.data.message);\n }\n let base64decoded = jwtDecode(loginResponse.data.data.accessToken);\n // let accessTokenExpires = base64decoded.exp;\n let accessTokenExpires = base64decoded.exp && base64decoded.exp * 1000;\n const returnResponse = {\n accessToken: loginResponse.data.data.accessToken,\n refreshToken: loginResponse.data.data.refreshToken,\n accessTokenExpires: accessTokenExpires,\n ...loginResponse.data.data,\n }\n return returnResponse;\n }\n }\n } catch (error: any) {\n throw new Error(error?.response?.data?.message);\n }\n },\n }),\n ],\n callbacks: {\n // @ts-ignore\n jwt: async ({ token, user }) => {\n // console.log(\"JWT callback called\");\n const bufferTime = 60000;\n if (Date.now() >= (token.accessTokenExpires as number - bufferTime)) {\n // Call the refresh token function\n return await refreshAccessToken(token);\n }\n\n // If there is no user (first time login or session), we return the user data\n if (user) {\n // const base64decoded = jwtDecode(user.accessToken);\n // Convert from seconds to milliseconds\n // const accessTokenExpires = base64decoded.exp && base64decoded.exp * 1000; \n // const accessTokenExpires = user.accessTokenExpires * 1000; \n return {\n ...token,\n accessToken: user.accessToken,\n refreshToken: user.refreshToken,\n accessTokenExpires: user.accessTokenExpires,\n user: user, // Include the user data here\n };\n }\n\n return token; // If no update needed, just return the existing token\n },\n // @ts-ignore\n session: async ({ session, token }) => {\n // console.log(\"Session callback called\");\n\n const user = token.user || {}; // Default to an empty object if user is undefined or null\n session.error = token.error ? token.error : null;\n // if (token.error) {\n // return null\n // }\n session.user = {\n ...user, // Include the user info from the token\n accessToken: token?.accessToken, // Add the access token to session for client use\n refreshToken: token?.refreshToken, // Add refresh token to session for future use\n accessTokenExpires: token?.accessTokenExpires && token?.accessTokenExpires, // Store the expiry time\n };\n return session;\n\n },\n },\n pages: {\n signIn: \"/auth/login\",\n },\n secret: process.env.NEXTAUTH_SECRET,\n}\n\nexport default authProviders"]}