generates secure API key within admin UI
This commit is contained in:
@@ -7,5 +7,7 @@ module.exports = [
|
||||
{
|
||||
name: 'apiKey',
|
||||
type: 'text',
|
||||
minLength: 24,
|
||||
maxLength: 48,
|
||||
},
|
||||
];
|
||||
|
||||
71
src/client/components/forms/field-types/Auth/APIKey.js
Normal file
71
src/client/components/forms/field-types/Auth/APIKey.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import useFieldType from '../../useFieldType';
|
||||
import Label from '../../Label';
|
||||
import Button from '../../../elements/Button';
|
||||
import generateAPIKey from './generateAPIKey';
|
||||
import { text } from '../../../../../fields/validations';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const path = 'apiKey';
|
||||
|
||||
const validate = val => text(val, { minLength: 24, maxLength: 48 });
|
||||
|
||||
const APIKey = (props) => {
|
||||
const {
|
||||
initialData,
|
||||
} = props;
|
||||
|
||||
const fieldType = useFieldType({
|
||||
path: 'apiKey',
|
||||
initialData: initialData || generateAPIKey(),
|
||||
validate,
|
||||
});
|
||||
|
||||
const {
|
||||
value,
|
||||
setValue,
|
||||
} = fieldType;
|
||||
|
||||
const classes = [
|
||||
'field-type',
|
||||
'api-key',
|
||||
'read-only',
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={classes}>
|
||||
<Label
|
||||
htmlFor={path}
|
||||
label="API Key"
|
||||
/>
|
||||
<input
|
||||
value={value || ''}
|
||||
disabled="disabled"
|
||||
type="text"
|
||||
id="apiKey"
|
||||
name="apiKey"
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => setValue(generateAPIKey())}
|
||||
size="small"
|
||||
buttonStyle="secondary"
|
||||
>
|
||||
Generate new API Key
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
APIKey.defaultProps = {
|
||||
initialData: undefined,
|
||||
};
|
||||
|
||||
APIKey.propTypes = {
|
||||
initialData: PropTypes.string,
|
||||
};
|
||||
|
||||
export default APIKey;
|
||||
@@ -0,0 +1,16 @@
|
||||
function generateAPIKey() {
|
||||
let pass = '';
|
||||
const str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
+ 'abcdefghijklmnopqrstuvwxyz0123456789@#$';
|
||||
|
||||
for (let i = 1; i <= 36; i += 1) {
|
||||
const char = Math.floor(Math.random()
|
||||
* str.length + 1);
|
||||
|
||||
pass += str.charAt(char);
|
||||
}
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
export default generateAPIKey;
|
||||
@@ -8,6 +8,7 @@ import Button from '../../../elements/Button';
|
||||
import ConfirmPassword from '../ConfirmPassword';
|
||||
import useForm from '../../Form/useForm';
|
||||
import CopyToClipboard from '../../../elements/CopyToClipboard';
|
||||
import APIKey from './APIKey';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@@ -76,14 +77,7 @@ const Auth = (props) => {
|
||||
name="enableAPIKey"
|
||||
/>
|
||||
{enableAPIKey?.value && (
|
||||
<div className={`${baseClass}__api-key-generator`}>
|
||||
<Text
|
||||
label={APIKeyLabel}
|
||||
initialData={initialData?.apiKey}
|
||||
name="apiKey"
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
<APIKey initialData={initialData?.apiKey} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import '../../../../scss/styles.scss';
|
||||
@import '../shared.scss';
|
||||
|
||||
.auth-fields {
|
||||
padding: base(2) base(2) base(1.5);
|
||||
@@ -13,3 +14,9 @@
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.field-type.api-key {
|
||||
input {
|
||||
@include formInput;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import useFieldType from '../../useFieldType';
|
||||
import withCondition from '../../withCondition';
|
||||
@@ -21,16 +21,23 @@ const Text = (props) => {
|
||||
label,
|
||||
placeholder,
|
||||
readOnly,
|
||||
minLength,
|
||||
maxLength,
|
||||
} = props;
|
||||
|
||||
const path = pathFromProps || name;
|
||||
|
||||
const memoizedValidate = useCallback((value) => {
|
||||
const validationResult = validate(value, { minLength, maxLength });
|
||||
return validationResult;
|
||||
}, [validate, maxLength, minLength]);
|
||||
|
||||
const fieldType = useFieldType({
|
||||
path,
|
||||
required,
|
||||
initialData,
|
||||
defaultValue,
|
||||
validate,
|
||||
validate: memoizedValidate,
|
||||
enableDebouncedValue: true,
|
||||
});
|
||||
|
||||
@@ -89,6 +96,8 @@ Text.defaultProps = {
|
||||
style: {},
|
||||
validate: text,
|
||||
path: '',
|
||||
minLength: undefined,
|
||||
maxLength: undefined,
|
||||
};
|
||||
|
||||
Text.propTypes = {
|
||||
@@ -106,6 +115,8 @@ Text.propTypes = {
|
||||
PropTypes.string,
|
||||
PropTypes.node,
|
||||
]),
|
||||
minLength: PropTypes.number,
|
||||
maxLength: PropTypes.number,
|
||||
};
|
||||
|
||||
export default withCondition(Text);
|
||||
|
||||
Reference in New Issue
Block a user