@payloadcms/ui 3.89.0-internal.95c9cba → 3.90.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.
- package/dist/elements/BulkUpload/FormsManager/createFormData.d.ts +1 -1
- package/dist/elements/BulkUpload/FormsManager/createFormData.d.ts.map +1 -1
- package/dist/elements/BulkUpload/FormsManager/createFormData.js +7 -3
- package/dist/elements/BulkUpload/FormsManager/createFormData.js.map +1 -1
- package/dist/elements/BulkUpload/FormsManager/index.d.ts.map +1 -1
- package/dist/elements/BulkUpload/FormsManager/index.js +4 -2
- package/dist/elements/BulkUpload/FormsManager/index.js.map +1 -1
- package/dist/elements/PublishButton/ScheduleDrawer/buildUpcomingScheduleWhere.d.ts +13 -0
- package/dist/elements/PublishButton/ScheduleDrawer/buildUpcomingScheduleWhere.d.ts.map +1 -0
- package/dist/elements/PublishButton/ScheduleDrawer/buildUpcomingScheduleWhere.js +41 -0
- package/dist/elements/PublishButton/ScheduleDrawer/buildUpcomingScheduleWhere.js.map +1 -0
- package/dist/elements/PublishButton/ScheduleDrawer/index.d.ts.map +1 -1
- package/dist/elements/PublishButton/ScheduleDrawer/index.js +8 -54
- package/dist/elements/PublishButton/ScheduleDrawer/index.js.map +1 -1
- package/dist/elements/PublishButton/ScheduleDrawer/types.d.ts +1 -1
- package/dist/elements/PublishButton/ScheduleDrawer/types.d.ts.map +1 -1
- package/dist/elements/PublishButton/ScheduleDrawer/types.js.map +1 -1
- package/dist/elements/Spinner/index.d.ts +19 -0
- package/dist/elements/Spinner/index.d.ts.map +1 -0
- package/dist/elements/Spinner/index.js +51 -0
- package/dist/elements/Spinner/index.js.map +1 -0
- package/dist/elements/Spinner/index.scss +23 -0
- package/dist/exports/client/index.d.ts +4 -1
- package/dist/exports/client/index.d.ts.map +1 -1
- package/dist/exports/client/index.js +24 -24
- package/dist/exports/client/index.js.map +4 -4
- package/dist/fields/Tabs/index.d.ts.map +1 -1
- package/dist/fields/Tabs/index.js +109 -234
- package/dist/fields/Tabs/index.js.map +1 -1
- package/dist/fields/Tabs/resolveRestoredTabIndex.d.ts +19 -0
- package/dist/fields/Tabs/resolveRestoredTabIndex.d.ts.map +1 -0
- package/dist/fields/Tabs/resolveRestoredTabIndex.js +20 -0
- package/dist/fields/Tabs/resolveRestoredTabIndex.js.map +1 -0
- package/dist/fields/Tabs/resolveRestoredTabIndex.spec.js +53 -0
- package/dist/fields/Tabs/resolveRestoredTabIndex.spec.js.map +1 -0
- package/dist/forms/Form/index.d.ts.map +1 -1
- package/dist/forms/Form/index.js +6 -2
- package/dist/forms/Form/index.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/renderField.d.ts.map +1 -1
- package/dist/forms/fieldSchemasToFormState/renderField.js +3 -2
- package/dist/forms/fieldSchemasToFormState/renderField.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/serverFunctions/mergeAllowedFieldOverrides.d.ts +12 -0
- package/dist/forms/fieldSchemasToFormState/serverFunctions/mergeAllowedFieldOverrides.d.ts.map +1 -0
- package/dist/forms/fieldSchemasToFormState/serverFunctions/mergeAllowedFieldOverrides.js +32 -0
- package/dist/forms/fieldSchemasToFormState/serverFunctions/mergeAllowedFieldOverrides.js.map +1 -0
- package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.d.ts +8 -6
- package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.d.ts.map +1 -1
- package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.js +25 -9
- package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.spec.js +179 -0
- package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.spec.js.map +1 -0
- package/dist/forms/fieldSchemasToFormState/types.d.ts +1 -0
- package/dist/forms/fieldSchemasToFormState/types.d.ts.map +1 -1
- package/dist/forms/fieldSchemasToFormState/types.js.map +1 -1
- package/dist/icons/Eye/index.scss +1 -1
- package/dist/icons/Refresh/index.d.ts +7 -0
- package/dist/icons/Refresh/index.d.ts.map +1 -0
- package/dist/icons/Refresh/index.js +35 -0
- package/dist/icons/Refresh/index.js.map +1 -0
- package/dist/icons/Refresh/index.scss +11 -0
- package/dist/icons/Spinner/index.d.ts +8 -0
- package/dist/icons/Spinner/index.d.ts.map +1 -0
- package/dist/icons/Spinner/index.js +34 -0
- package/dist/icons/Spinner/index.js.map +1 -0
- package/dist/icons/Spinner/index.scss +12 -0
- package/dist/providers/LivePreview/index.d.ts.map +1 -1
- package/dist/providers/LivePreview/index.js +13 -6
- package/dist/providers/LivePreview/index.js.map +1 -1
- package/dist/providers/ServerFunctions/index.d.ts +5 -1
- package/dist/providers/ServerFunctions/index.d.ts.map +1 -1
- package/dist/providers/ServerFunctions/index.js +15 -0
- package/dist/providers/ServerFunctions/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utilities/buildFormState.d.ts.map +1 -1
- package/dist/utilities/buildFormState.js +6 -2
- package/dist/utilities/buildFormState.js.map +1 -1
- package/dist/utilities/formatAbsoluteURL.d.ts +1 -1
- package/dist/utilities/formatAbsoluteURL.d.ts.map +1 -1
- package/dist/utilities/formatAbsoluteURL.js +18 -8
- package/dist/utilities/formatAbsoluteURL.js.map +1 -1
- package/dist/utilities/formatAbsoluteURL.spec.js +27 -0
- package/dist/utilities/formatAbsoluteURL.spec.js.map +1 -0
- package/dist/utilities/isAbsoluteURL.d.ts +3 -0
- package/dist/utilities/isAbsoluteURL.d.ts.map +1 -0
- package/dist/utilities/isAbsoluteURL.js +15 -0
- package/dist/utilities/isAbsoluteURL.js.map +1 -0
- package/dist/utilities/isAbsoluteURL.spec.js +11 -0
- package/dist/utilities/isAbsoluteURL.spec.js.map +1 -0
- package/dist/utilities/isHttpURL.d.ts +3 -0
- package/dist/utilities/isHttpURL.d.ts.map +1 -0
- package/dist/utilities/isHttpURL.js +12 -0
- package/dist/utilities/isHttpURL.js.map +1 -0
- package/dist/utilities/isHttpURL.spec.js +25 -0
- package/dist/utilities/isHttpURL.spec.js.map +1 -0
- package/dist/utilities/schedulePublishHandler.d.ts +8 -1
- package/dist/utilities/schedulePublishHandler.d.ts.map +1 -1
- package/dist/utilities/schedulePublishHandler.js +78 -5
- package/dist/utilities/schedulePublishHandler.js.map +1 -1
- package/dist/views/Edit/Auth/APIKey.d.ts +1 -1
- package/dist/views/Edit/Auth/APIKey.d.ts.map +1 -1
- package/dist/views/Edit/Auth/APIKey.js +216 -59
- package/dist/views/Edit/Auth/APIKey.js.map +1 -1
- package/dist/views/Edit/Auth/APIKeyGenerationModal.d.ts +11 -0
- package/dist/views/Edit/Auth/APIKeyGenerationModal.d.ts.map +1 -0
- package/dist/views/Edit/Auth/APIKeyGenerationModal.js +113 -0
- package/dist/views/Edit/Auth/APIKeyGenerationModal.js.map +1 -0
- package/dist/views/Edit/Auth/index.d.ts.map +1 -1
- package/dist/views/Edit/Auth/index.js +10 -30
- package/dist/views/Edit/Auth/index.js.map +1 -1
- package/dist/views/Edit/Auth/index.scss +73 -36
- package/dist/views/Edit/Auth/types.d.ts +1 -1
- package/dist/views/Edit/Auth/types.d.ts.map +1 -1
- package/dist/views/Edit/Auth/types.js.map +1 -1
- package/package.json +6 -5
- package/dist/elements/GenerateConfirmation/index.d.ts +0 -7
- package/dist/elements/GenerateConfirmation/index.d.ts.map +0 -1
- package/dist/elements/GenerateConfirmation/index.js +0 -95
- package/dist/elements/GenerateConfirmation/index.js.map +0 -1
|
@@ -1,41 +1,65 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useModal } from '@faceless-ui/modal';
|
|
4
5
|
import { getTranslation } from '@payloadcms/translations';
|
|
5
|
-
import { text } from 'payload/shared';
|
|
6
|
-
import React, { useEffect, useMemo, useState } from 'react';
|
|
6
|
+
import { formatAdminURL, text } from 'payload/shared';
|
|
7
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
8
|
+
import { toast } from 'sonner';
|
|
7
9
|
import { v4 as uuidv4 } from 'uuid';
|
|
8
10
|
import { Button } from '../../../elements/Button/index.js';
|
|
11
|
+
import { ConfirmationModal } from '../../../elements/ConfirmationModal/index.js';
|
|
9
12
|
import { CopyToClipboard } from '../../../elements/CopyToClipboard/index.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
13
|
+
import { Spinner } from '../../../elements/Spinner/index.js';
|
|
14
|
+
import { FieldDescription } from '../../../fields/FieldDescription/index.js';
|
|
15
|
+
import { useFormFields, useFormModified } from '../../../forms/Form/context.js';
|
|
12
16
|
import { useField } from '../../../forms/useField/index.js';
|
|
13
17
|
import { EyeIcon } from '../../../icons/Eye/index.js';
|
|
18
|
+
import { RefreshIcon } from '../../../icons/Refresh/index.js';
|
|
14
19
|
import { useConfig } from '../../../providers/Config/index.js';
|
|
15
20
|
import { useDocumentInfo } from '../../../providers/DocumentInfo/index.js';
|
|
21
|
+
import { useLocale } from '../../../providers/Locale/index.js';
|
|
16
22
|
import { useTranslation } from '../../../providers/Translation/index.js';
|
|
23
|
+
import { APIKeyGenerationModal } from './APIKeyGenerationModal.js';
|
|
17
24
|
const path = 'apiKey';
|
|
18
25
|
const baseClass = 'api-key';
|
|
19
26
|
const fieldBaseClass = 'field-type';
|
|
27
|
+
const maskedAPIKey = '•'.repeat(24);
|
|
20
28
|
export const APIKey = ({
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
readOnly,
|
|
30
|
+
reveal
|
|
23
31
|
}) => {
|
|
24
|
-
const [initialAPIKey] = useState(uuidv4());
|
|
25
32
|
const [highlightedField, setHighlightedField] = useState(false);
|
|
33
|
+
const [hasUpdatedPersistedAPIKey, setHasUpdatedPersistedAPIKey] = useState(null);
|
|
34
|
+
const [isRevealing, setIsRevealing] = useState(false);
|
|
35
|
+
const [revealedKey, setRevealedKey] = useState(null);
|
|
36
|
+
const [showCopyWarning, setShowCopyWarning] = useState(false);
|
|
26
37
|
const [showKey, setShowKey] = useState(false);
|
|
38
|
+
const modified = useFormModified();
|
|
39
|
+
const wasModified = useRef(modified);
|
|
27
40
|
const {
|
|
28
41
|
i18n,
|
|
29
42
|
t
|
|
30
43
|
} = useTranslation();
|
|
44
|
+
const {
|
|
45
|
+
toggleModal
|
|
46
|
+
} = useModal();
|
|
31
47
|
const {
|
|
32
48
|
config,
|
|
33
49
|
getEntityConfig
|
|
34
50
|
} = useConfig();
|
|
35
51
|
const {
|
|
36
|
-
|
|
52
|
+
id,
|
|
53
|
+
collectionSlug,
|
|
54
|
+
setData,
|
|
55
|
+
setLastUpdateTime
|
|
37
56
|
} = useDocumentInfo();
|
|
38
|
-
const
|
|
57
|
+
const {
|
|
58
|
+
code: locale
|
|
59
|
+
} = useLocale();
|
|
60
|
+
const revokeModalSlug = `revoke-api-key-${id}`;
|
|
61
|
+
const hasAPIKey = useFormFields(([fields]) => fields && fields.hasAPIKey || null);
|
|
62
|
+
const dispatchFields_0 = useFormFields(([, dispatchFields]) => dispatchFields);
|
|
39
63
|
const apiKeyField = getEntityConfig({
|
|
40
64
|
collectionSlug
|
|
41
65
|
})?.fields?.find(field => 'name' in field && field.name === 'apiKey');
|
|
@@ -59,7 +83,16 @@ export const APIKey = ({
|
|
|
59
83
|
},
|
|
60
84
|
siblingData: {}
|
|
61
85
|
});
|
|
62
|
-
const
|
|
86
|
+
const {
|
|
87
|
+
setValue,
|
|
88
|
+
value
|
|
89
|
+
} = useField({
|
|
90
|
+
path,
|
|
91
|
+
validate
|
|
92
|
+
});
|
|
93
|
+
const apiKeyValue = revealedKey || value;
|
|
94
|
+
const hasPersistedAPIKey = hasUpdatedPersistedAPIKey ?? Boolean(hasAPIKey?.value);
|
|
95
|
+
const canRevealPersistedAPIKey = reveal && hasPersistedAPIKey && !revealedKey;
|
|
63
96
|
const apiKeyLabel = useMemo(() => {
|
|
64
97
|
let label = 'API Key';
|
|
65
98
|
if (apiKeyField?.label) {
|
|
@@ -67,77 +100,201 @@ export const APIKey = ({
|
|
|
67
100
|
}
|
|
68
101
|
return getTranslation(label, i18n);
|
|
69
102
|
}, [apiKeyField, i18n]);
|
|
70
|
-
const APIKeyLabel = useMemo(() => /*#__PURE__*/_jsxs("label", {
|
|
71
|
-
className: `${baseClass}__label field-label`,
|
|
72
|
-
htmlFor: "apiKey",
|
|
73
|
-
children: [/*#__PURE__*/_jsx("span", {
|
|
74
|
-
children: apiKeyLabel
|
|
75
|
-
}), /*#__PURE__*/_jsx(CopyToClipboard, {
|
|
76
|
-
value: apiKeyValue
|
|
77
|
-
})]
|
|
78
|
-
}), [apiKeyLabel, apiKeyValue]);
|
|
79
|
-
const fieldType = useField({
|
|
80
|
-
path: 'apiKey',
|
|
81
|
-
validate
|
|
82
|
-
});
|
|
83
103
|
const highlightField = () => {
|
|
84
|
-
|
|
85
|
-
|
|
104
|
+
setHighlightedField(true);
|
|
105
|
+
};
|
|
106
|
+
const updateKey = async apiKey => {
|
|
107
|
+
if (!id) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const response = await fetch(formatAdminURL({
|
|
112
|
+
apiRoute: config.routes.api,
|
|
113
|
+
path: `/${collectionSlug}/${encodeURIComponent(String(id))}?depth=0&fallback-locale=null&locale=${locale}`
|
|
114
|
+
}), {
|
|
115
|
+
body: JSON.stringify({
|
|
116
|
+
apiKey,
|
|
117
|
+
// The `enableAPIKey` field is for backward compatibility only and will be removed in v4.
|
|
118
|
+
enableAPIKey: Boolean(apiKey)
|
|
119
|
+
}),
|
|
120
|
+
headers: {
|
|
121
|
+
'Content-Type': 'application/json'
|
|
122
|
+
},
|
|
123
|
+
method: 'PATCH'
|
|
124
|
+
});
|
|
125
|
+
if (!response.ok) {
|
|
126
|
+
throw new Error('API key update failed');
|
|
127
|
+
}
|
|
128
|
+
const result = await response.json();
|
|
129
|
+
setHasUpdatedPersistedAPIKey(Boolean(apiKey));
|
|
130
|
+
dispatchFields_0({
|
|
131
|
+
type: 'REMOVE',
|
|
132
|
+
path
|
|
133
|
+
});
|
|
134
|
+
// The `enableAPIKey` field is for backward compatibility only and will be removed in v4.
|
|
135
|
+
dispatchFields_0({
|
|
136
|
+
type: 'REMOVE',
|
|
137
|
+
path: 'enableAPIKey'
|
|
138
|
+
});
|
|
139
|
+
if (result.doc?.updatedAt) {
|
|
140
|
+
setData(result.doc);
|
|
141
|
+
setLastUpdateTime(new Date(result.doc.updatedAt).getTime());
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
} catch {
|
|
145
|
+
toast.error('Failed to update the API key.');
|
|
146
|
+
return false;
|
|
86
147
|
}
|
|
87
|
-
setTimeout(() => {
|
|
88
|
-
setHighlightedField(true);
|
|
89
|
-
}, 1);
|
|
90
148
|
};
|
|
91
|
-
const {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
149
|
+
const generateKey = async () => {
|
|
150
|
+
const key = uuidv4();
|
|
151
|
+
if (!id) {
|
|
152
|
+
setValue(key, true);
|
|
153
|
+
setShowCopyWarning(true);
|
|
154
|
+
setShowKey(true);
|
|
155
|
+
highlightField();
|
|
156
|
+
return true;
|
|
98
157
|
}
|
|
99
|
-
if (!
|
|
100
|
-
|
|
158
|
+
if (!(await updateKey(key))) {
|
|
159
|
+
return false;
|
|
101
160
|
}
|
|
102
|
-
|
|
161
|
+
setRevealedKey(key);
|
|
162
|
+
setShowCopyWarning(true);
|
|
163
|
+
setShowKey(true);
|
|
164
|
+
highlightField();
|
|
165
|
+
return true;
|
|
166
|
+
};
|
|
167
|
+
const revokeKey = async () => {
|
|
168
|
+
if (!(await updateKey(null))) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
setRevealedKey(null);
|
|
172
|
+
setHasUpdatedPersistedAPIKey(false);
|
|
173
|
+
setHighlightedField(false);
|
|
174
|
+
setShowCopyWarning(false);
|
|
175
|
+
setShowKey(false);
|
|
176
|
+
toast.success('API key revoked successfully.');
|
|
177
|
+
};
|
|
178
|
+
const revealKey = async () => {
|
|
179
|
+
if (isRevealing) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
setIsRevealing(true);
|
|
183
|
+
try {
|
|
184
|
+
const response_0 = await fetch(formatAdminURL({
|
|
185
|
+
apiRoute: config.routes.api,
|
|
186
|
+
path: `/${collectionSlug}/${encodeURIComponent(String(id))}/api-key/reveal`
|
|
187
|
+
}), {
|
|
188
|
+
method: 'POST'
|
|
189
|
+
});
|
|
190
|
+
if (!response_0.ok) {
|
|
191
|
+
toast.error('Failed to reveal the API key.');
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const result_0 = await response_0.json();
|
|
195
|
+
setRevealedKey(result_0.apiKey);
|
|
196
|
+
setShowCopyWarning(false);
|
|
197
|
+
setShowKey(true);
|
|
198
|
+
} catch {
|
|
199
|
+
toast.error('Failed to reveal the API key.');
|
|
200
|
+
} finally {
|
|
201
|
+
setIsRevealing(false);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
103
204
|
useEffect(() => {
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
205
|
+
if (wasModified.current && !modified && apiKeyValue) {
|
|
206
|
+
setHasUpdatedPersistedAPIKey(true);
|
|
207
|
+
setHighlightedField(false);
|
|
208
|
+
setRevealedKey(null);
|
|
209
|
+
setShowCopyWarning(false);
|
|
210
|
+
dispatchFields_0({
|
|
211
|
+
type: 'REMOVE',
|
|
212
|
+
path
|
|
213
|
+
});
|
|
214
|
+
setShowKey(false);
|
|
108
215
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
216
|
+
wasModified.current = modified;
|
|
217
|
+
}, [apiKeyValue, dispatchFields_0, modified]);
|
|
113
218
|
return /*#__PURE__*/_jsxs(React.Fragment, {
|
|
114
219
|
children: [/*#__PURE__*/_jsxs("div", {
|
|
115
220
|
className: [fieldBaseClass, 'api-key', 'read-only'].filter(Boolean).join(' '),
|
|
116
|
-
children: [
|
|
117
|
-
className: `${baseClass}
|
|
221
|
+
children: [/*#__PURE__*/_jsxs("label", {
|
|
222
|
+
className: `${baseClass}__label field-label`,
|
|
223
|
+
htmlFor: "apiKey",
|
|
224
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
225
|
+
children: apiKeyLabel
|
|
226
|
+
}), apiKeyValue && /*#__PURE__*/_jsx(CopyToClipboard, {
|
|
227
|
+
value: apiKeyValue
|
|
228
|
+
})]
|
|
229
|
+
}), /*#__PURE__*/_jsxs("div", {
|
|
230
|
+
className: [`${baseClass}__input-wrap`, !readOnly && hasPersistedAPIKey && `${baseClass}__input-wrap--has-regenerate`, highlightedField && `${baseClass}__input-wrap--highlighted`].filter(Boolean).join(' '),
|
|
118
231
|
children: [/*#__PURE__*/_jsx("input", {
|
|
119
232
|
"aria-label": apiKeyLabel,
|
|
120
|
-
className: highlightedField ? 'highlight' : undefined,
|
|
121
233
|
disabled: true,
|
|
122
234
|
id: "apiKey",
|
|
123
235
|
name: "apiKey",
|
|
124
|
-
type: showKey ? '
|
|
125
|
-
value:
|
|
126
|
-
}), /*#__PURE__*/
|
|
236
|
+
type: apiKeyValue && !showKey ? 'password' : 'text',
|
|
237
|
+
value: apiKeyValue || (hasPersistedAPIKey ? maskedAPIKey : '')
|
|
238
|
+
}), (apiKeyValue || canRevealPersistedAPIKey || !readOnly && hasPersistedAPIKey) && /*#__PURE__*/_jsxs("div", {
|
|
127
239
|
className: `${baseClass}__toggle-button-wrap`,
|
|
128
|
-
children: /*#__PURE__*/_jsx(Button, {
|
|
240
|
+
children: [(apiKeyValue || canRevealPersistedAPIKey) && /*#__PURE__*/_jsx(Button, {
|
|
241
|
+
"aria-label": canRevealPersistedAPIKey ? 'Reveal API key' : 'Toggle API key visibility',
|
|
129
242
|
buttonStyle: "none",
|
|
130
|
-
className: `${baseClass}
|
|
131
|
-
|
|
243
|
+
className: [`${baseClass}__visibility-button`, !readOnly && hasPersistedAPIKey && `${baseClass}__visibility-button--with-regenerate`].filter(Boolean).join(' '),
|
|
244
|
+
disabled: isRevealing,
|
|
245
|
+
extraButtonProps: {
|
|
246
|
+
'aria-busy': isRevealing
|
|
247
|
+
},
|
|
248
|
+
icon: isRevealing ? /*#__PURE__*/_jsx(Spinner, {
|
|
249
|
+
loadingText: null,
|
|
250
|
+
size: "sm"
|
|
251
|
+
}) : /*#__PURE__*/_jsx(EyeIcon, {
|
|
132
252
|
active: showKey
|
|
133
253
|
}),
|
|
134
|
-
|
|
135
|
-
|
|
254
|
+
id: canRevealPersistedAPIKey ? 'reveal-api-key' : 'toggle-api-key-visibility',
|
|
255
|
+
onClick: canRevealPersistedAPIKey ? revealKey : () => setShowKey(previous => !previous)
|
|
256
|
+
}), !readOnly && hasPersistedAPIKey && /*#__PURE__*/_jsx(APIKeyGenerationModal, {
|
|
257
|
+
highlightField: highlightField,
|
|
258
|
+
icon: /*#__PURE__*/_jsx(RefreshIcon, {}),
|
|
259
|
+
id: "regenerate-api-key",
|
|
260
|
+
setKey: generateKey
|
|
261
|
+
})]
|
|
136
262
|
})]
|
|
263
|
+
}), apiKeyValue && showCopyWarning && /*#__PURE__*/_jsx(FieldDescription, {
|
|
264
|
+
description: reveal ? 'Make sure to copy your API key. You may not have access to reveal it again.' : 'Make sure to copy your API key. It will not be displayed again.',
|
|
265
|
+
path: path
|
|
137
266
|
})]
|
|
138
|
-
}), !readOnly && /*#__PURE__*/_jsx(
|
|
267
|
+
}), !readOnly && !apiKeyValue && !hasPersistedAPIKey && (id ? /*#__PURE__*/_jsx(APIKeyGenerationModal, {
|
|
139
268
|
highlightField: highlightField,
|
|
140
|
-
|
|
269
|
+
id: "generate-api-key",
|
|
270
|
+
setKey: generateKey,
|
|
271
|
+
willInvalidateExistingKey: false
|
|
272
|
+
}) : /*#__PURE__*/_jsx(Button, {
|
|
273
|
+
buttonStyle: "secondary",
|
|
274
|
+
id: "generate-api-key",
|
|
275
|
+
onClick: () => void generateKey(),
|
|
276
|
+
size: "small",
|
|
277
|
+
children: t('authentication:generateNewAPIKey')
|
|
278
|
+
})), !readOnly && hasPersistedAPIKey && /*#__PURE__*/_jsxs("div", {
|
|
279
|
+
className: `${baseClass}__actions`,
|
|
280
|
+
children: [/*#__PURE__*/_jsx(Button, {
|
|
281
|
+
buttonStyle: "secondary",
|
|
282
|
+
className: `${baseClass}__revoke-button`,
|
|
283
|
+
id: "revoke-api-key",
|
|
284
|
+
onClick: () => toggleModal(revokeModalSlug),
|
|
285
|
+
size: "small",
|
|
286
|
+
children: "Revoke API key"
|
|
287
|
+
}), /*#__PURE__*/_jsx(ConfirmationModal, {
|
|
288
|
+
body: /*#__PURE__*/_jsxs("span", {
|
|
289
|
+
children: ["Are you sure you want to revoke the API key for user ", /*#__PURE__*/_jsx("strong", {
|
|
290
|
+
children: id
|
|
291
|
+
}), "? The key will no longer be usable, and this action cannot be undone."]
|
|
292
|
+
}),
|
|
293
|
+
confirmLabel: "Revoke",
|
|
294
|
+
heading: "Revoke API key?",
|
|
295
|
+
modalSlug: revokeModalSlug,
|
|
296
|
+
onConfirm: revokeKey
|
|
297
|
+
})]
|
|
141
298
|
})]
|
|
142
299
|
});
|
|
143
300
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"APIKey.js","names":["getTranslation","text","React","useEffect","useMemo","useState","v4","uuidv4","Button","CopyToClipboard","GenerateConfirmation","useFormFields","useField","EyeIcon","useConfig","useDocumentInfo","useTranslation","path","baseClass","fieldBaseClass","APIKey","enabled","readOnly","initialAPIKey","highlightedField","setHighlightedField","showKey","setShowKey","i18n","t","config","getEntityConfig","collectionSlug","apiKey","fields","apiKeyField","find","field","name","validate","val","type","blockData","data","event","maxLength","minLength","preferences","req","payload","siblingData","apiKeyValue","value","apiKeyLabel","label","APIKeyLabel","_jsxs","className","htmlFor","_jsx","fieldType","highlightField","setTimeout","setValue","Fragment","filter","Boolean","join","undefined","disabled","id","buttonStyle","icon","active","onClick","prev","setKey"],"sources":["../../../../src/views/Edit/Auth/APIKey.tsx"],"sourcesContent":["'use client'\nimport type { PayloadRequest, TextFieldClient } from 'payload'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport { text } from 'payload/shared'\nimport React, { useEffect, useMemo, useState } from 'react'\nimport { v4 as uuidv4 } from 'uuid'\n\nimport { Button } from '../../../elements/Button/index.js'\nimport { CopyToClipboard } from '../../../elements/CopyToClipboard/index.js'\nimport { GenerateConfirmation } from '../../../elements/GenerateConfirmation/index.js'\nimport { useFormFields } from '../../../forms/Form/context.js'\nimport { useField } from '../../../forms/useField/index.js'\nimport { EyeIcon } from '../../../icons/Eye/index.js'\nimport { useConfig } from '../../../providers/Config/index.js'\nimport { useDocumentInfo } from '../../../providers/DocumentInfo/index.js'\nimport { useTranslation } from '../../../providers/Translation/index.js'\n\nconst path = 'apiKey'\nconst baseClass = 'api-key'\nconst fieldBaseClass = 'field-type'\n\nexport const APIKey: React.FC<{ readonly enabled: boolean; readonly readOnly?: boolean }> = ({\n enabled,\n readOnly,\n}) => {\n const [initialAPIKey] = useState(uuidv4())\n const [highlightedField, setHighlightedField] = useState(false)\n const [showKey, setShowKey] = useState(false)\n const { i18n, t } = useTranslation()\n const { config, getEntityConfig } = useConfig()\n const { collectionSlug } = useDocumentInfo()\n\n const apiKey = useFormFields(([fields]) => (fields && fields[path]) || null)\n\n const apiKeyField: TextFieldClient = getEntityConfig({ collectionSlug })?.fields?.find(\n (field) => 'name' in field && field.name === 'apiKey',\n ) as TextFieldClient\n\n const validate = (val) =>\n text(val, {\n name: 'apiKey',\n type: 'text',\n blockData: {},\n data: {},\n event: 'onChange',\n maxLength: 48,\n minLength: 24,\n path: ['apiKey'],\n preferences: { fields: {} },\n req: {\n payload: {\n config,\n },\n t,\n } as unknown as PayloadRequest,\n siblingData: {},\n })\n\n const apiKeyValue = apiKey?.value\n\n const apiKeyLabel = useMemo(() => {\n let label: Record<string, string> | string = 'API Key'\n\n if (apiKeyField?.label) {\n label = apiKeyField.label\n }\n\n return getTranslation(label, i18n)\n }, [apiKeyField, i18n])\n\n const APIKeyLabel = useMemo(\n () => (\n <label className={`${baseClass}__label field-label`} htmlFor=\"apiKey\">\n <span>{apiKeyLabel}</span>\n <CopyToClipboard value={apiKeyValue as string} />\n </label>\n ),\n [apiKeyLabel, apiKeyValue],\n )\n\n const fieldType = useField({\n path: 'apiKey',\n validate,\n })\n\n const highlightField = () => {\n if (highlightedField) {\n setHighlightedField(false)\n }\n setTimeout(() => {\n setHighlightedField(true)\n }, 1)\n }\n\n const { setValue, value } = fieldType\n\n useEffect(() => {\n if (!apiKeyValue && enabled) {\n setValue(initialAPIKey)\n }\n if (!enabled && apiKeyValue) {\n setValue(null)\n }\n }, [apiKeyValue, enabled, setValue, initialAPIKey])\n\n useEffect(() => {\n if (highlightedField) {\n setTimeout(() => {\n setHighlightedField(false)\n }, 10000)\n }\n }, [highlightedField])\n\n if (!enabled) {\n return null\n }\n\n return (\n <React.Fragment>\n <div className={[fieldBaseClass, 'api-key', 'read-only'].filter(Boolean).join(' ')}>\n {APIKeyLabel}\n <div className={`${baseClass}__input-wrap`}>\n <input\n aria-label={apiKeyLabel}\n className={highlightedField ? 'highlight' : undefined}\n disabled\n id=\"apiKey\"\n name=\"apiKey\"\n type={showKey ? 'text' : 'password'}\n value={(value as string) || ''}\n />\n <div className={`${baseClass}__toggle-button-wrap`}>\n <Button\n buttonStyle=\"none\"\n className={`${baseClass}__toggle-button`}\n icon={<EyeIcon active={showKey} />}\n onClick={() => setShowKey((prev) => !prev)}\n />\n </div>\n </div>\n </div>\n {!readOnly && (\n <GenerateConfirmation highlightField={highlightField} setKey={() => setValue(uuidv4())} />\n )}\n </React.Fragment>\n )\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"APIKey.js","names":["useModal","getTranslation","formatAdminURL","text","React","useEffect","useMemo","useRef","useState","toast","v4","uuidv4","Button","ConfirmationModal","CopyToClipboard","Spinner","FieldDescription","useFormFields","useFormModified","useField","EyeIcon","RefreshIcon","useConfig","useDocumentInfo","useLocale","useTranslation","APIKeyGenerationModal","path","baseClass","fieldBaseClass","maskedAPIKey","repeat","APIKey","readOnly","reveal","highlightedField","setHighlightedField","hasUpdatedPersistedAPIKey","setHasUpdatedPersistedAPIKey","isRevealing","setIsRevealing","revealedKey","setRevealedKey","showCopyWarning","setShowCopyWarning","showKey","setShowKey","modified","wasModified","i18n","t","toggleModal","config","getEntityConfig","id","collectionSlug","setData","setLastUpdateTime","code","locale","revokeModalSlug","hasAPIKey","fields","dispatchFields","apiKeyField","find","field","name","validate","val","type","blockData","data","event","maxLength","minLength","preferences","req","payload","siblingData","setValue","value","apiKeyValue","hasPersistedAPIKey","Boolean","canRevealPersistedAPIKey","apiKeyLabel","label","highlightField","updateKey","apiKey","response","fetch","apiRoute","routes","api","encodeURIComponent","String","body","JSON","stringify","enableAPIKey","headers","method","ok","Error","result","json","doc","updatedAt","Date","getTime","error","generateKey","key","revokeKey","success","revealKey","current","_jsxs","Fragment","className","filter","join","htmlFor","_jsx","disabled","buttonStyle","extraButtonProps","icon","loadingText","size","active","onClick","previous","setKey","description","willInvalidateExistingKey","confirmLabel","heading","modalSlug","onConfirm"],"sources":["../../../../src/views/Edit/Auth/APIKey.tsx"],"sourcesContent":["'use client'\nimport type { PayloadRequest, TextFieldClient } from 'payload'\n\nimport { useModal } from '@faceless-ui/modal'\nimport { getTranslation } from '@payloadcms/translations'\nimport { formatAdminURL, text } from 'payload/shared'\nimport React, { useEffect, useMemo, useRef, useState } from 'react'\nimport { toast } from 'sonner'\nimport { v4 as uuidv4 } from 'uuid'\n\nimport { Button } from '../../../elements/Button/index.js'\nimport { ConfirmationModal } from '../../../elements/ConfirmationModal/index.js'\nimport { CopyToClipboard } from '../../../elements/CopyToClipboard/index.js'\nimport { Spinner } from '../../../elements/Spinner/index.js'\nimport { FieldDescription } from '../../../fields/FieldDescription/index.js'\nimport { useFormFields, useFormModified } from '../../../forms/Form/context.js'\nimport { useField } from '../../../forms/useField/index.js'\nimport { EyeIcon } from '../../../icons/Eye/index.js'\nimport { RefreshIcon } from '../../../icons/Refresh/index.js'\nimport { useConfig } from '../../../providers/Config/index.js'\nimport { useDocumentInfo } from '../../../providers/DocumentInfo/index.js'\nimport { useLocale } from '../../../providers/Locale/index.js'\nimport { useTranslation } from '../../../providers/Translation/index.js'\nimport { APIKeyGenerationModal } from './APIKeyGenerationModal.js'\n\nconst path = 'apiKey'\nconst baseClass = 'api-key'\nconst fieldBaseClass = 'field-type'\nconst maskedAPIKey = '•'.repeat(24)\n\nexport const APIKey: React.FC<{ readonly readOnly?: boolean; readonly reveal?: boolean }> = ({\n readOnly,\n reveal,\n}) => {\n const [highlightedField, setHighlightedField] = useState(false)\n const [hasUpdatedPersistedAPIKey, setHasUpdatedPersistedAPIKey] = useState<boolean | null>(null)\n const [isRevealing, setIsRevealing] = useState(false)\n const [revealedKey, setRevealedKey] = useState<null | string>(null)\n const [showCopyWarning, setShowCopyWarning] = useState(false)\n const [showKey, setShowKey] = useState(false)\n const modified = useFormModified()\n const wasModified = useRef(modified)\n const { i18n, t } = useTranslation()\n const { toggleModal } = useModal()\n const { config, getEntityConfig } = useConfig()\n const { id, collectionSlug, setData, setLastUpdateTime } = useDocumentInfo()\n const { code: locale } = useLocale()\n const revokeModalSlug = `revoke-api-key-${id}`\n\n const hasAPIKey = useFormFields(([fields]) => (fields && fields.hasAPIKey) || null)\n const dispatchFields = useFormFields(([, dispatchFields]) => dispatchFields)\n\n const apiKeyField: TextFieldClient = getEntityConfig({ collectionSlug })?.fields?.find(\n (field) => 'name' in field && field.name === 'apiKey',\n ) as TextFieldClient\n const validate = (val) =>\n text(val, {\n name: 'apiKey',\n type: 'text',\n blockData: {},\n data: {},\n event: 'onChange',\n maxLength: 48,\n minLength: 24,\n path: ['apiKey'],\n preferences: { fields: {} },\n req: {\n payload: {\n config,\n },\n t,\n } as unknown as PayloadRequest,\n siblingData: {},\n })\n\n const { setValue, value } = useField({\n path,\n validate,\n })\n const apiKeyValue = revealedKey || (value as null | string | undefined)\n const hasPersistedAPIKey =\n hasUpdatedPersistedAPIKey ?? Boolean(hasAPIKey?.value as boolean | undefined)\n const canRevealPersistedAPIKey = reveal && hasPersistedAPIKey && !revealedKey\n\n const apiKeyLabel = useMemo(() => {\n let label: Record<string, string> | string = 'API Key'\n\n if (apiKeyField?.label) {\n label = apiKeyField.label\n }\n\n return getTranslation(label, i18n)\n }, [apiKeyField, i18n])\n\n const highlightField = () => {\n setHighlightedField(true)\n }\n\n const updateKey = async (apiKey: null | string) => {\n if (!id) {\n return false\n }\n\n try {\n const response = await fetch(\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${collectionSlug}/${encodeURIComponent(String(id))}?depth=0&fallback-locale=null&locale=${locale}`,\n }),\n {\n body: JSON.stringify({\n apiKey,\n // The `enableAPIKey` field is for backward compatibility only and will be removed in v4.\n enableAPIKey: Boolean(apiKey),\n }),\n headers: { 'Content-Type': 'application/json' },\n method: 'PATCH',\n },\n )\n\n if (!response.ok) {\n throw new Error('API key update failed')\n }\n\n const result = await response.json()\n\n setHasUpdatedPersistedAPIKey(Boolean(apiKey))\n dispatchFields({ type: 'REMOVE', path })\n // The `enableAPIKey` field is for backward compatibility only and will be removed in v4.\n dispatchFields({ type: 'REMOVE', path: 'enableAPIKey' })\n\n if (result.doc?.updatedAt) {\n setData(result.doc)\n setLastUpdateTime(new Date(result.doc.updatedAt).getTime())\n }\n\n return true\n } catch {\n toast.error('Failed to update the API key.')\n return false\n }\n }\n\n const generateKey = async () => {\n const key = uuidv4()\n\n if (!id) {\n setValue(key, true)\n setShowCopyWarning(true)\n setShowKey(true)\n highlightField()\n\n return true\n }\n\n if (!(await updateKey(key))) {\n return false\n }\n\n setRevealedKey(key)\n setShowCopyWarning(true)\n setShowKey(true)\n highlightField()\n\n return true\n }\n\n const revokeKey = async () => {\n if (!(await updateKey(null))) {\n return\n }\n\n setRevealedKey(null)\n setHasUpdatedPersistedAPIKey(false)\n setHighlightedField(false)\n setShowCopyWarning(false)\n setShowKey(false)\n toast.success('API key revoked successfully.')\n }\n\n const revealKey = async () => {\n if (isRevealing) {\n return\n }\n\n setIsRevealing(true)\n\n try {\n const response = await fetch(\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${collectionSlug}/${encodeURIComponent(String(id))}/api-key/reveal`,\n }),\n { method: 'POST' },\n )\n\n if (!response.ok) {\n toast.error('Failed to reveal the API key.')\n return\n }\n\n const result = await response.json()\n\n setRevealedKey(result.apiKey)\n setShowCopyWarning(false)\n setShowKey(true)\n } catch {\n toast.error('Failed to reveal the API key.')\n } finally {\n setIsRevealing(false)\n }\n }\n\n useEffect(() => {\n if (wasModified.current && !modified && apiKeyValue) {\n setHasUpdatedPersistedAPIKey(true)\n setHighlightedField(false)\n setRevealedKey(null)\n setShowCopyWarning(false)\n dispatchFields({ type: 'REMOVE', path })\n setShowKey(false)\n }\n\n wasModified.current = modified\n }, [apiKeyValue, dispatchFields, modified])\n\n return (\n <React.Fragment>\n <div className={[fieldBaseClass, 'api-key', 'read-only'].filter(Boolean).join(' ')}>\n <label className={`${baseClass}__label field-label`} htmlFor=\"apiKey\">\n <span>{apiKeyLabel}</span>\n {apiKeyValue && <CopyToClipboard value={apiKeyValue} />}\n </label>\n <div\n className={[\n `${baseClass}__input-wrap`,\n !readOnly && hasPersistedAPIKey && `${baseClass}__input-wrap--has-regenerate`,\n highlightedField && `${baseClass}__input-wrap--highlighted`,\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <input\n aria-label={apiKeyLabel}\n disabled\n id=\"apiKey\"\n name=\"apiKey\"\n type={apiKeyValue && !showKey ? 'password' : 'text'}\n value={apiKeyValue || (hasPersistedAPIKey ? maskedAPIKey : '')}\n />\n {(apiKeyValue || canRevealPersistedAPIKey || (!readOnly && hasPersistedAPIKey)) && (\n <div className={`${baseClass}__toggle-button-wrap`}>\n {(apiKeyValue || canRevealPersistedAPIKey) && (\n <Button\n aria-label={\n canRevealPersistedAPIKey ? 'Reveal API key' : 'Toggle API key visibility'\n }\n buttonStyle=\"none\"\n className={[\n `${baseClass}__visibility-button`,\n !readOnly &&\n hasPersistedAPIKey &&\n `${baseClass}__visibility-button--with-regenerate`,\n ]\n .filter(Boolean)\n .join(' ')}\n disabled={isRevealing}\n extraButtonProps={{ 'aria-busy': isRevealing }}\n icon={\n isRevealing ? (\n <Spinner loadingText={null} size=\"sm\" />\n ) : (\n <EyeIcon active={showKey} />\n )\n }\n id={canRevealPersistedAPIKey ? 'reveal-api-key' : 'toggle-api-key-visibility'}\n onClick={\n canRevealPersistedAPIKey ? revealKey : () => setShowKey((previous) => !previous)\n }\n />\n )}\n {!readOnly && hasPersistedAPIKey && (\n <APIKeyGenerationModal\n highlightField={highlightField}\n icon={<RefreshIcon />}\n id=\"regenerate-api-key\"\n setKey={generateKey}\n />\n )}\n </div>\n )}\n </div>\n {apiKeyValue && showCopyWarning && (\n <FieldDescription\n description={\n reveal\n ? 'Make sure to copy your API key. You may not have access to reveal it again.'\n : 'Make sure to copy your API key. It will not be displayed again.'\n }\n path={path}\n />\n )}\n </div>\n {!readOnly &&\n !apiKeyValue &&\n !hasPersistedAPIKey &&\n (id ? (\n <APIKeyGenerationModal\n highlightField={highlightField}\n id=\"generate-api-key\"\n setKey={generateKey}\n willInvalidateExistingKey={false}\n />\n ) : (\n <Button\n buttonStyle=\"secondary\"\n id=\"generate-api-key\"\n onClick={() => void generateKey()}\n size=\"small\"\n >\n {t('authentication:generateNewAPIKey')}\n </Button>\n ))}\n {!readOnly && hasPersistedAPIKey && (\n <div className={`${baseClass}__actions`}>\n <Button\n buttonStyle=\"secondary\"\n className={`${baseClass}__revoke-button`}\n id=\"revoke-api-key\"\n onClick={() => toggleModal(revokeModalSlug)}\n size=\"small\"\n >\n Revoke API key\n </Button>\n <ConfirmationModal\n body={\n <span>\n Are you sure you want to revoke the API key for user <strong>{id}</strong>? The key\n will no longer be usable, and this action cannot be undone.\n </span>\n }\n confirmLabel=\"Revoke\"\n heading=\"Revoke API key?\"\n modalSlug={revokeModalSlug}\n onConfirm={revokeKey}\n />\n </div>\n )}\n </React.Fragment>\n )\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type APIKeyGenerationModalProps = {
|
|
3
|
+
highlightField: (Boolean: any) => void;
|
|
4
|
+
icon?: React.ReactNode;
|
|
5
|
+
id?: string;
|
|
6
|
+
setKey: () => boolean | Promise<boolean | void> | void;
|
|
7
|
+
willInvalidateExistingKey?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type GenerateConfirmationProps = APIKeyGenerationModalProps;
|
|
10
|
+
export declare function APIKeyGenerationModal(props: APIKeyGenerationModalProps): React.JSX.Element;
|
|
11
|
+
//# sourceMappingURL=APIKeyGenerationModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"APIKeyGenerationModal.d.ts","sourceRoot":"","sources":["../../../../src/views/Edit/Auth/APIKeyGenerationModal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsB,MAAM,OAAO,CAAA;AAS1C,MAAM,MAAM,0BAA0B,GAAG;IACvC,cAAc,EAAE,CAAC,OAAO,KAAA,KAAK,IAAI,CAAA;IACjC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,IAAI,CAAA;IACtD,yBAAyB,CAAC,EAAE,OAAO,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,0BAA0B,CAAA;AAElE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,qBAyDtE"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { c as _c } from "react/compiler-runtime";
|
|
4
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { useModal } from '@faceless-ui/modal';
|
|
6
|
+
import React, { useCallback } from 'react';
|
|
7
|
+
import { toast } from 'sonner';
|
|
8
|
+
import { Button } from '../../../elements/Button/index.js';
|
|
9
|
+
import { ConfirmationModal } from '../../../elements/ConfirmationModal/index.js';
|
|
10
|
+
import { Translation } from '../../../elements/Translation/index.js';
|
|
11
|
+
import { useDocumentInfo } from '../../../providers/DocumentInfo/index.js';
|
|
12
|
+
import { useTranslation } from '../../../providers/Translation/index.js';
|
|
13
|
+
export function APIKeyGenerationModal(props) {
|
|
14
|
+
const $ = _c(16);
|
|
15
|
+
const {
|
|
16
|
+
id,
|
|
17
|
+
highlightField,
|
|
18
|
+
icon,
|
|
19
|
+
setKey,
|
|
20
|
+
willInvalidateExistingKey: t0
|
|
21
|
+
} = props;
|
|
22
|
+
const willInvalidateExistingKey = t0 === undefined ? true : t0;
|
|
23
|
+
const {
|
|
24
|
+
id: documentID
|
|
25
|
+
} = useDocumentInfo();
|
|
26
|
+
const {
|
|
27
|
+
toggleModal
|
|
28
|
+
} = useModal();
|
|
29
|
+
const {
|
|
30
|
+
t
|
|
31
|
+
} = useTranslation();
|
|
32
|
+
const modalSlug = `generate-confirmation-${documentID}`;
|
|
33
|
+
let t1;
|
|
34
|
+
if ($[0] !== highlightField || $[1] !== setKey || $[2] !== t) {
|
|
35
|
+
t1 = async () => {
|
|
36
|
+
if ((await setKey()) === false) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
toast.success(t("authentication:newAPIKeyGenerated"));
|
|
40
|
+
highlightField(true);
|
|
41
|
+
};
|
|
42
|
+
$[0] = highlightField;
|
|
43
|
+
$[1] = setKey;
|
|
44
|
+
$[2] = t;
|
|
45
|
+
$[3] = t1;
|
|
46
|
+
} else {
|
|
47
|
+
t1 = $[3];
|
|
48
|
+
}
|
|
49
|
+
const handleGenerate = t1;
|
|
50
|
+
let t2;
|
|
51
|
+
if ($[4] !== documentID || $[5] !== handleGenerate || $[6] !== icon || $[7] !== id || $[8] !== modalSlug || $[9] !== t || $[10] !== toggleModal || $[11] !== willInvalidateExistingKey) {
|
|
52
|
+
let t3;
|
|
53
|
+
if ($[13] !== modalSlug || $[14] !== toggleModal) {
|
|
54
|
+
t3 = () => {
|
|
55
|
+
toggleModal(modalSlug);
|
|
56
|
+
};
|
|
57
|
+
$[13] = modalSlug;
|
|
58
|
+
$[14] = toggleModal;
|
|
59
|
+
$[15] = t3;
|
|
60
|
+
} else {
|
|
61
|
+
t3 = $[15];
|
|
62
|
+
}
|
|
63
|
+
t2 = _jsxs(React.Fragment, {
|
|
64
|
+
children: [_jsx(Button, {
|
|
65
|
+
"aria-label": icon ? t("authentication:generateNewAPIKey") : undefined,
|
|
66
|
+
buttonStyle: icon ? "none" : "secondary",
|
|
67
|
+
className: icon ? "api-key__regenerate-button" : undefined,
|
|
68
|
+
icon,
|
|
69
|
+
id,
|
|
70
|
+
onClick: t3,
|
|
71
|
+
size: "small",
|
|
72
|
+
children: !icon && t("authentication:generateNewAPIKey")
|
|
73
|
+
}), _jsx(ConfirmationModal, {
|
|
74
|
+
body: willInvalidateExistingKey ? _jsx(Translation, {
|
|
75
|
+
elements: {
|
|
76
|
+
1: _temp
|
|
77
|
+
},
|
|
78
|
+
i18nKey: "authentication:generatingNewAPIKeyWillInvalidate",
|
|
79
|
+
t
|
|
80
|
+
}) : _jsxs("span", {
|
|
81
|
+
children: ["Are you sure you want to generate an API key for user ", _jsx("strong", {
|
|
82
|
+
children: documentID
|
|
83
|
+
}), "? This will take effect immediately."]
|
|
84
|
+
}),
|
|
85
|
+
confirmLabel: t("authentication:generate"),
|
|
86
|
+
heading: t("authentication:confirmGeneration"),
|
|
87
|
+
modalSlug,
|
|
88
|
+
onConfirm: handleGenerate
|
|
89
|
+
})]
|
|
90
|
+
});
|
|
91
|
+
$[4] = documentID;
|
|
92
|
+
$[5] = handleGenerate;
|
|
93
|
+
$[6] = icon;
|
|
94
|
+
$[7] = id;
|
|
95
|
+
$[8] = modalSlug;
|
|
96
|
+
$[9] = t;
|
|
97
|
+
$[10] = toggleModal;
|
|
98
|
+
$[11] = willInvalidateExistingKey;
|
|
99
|
+
$[12] = t2;
|
|
100
|
+
} else {
|
|
101
|
+
t2 = $[12];
|
|
102
|
+
}
|
|
103
|
+
return t2;
|
|
104
|
+
}
|
|
105
|
+
function _temp(t0) {
|
|
106
|
+
const {
|
|
107
|
+
children
|
|
108
|
+
} = t0;
|
|
109
|
+
return _jsx("strong", {
|
|
110
|
+
children
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=APIKeyGenerationModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"APIKeyGenerationModal.js","names":["c","_c","useModal","React","useCallback","toast","Button","ConfirmationModal","Translation","useDocumentInfo","useTranslation","APIKeyGenerationModal","props","$","id","highlightField","icon","setKey","willInvalidateExistingKey","t0","undefined","documentID","toggleModal","t","modalSlug","t1","success","handleGenerate","t2","t3","_jsxs","Fragment","children","_jsx","buttonStyle","className","onClick","size","body","elements","1","_temp","i18nKey","heading","onConfirm"],"sources":["../../../../src/views/Edit/Auth/APIKeyGenerationModal.tsx"],"sourcesContent":["'use client'\nimport { useModal } from '@faceless-ui/modal'\nimport React, { useCallback } from 'react'\nimport { toast } from 'sonner'\n\nimport { Button } from '../../../elements/Button/index.js'\nimport { ConfirmationModal } from '../../../elements/ConfirmationModal/index.js'\nimport { Translation } from '../../../elements/Translation/index.js'\nimport { useDocumentInfo } from '../../../providers/DocumentInfo/index.js'\nimport { useTranslation } from '../../../providers/Translation/index.js'\n\nexport type APIKeyGenerationModalProps = {\n highlightField: (Boolean) => void\n icon?: React.ReactNode\n id?: string\n setKey: () => boolean | Promise<boolean | void> | void\n willInvalidateExistingKey?: boolean\n}\n\nexport type GenerateConfirmationProps = APIKeyGenerationModalProps\n\nexport function APIKeyGenerationModal(props: APIKeyGenerationModalProps) {\n const { id, highlightField, icon, setKey, willInvalidateExistingKey = true } = props\n\n const { id: documentID } = useDocumentInfo()\n const { toggleModal } = useModal()\n const { t } = useTranslation()\n\n const modalSlug = `generate-confirmation-${documentID}`\n\n const handleGenerate = useCallback(async () => {\n if ((await setKey()) === false) {\n return\n }\n\n toast.success(t('authentication:newAPIKeyGenerated'))\n highlightField(true)\n }, [highlightField, setKey, t])\n\n return (\n <React.Fragment>\n <Button\n aria-label={icon ? t('authentication:generateNewAPIKey') : undefined}\n buttonStyle={icon ? 'none' : 'secondary'}\n className={icon ? 'api-key__regenerate-button' : undefined}\n icon={icon}\n id={id}\n onClick={() => {\n toggleModal(modalSlug)\n }}\n size=\"small\"\n >\n {!icon && t('authentication:generateNewAPIKey')}\n </Button>\n <ConfirmationModal\n body={\n willInvalidateExistingKey ? (\n <Translation\n elements={{\n 1: ({ children }) => <strong>{children}</strong>,\n }}\n i18nKey=\"authentication:generatingNewAPIKeyWillInvalidate\"\n t={t}\n />\n ) : (\n <span>\n Are you sure you want to generate an API key for user <strong>{documentID}</strong>?\n This will take effect immediately.\n </span>\n )\n }\n confirmLabel={t('authentication:generate')}\n heading={t('authentication:confirmGeneration')}\n modalSlug={modalSlug}\n onConfirm={handleGenerate}\n />\n </React.Fragment>\n )\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/views/Edit/Auth/index.tsx"],"names":[],"mappings":"AAKA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/views/Edit/Auth/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAoD,MAAM,OAAO,CAAA;AAGxE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAWvC,OAAO,cAAc,CAAA;AAKrB,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAoQhC,CAAA"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { c as _c } from "react/compiler-runtime";
|
|
4
4
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { formatAdminURL, getFieldPermissions } from 'payload/shared';
|
|
6
|
-
import React, {
|
|
6
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
7
7
|
import { toast } from 'sonner';
|
|
8
8
|
import { Button } from '../../../elements/Button/index.js';
|
|
9
9
|
import { EmailAndUsernameFields } from '../../../elements/EmailAndUsername/index.js';
|
|
@@ -34,8 +34,7 @@ export const Auth = props => {
|
|
|
34
34
|
verify
|
|
35
35
|
} = props;
|
|
36
36
|
const [changingPassword, setChangingPassword] = useState(requirePassword);
|
|
37
|
-
const
|
|
38
|
-
const dispatchFields = useFormFields(_temp2);
|
|
37
|
+
const dispatchFields = useFormFields(_temp);
|
|
39
38
|
const modified = useFormModified();
|
|
40
39
|
const {
|
|
41
40
|
i18n,
|
|
@@ -130,10 +129,8 @@ export const Auth = props => {
|
|
|
130
129
|
}
|
|
131
130
|
const enableFields = (!disableLocalStrategy || typeof disableLocalStrategy === "object" && disableLocalStrategy.enableFields === true) && (showUnlock || showPasswordFields);
|
|
132
131
|
const disabled = readOnly || isInitializing || isTrashed;
|
|
133
|
-
const apiKeyPermissions = docPermissions?.fields === true ? true : docPermissions?.fields?.
|
|
134
|
-
const
|
|
135
|
-
const enableAPIKeyReadOnly = readOnly || apiKeyPermissions !== true && !apiKeyPermissions?.update;
|
|
136
|
-
const canReadApiKey = apiKeyPermissions === true || apiKeyPermissions?.read;
|
|
132
|
+
const apiKeyPermissions = docPermissions?.fields === true ? true : docPermissions?.fields?.apiKey;
|
|
133
|
+
const canManageAPIKey = apiKeyPermissions === true || typeof apiKeyPermissions === "object" && Boolean(apiKeyPermissions?.[operation]);
|
|
137
134
|
let t2;
|
|
138
135
|
bb0: {
|
|
139
136
|
if (docPermissions) {
|
|
@@ -237,7 +234,7 @@ export const Auth = props => {
|
|
|
237
234
|
}
|
|
238
235
|
useEffect(t5, t6);
|
|
239
236
|
const showAuthBlock = enableFields;
|
|
240
|
-
const showAPIKeyBlock = useAPIKey &&
|
|
237
|
+
const showAPIKeyBlock = useAPIKey && canManageAPIKey;
|
|
241
238
|
const showVerifyBlock = verify && isEditing;
|
|
242
239
|
if (!(showAuthBlock || showAPIKeyBlock || showVerifyBlock)) {
|
|
243
240
|
return null;
|
|
@@ -301,24 +298,11 @@ export const Auth = props => {
|
|
|
301
298
|
children: t("authentication:forceUnlock")
|
|
302
299
|
})]
|
|
303
300
|
})]
|
|
304
|
-
}),
|
|
301
|
+
}), showAPIKeyBlock && _jsx("div", {
|
|
305
302
|
className: `${baseClass}__api-key`,
|
|
306
|
-
children:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
name: "enableAPIKey",
|
|
310
|
-
admin: {
|
|
311
|
-
disabled,
|
|
312
|
-
readOnly: enableAPIKeyReadOnly
|
|
313
|
-
},
|
|
314
|
-
label: t("authentication:enableAPIKey")
|
|
315
|
-
},
|
|
316
|
-
path: "enableAPIKey",
|
|
317
|
-
schemaPath: `${collectionSlug}.enableAPIKey`
|
|
318
|
-
}), _jsx(APIKey, {
|
|
319
|
-
enabled: !!enableAPIKey?.value,
|
|
320
|
-
readOnly: apiKeyReadOnly
|
|
321
|
-
})]
|
|
303
|
+
children: _jsx(APIKey, {
|
|
304
|
+
readOnly: disabled,
|
|
305
|
+
reveal: typeof useAPIKey === "object" && useAPIKey.reveal === true
|
|
322
306
|
})
|
|
323
307
|
}), verify && isEditing && _jsx(CheckboxField, {
|
|
324
308
|
field: {
|
|
@@ -334,11 +318,7 @@ export const Auth = props => {
|
|
|
334
318
|
})]
|
|
335
319
|
});
|
|
336
320
|
};
|
|
337
|
-
function _temp(
|
|
338
|
-
const [fields] = t0;
|
|
339
|
-
return fields && fields?.enableAPIKey || null;
|
|
340
|
-
}
|
|
341
|
-
function _temp2(reducer) {
|
|
321
|
+
function _temp(reducer) {
|
|
342
322
|
return reducer[1];
|
|
343
323
|
}
|
|
344
324
|
//# sourceMappingURL=index.js.map
|