mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 20:59:44 +02:00
feat: Use environment variables for default admin configuration
This commit is contained in:
parent
2dfa79801f
commit
e59535b9b4
20 changed files with 224 additions and 121 deletions
|
@ -1,4 +1,5 @@
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
import pickBy from 'lodash/pickBy';
|
import pickBy from 'lodash/pickBy';
|
||||||
import React, { useCallback, useMemo, useRef } from 'react';
|
import React, { useCallback, useMemo, useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
@ -9,7 +10,7 @@ import { useForm } from '../../hooks';
|
||||||
|
|
||||||
import styles from './UserInformationEdit.module.scss';
|
import styles from './UserInformationEdit.module.scss';
|
||||||
|
|
||||||
const UserInformationEdit = React.memo(({ defaultData, onUpdate }) => {
|
const UserInformationEdit = React.memo(({ defaultData, isNameEditable, onUpdate }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const [data, handleFieldChange] = useForm(() => ({
|
const [data, handleFieldChange] = useForm(() => ({
|
||||||
|
@ -32,13 +33,17 @@ const UserInformationEdit = React.memo(({ defaultData, onUpdate }) => {
|
||||||
const nameField = useRef(null);
|
const nameField = useRef(null);
|
||||||
|
|
||||||
const handleSubmit = useCallback(() => {
|
const handleSubmit = useCallback(() => {
|
||||||
|
if (isNameEditable) {
|
||||||
if (!cleanData.name) {
|
if (!cleanData.name) {
|
||||||
nameField.current.select();
|
nameField.current.select();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdate(cleanData);
|
onUpdate(cleanData);
|
||||||
}, [onUpdate, cleanData]);
|
} else {
|
||||||
|
onUpdate(omit(cleanData, 'name'));
|
||||||
|
}
|
||||||
|
}, [isNameEditable, onUpdate, cleanData]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
|
@ -48,6 +53,7 @@ const UserInformationEdit = React.memo(({ defaultData, onUpdate }) => {
|
||||||
ref={nameField}
|
ref={nameField}
|
||||||
name="name"
|
name="name"
|
||||||
value={data.name}
|
value={data.name}
|
||||||
|
disabled={!isNameEditable}
|
||||||
className={styles.field}
|
className={styles.field}
|
||||||
onChange={handleFieldChange}
|
onChange={handleFieldChange}
|
||||||
/>
|
/>
|
||||||
|
@ -74,6 +80,7 @@ const UserInformationEdit = React.memo(({ defaultData, onUpdate }) => {
|
||||||
|
|
||||||
UserInformationEdit.propTypes = {
|
UserInformationEdit.propTypes = {
|
||||||
defaultData: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
defaultData: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
|
isNameEditable: PropTypes.bool.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { Popup } from '../lib/custom-ui';
|
||||||
|
|
||||||
import UserInformationEdit from './UserInformationEdit';
|
import UserInformationEdit from './UserInformationEdit';
|
||||||
|
|
||||||
const UserInformationEditStep = React.memo(({ defaultData, onUpdate, onBack, onClose }) => {
|
const UserInformationEditStep = React.memo(
|
||||||
|
({ defaultData, isNameEditable, onUpdate, onBack, onClose }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const handleUpdate = useCallback(
|
const handleUpdate = useCallback(
|
||||||
|
@ -24,14 +25,20 @@ const UserInformationEditStep = React.memo(({ defaultData, onUpdate, onBack, onC
|
||||||
})}
|
})}
|
||||||
</Popup.Header>
|
</Popup.Header>
|
||||||
<Popup.Content>
|
<Popup.Content>
|
||||||
<UserInformationEdit defaultData={defaultData} onUpdate={handleUpdate} />
|
<UserInformationEdit
|
||||||
|
defaultData={defaultData}
|
||||||
|
isNameEditable={isNameEditable}
|
||||||
|
onUpdate={handleUpdate}
|
||||||
|
/>
|
||||||
</Popup.Content>
|
</Popup.Content>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
UserInformationEditStep.propTypes = {
|
UserInformationEditStep.propTypes = {
|
||||||
defaultData: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
defaultData: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
|
isNameEditable: PropTypes.bool.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onBack: PropTypes.func,
|
onBack: PropTypes.func,
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -23,6 +23,7 @@ const AccountPane = React.memo(
|
||||||
phone,
|
phone,
|
||||||
organization,
|
organization,
|
||||||
language,
|
language,
|
||||||
|
isLocked,
|
||||||
isAvatarUpdating,
|
isAvatarUpdating,
|
||||||
usernameUpdateForm,
|
usernameUpdateForm,
|
||||||
emailUpdateForm,
|
emailUpdateForm,
|
||||||
|
@ -74,6 +75,7 @@ const AccountPane = React.memo(
|
||||||
phone,
|
phone,
|
||||||
organization,
|
organization,
|
||||||
}}
|
}}
|
||||||
|
isNameEditable={!isLocked}
|
||||||
onUpdate={onUpdate}
|
onUpdate={onUpdate}
|
||||||
/>
|
/>
|
||||||
<Divider horizontal section>
|
<Divider horizontal section>
|
||||||
|
@ -102,6 +104,8 @@ const AccountPane = React.memo(
|
||||||
value={language || 'auto'}
|
value={language || 'auto'}
|
||||||
onChange={handleLanguageChange}
|
onChange={handleLanguageChange}
|
||||||
/>
|
/>
|
||||||
|
{!isLocked && (
|
||||||
|
<>
|
||||||
<Divider horizontal section>
|
<Divider horizontal section>
|
||||||
<Header as="h4">
|
<Header as="h4">
|
||||||
{t('common.authentication', {
|
{t('common.authentication', {
|
||||||
|
@ -159,6 +163,8 @@ const AccountPane = React.memo(
|
||||||
</Button>
|
</Button>
|
||||||
</UserPasswordEditPopup>
|
</UserPasswordEditPopup>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Tab.Pane>
|
</Tab.Pane>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -172,6 +178,7 @@ AccountPane.propTypes = {
|
||||||
phone: PropTypes.string,
|
phone: PropTypes.string,
|
||||||
organization: PropTypes.string,
|
organization: PropTypes.string,
|
||||||
language: PropTypes.string,
|
language: PropTypes.string,
|
||||||
|
isLocked: PropTypes.bool.isRequired,
|
||||||
isAvatarUpdating: PropTypes.bool.isRequired,
|
isAvatarUpdating: PropTypes.bool.isRequired,
|
||||||
/* eslint-disable react/forbid-prop-types */
|
/* eslint-disable react/forbid-prop-types */
|
||||||
usernameUpdateForm: PropTypes.object.isRequired,
|
usernameUpdateForm: PropTypes.object.isRequired,
|
||||||
|
|
|
@ -16,6 +16,7 @@ const UserSettingsModal = React.memo(
|
||||||
phone,
|
phone,
|
||||||
organization,
|
organization,
|
||||||
language,
|
language,
|
||||||
|
isLocked,
|
||||||
subscribeToOwnCards,
|
subscribeToOwnCards,
|
||||||
isAvatarUpdating,
|
isAvatarUpdating,
|
||||||
usernameUpdateForm,
|
usernameUpdateForm,
|
||||||
|
@ -48,6 +49,7 @@ const UserSettingsModal = React.memo(
|
||||||
phone={phone}
|
phone={phone}
|
||||||
organization={organization}
|
organization={organization}
|
||||||
language={language}
|
language={language}
|
||||||
|
isLocked={isLocked}
|
||||||
isAvatarUpdating={isAvatarUpdating}
|
isAvatarUpdating={isAvatarUpdating}
|
||||||
usernameUpdateForm={usernameUpdateForm}
|
usernameUpdateForm={usernameUpdateForm}
|
||||||
emailUpdateForm={emailUpdateForm}
|
emailUpdateForm={emailUpdateForm}
|
||||||
|
@ -104,6 +106,7 @@ UserSettingsModal.propTypes = {
|
||||||
phone: PropTypes.string,
|
phone: PropTypes.string,
|
||||||
organization: PropTypes.string,
|
organization: PropTypes.string,
|
||||||
language: PropTypes.string,
|
language: PropTypes.string,
|
||||||
|
isLocked: PropTypes.bool.isRequired,
|
||||||
subscribeToOwnCards: PropTypes.bool.isRequired,
|
subscribeToOwnCards: PropTypes.bool.isRequired,
|
||||||
isAvatarUpdating: PropTypes.bool.isRequired,
|
isAvatarUpdating: PropTypes.bool.isRequired,
|
||||||
/* eslint-disable react/forbid-prop-types */
|
/* eslint-disable react/forbid-prop-types */
|
||||||
|
|
|
@ -64,6 +64,7 @@ const ActionsStep = React.memo(
|
||||||
return (
|
return (
|
||||||
<UserInformationEditStep
|
<UserInformationEditStep
|
||||||
defaultData={pick(user, ['name', 'phone', 'organization'])}
|
defaultData={pick(user, ['name', 'phone', 'organization'])}
|
||||||
|
isNameEditable={!user.isLocked}
|
||||||
onUpdate={onUpdate}
|
onUpdate={onUpdate}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
|
@ -135,6 +136,8 @@ const ActionsStep = React.memo(
|
||||||
context: 'title',
|
context: 'title',
|
||||||
})}
|
})}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
{!user.isLocked && (
|
||||||
|
<>
|
||||||
<Menu.Item className={styles.menuItem} onClick={handleEditUsernameClick}>
|
<Menu.Item className={styles.menuItem} onClick={handleEditUsernameClick}>
|
||||||
{t('action.editUsername', {
|
{t('action.editUsername', {
|
||||||
context: 'title',
|
context: 'title',
|
||||||
|
@ -155,6 +158,8 @@ const ActionsStep = React.memo(
|
||||||
context: 'title',
|
context: 'title',
|
||||||
})}
|
})}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Menu>
|
</Menu>
|
||||||
</Popup.Content>
|
</Popup.Content>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -17,6 +17,7 @@ const Item = React.memo(
|
||||||
organization,
|
organization,
|
||||||
phone,
|
phone,
|
||||||
isAdmin,
|
isAdmin,
|
||||||
|
isLocked,
|
||||||
emailUpdateForm,
|
emailUpdateForm,
|
||||||
passwordUpdateForm,
|
passwordUpdateForm,
|
||||||
usernameUpdateForm,
|
usernameUpdateForm,
|
||||||
|
@ -46,7 +47,7 @@ const Item = React.memo(
|
||||||
<Table.Cell>{username || '-'}</Table.Cell>
|
<Table.Cell>{username || '-'}</Table.Cell>
|
||||||
<Table.Cell>{email}</Table.Cell>
|
<Table.Cell>{email}</Table.Cell>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
<Radio toggle checked={isAdmin} onChange={handleIsAdminChange} />
|
<Radio toggle checked={isAdmin} disabled={isLocked} onChange={handleIsAdminChange} />
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell textAlign="right">
|
<Table.Cell textAlign="right">
|
||||||
<ActionsPopup
|
<ActionsPopup
|
||||||
|
@ -57,6 +58,7 @@ const Item = React.memo(
|
||||||
organization,
|
organization,
|
||||||
phone,
|
phone,
|
||||||
isAdmin,
|
isAdmin,
|
||||||
|
isLocked,
|
||||||
emailUpdateForm,
|
emailUpdateForm,
|
||||||
passwordUpdateForm,
|
passwordUpdateForm,
|
||||||
usernameUpdateForm,
|
usernameUpdateForm,
|
||||||
|
@ -88,6 +90,7 @@ Item.propTypes = {
|
||||||
organization: PropTypes.string,
|
organization: PropTypes.string,
|
||||||
phone: PropTypes.string,
|
phone: PropTypes.string,
|
||||||
isAdmin: PropTypes.bool.isRequired,
|
isAdmin: PropTypes.bool.isRequired,
|
||||||
|
isLocked: PropTypes.bool.isRequired,
|
||||||
/* eslint-disable react/forbid-prop-types */
|
/* eslint-disable react/forbid-prop-types */
|
||||||
emailUpdateForm: PropTypes.object.isRequired,
|
emailUpdateForm: PropTypes.object.isRequired,
|
||||||
passwordUpdateForm: PropTypes.object.isRequired,
|
passwordUpdateForm: PropTypes.object.isRequired,
|
||||||
|
|
|
@ -110,6 +110,7 @@ const UsersModal = React.memo(
|
||||||
organization={item.organization}
|
organization={item.organization}
|
||||||
phone={item.phone}
|
phone={item.phone}
|
||||||
isAdmin={item.isAdmin}
|
isAdmin={item.isAdmin}
|
||||||
|
isLocked={item.isLocked}
|
||||||
emailUpdateForm={item.emailUpdateForm}
|
emailUpdateForm={item.emailUpdateForm}
|
||||||
passwordUpdateForm={item.passwordUpdateForm}
|
passwordUpdateForm={item.passwordUpdateForm}
|
||||||
usernameUpdateForm={item.usernameUpdateForm}
|
usernameUpdateForm={item.usernameUpdateForm}
|
||||||
|
|
|
@ -14,6 +14,7 @@ const mapStateToProps = (state) => {
|
||||||
phone,
|
phone,
|
||||||
organization,
|
organization,
|
||||||
language,
|
language,
|
||||||
|
isLocked,
|
||||||
subscribeToOwnCards,
|
subscribeToOwnCards,
|
||||||
isAvatarUpdating,
|
isAvatarUpdating,
|
||||||
emailUpdateForm,
|
emailUpdateForm,
|
||||||
|
@ -29,6 +30,7 @@ const mapStateToProps = (state) => {
|
||||||
phone,
|
phone,
|
||||||
organization,
|
organization,
|
||||||
language,
|
language,
|
||||||
|
isLocked,
|
||||||
subscribeToOwnCards,
|
subscribeToOwnCards,
|
||||||
isAvatarUpdating,
|
isAvatarUpdating,
|
||||||
emailUpdateForm,
|
emailUpdateForm,
|
||||||
|
|
|
@ -50,6 +50,9 @@ export default class extends BaseModel {
|
||||||
isAdmin: attr({
|
isAdmin: attr({
|
||||||
getDefault: () => false,
|
getDefault: () => false,
|
||||||
}),
|
}),
|
||||||
|
isLocked: attr({
|
||||||
|
getDefault: () => false,
|
||||||
|
}),
|
||||||
isAvatarUpdating: attr({
|
isAvatarUpdating: attr({
|
||||||
getDefault: () => false,
|
getDefault: () => false,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -24,6 +24,12 @@ services:
|
||||||
- DATABASE_URL=postgresql://postgres@postgres/planka
|
- DATABASE_URL=postgresql://postgres@postgres/planka
|
||||||
- SECRET_KEY=notsecretkey
|
- SECRET_KEY=notsecretkey
|
||||||
|
|
||||||
|
# Can be removed after installation
|
||||||
|
- DEFAULT_ADMIN_EMAIL=demo@demo.demo # Do not remove if you want to prevent this user from being edited/deleted
|
||||||
|
- DEFAULT_ADMIN_PASSWORD=demo
|
||||||
|
- DEFAULT_ADMIN_NAME=Demo Demo
|
||||||
|
- DEFAULT_ADMIN_USERNAME=demo
|
||||||
|
|
||||||
# related: https://github.com/knex/knex/issues/2354
|
# related: https://github.com/knex/knex/issues/2354
|
||||||
# As knex does not pass query parameters from the connection string we
|
# As knex does not pass query parameters from the connection string we
|
||||||
# have to use environment variables in order to pass the desired values, e.g.
|
# have to use environment variables in order to pass the desired values, e.g.
|
||||||
|
|
|
@ -4,6 +4,13 @@ BASE_URL=http://localhost:1337
|
||||||
DATABASE_URL=postgresql://postgres@localhost/planka
|
DATABASE_URL=postgresql://postgres@localhost/planka
|
||||||
SECRET_KEY=notsecretkey
|
SECRET_KEY=notsecretkey
|
||||||
|
|
||||||
|
## Can be removed after installation
|
||||||
|
|
||||||
|
DEFAULT_ADMIN_EMAIL=demo@demo.demo # Do not remove if you want to prevent this user from being edited/deleted
|
||||||
|
DEFAULT_ADMIN_PASSWORD=demo
|
||||||
|
DEFAULT_ADMIN_NAME=Demo Demo
|
||||||
|
DEFAULT_ADMIN_USERNAME=demo
|
||||||
|
|
||||||
## Optional
|
## Optional
|
||||||
|
|
||||||
# TRUST_PROXY=0
|
# TRUST_PROXY=0
|
||||||
|
|
|
@ -26,6 +26,10 @@ module.exports = {
|
||||||
throw Errors.USER_NOT_FOUND;
|
throw Errors.USER_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (user.email === sails.config.custom.defaultAdminEmail) {
|
||||||
|
throw Errors.USER_NOT_FOUND; // Forbidden
|
||||||
|
}
|
||||||
|
|
||||||
user = await sails.helpers.users.deleteOne.with({
|
user = await sails.helpers.users.deleteOne.with({
|
||||||
record: user,
|
record: user,
|
||||||
request: this.req,
|
request: this.req,
|
||||||
|
|
|
@ -59,6 +59,10 @@ module.exports = {
|
||||||
throw Errors.USER_NOT_FOUND;
|
throw Errors.USER_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (user.email === sails.config.custom.defaultAdminEmail) {
|
||||||
|
throw Errors.USER_NOT_FOUND; // Forbidden
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
inputs.id === currentUser.id &&
|
inputs.id === currentUser.id &&
|
||||||
!bcrypt.compareSync(inputs.currentPassword, user.password)
|
!bcrypt.compareSync(inputs.currentPassword, user.password)
|
||||||
|
|
|
@ -58,6 +58,10 @@ module.exports = {
|
||||||
throw Errors.USER_NOT_FOUND;
|
throw Errors.USER_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (user.email === sails.config.custom.defaultAdminEmail) {
|
||||||
|
throw Errors.USER_NOT_FOUND; // Forbidden
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
inputs.id === currentUser.id &&
|
inputs.id === currentUser.id &&
|
||||||
!bcrypt.compareSync(inputs.currentPassword, user.password)
|
!bcrypt.compareSync(inputs.currentPassword, user.password)
|
||||||
|
|
|
@ -61,6 +61,10 @@ module.exports = {
|
||||||
throw Errors.USER_NOT_FOUND;
|
throw Errors.USER_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (user.email === sails.config.custom.defaultAdminEmail) {
|
||||||
|
throw Errors.USER_NOT_FOUND; // Forbidden
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
inputs.id === currentUser.id &&
|
inputs.id === currentUser.id &&
|
||||||
!bcrypt.compareSync(inputs.currentPassword, user.password)
|
!bcrypt.compareSync(inputs.currentPassword, user.password)
|
||||||
|
|
|
@ -67,6 +67,13 @@ module.exports = {
|
||||||
throw Errors.USER_NOT_FOUND;
|
throw Errors.USER_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (user.email === sails.config.custom.defaultAdminEmail) {
|
||||||
|
/* eslint-disable no-param-reassign */
|
||||||
|
delete inputs.isAdmin;
|
||||||
|
delete inputs.name;
|
||||||
|
/* eslint-enable no-param-reassign */
|
||||||
|
}
|
||||||
|
|
||||||
const values = {
|
const values = {
|
||||||
..._.pick(inputs, [
|
..._.pick(inputs, [
|
||||||
'isAdmin',
|
'isAdmin',
|
||||||
|
|
|
@ -114,6 +114,7 @@ module.exports = {
|
||||||
avatarUrl:
|
avatarUrl:
|
||||||
this.avatar &&
|
this.avatar &&
|
||||||
`${sails.config.custom.userAvatarsUrl}/${this.avatar.dirname}/square-100.${this.avatar.extension}`,
|
`${sails.config.custom.userAvatarsUrl}/${this.avatar.dirname}/square-100.${this.avatar.extension}`,
|
||||||
|
isLocked: this.email === sails.config.custom.defaultAdminEmail,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,4 +40,6 @@ module.exports.custom = {
|
||||||
oidcJwksUri: process.env.OIDC_JWKS_URI,
|
oidcJwksUri: process.env.OIDC_JWKS_URI,
|
||||||
oidcScopes: process.env.OIDC_SCOPES || 'openid profile email',
|
oidcScopes: process.env.OIDC_SCOPES || 'openid profile email',
|
||||||
oidcSkipUserInfo: process.env.OIDC_SKIP_USER_INFO === 'true',
|
oidcSkipUserInfo: process.env.OIDC_SKIP_USER_INFO === 'true',
|
||||||
|
|
||||||
|
defaultAdminEmail: process.env.DEFAULT_ADMIN_EMAIL,
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,12 +6,8 @@ const knex = initKnex(knexfile);
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const isExists = await knex.schema.hasTable(knexfile.migrations.tableName);
|
|
||||||
|
|
||||||
await knex.migrate.latest();
|
await knex.migrate.latest();
|
||||||
if (!isExists) {
|
|
||||||
await knex.seed.run();
|
await knex.seed.run();
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
process.exitCode = 1;
|
process.exitCode = 1;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,42 @@
|
||||||
const bcrypt = require('bcrypt');
|
const bcrypt = require('bcrypt');
|
||||||
|
|
||||||
exports.seed = (knex) =>
|
const buildData = () => {
|
||||||
knex('user_account').insert({
|
const data = {
|
||||||
email: 'demo@demo.demo',
|
|
||||||
password: bcrypt.hashSync('demo', 10),
|
|
||||||
isAdmin: true,
|
isAdmin: true,
|
||||||
name: 'Demo Demo',
|
};
|
||||||
username: 'demo',
|
|
||||||
|
if (process.env.DEFAULT_ADMIN_PASSWORD) {
|
||||||
|
data.password = bcrypt.hashSync(process.env.DEFAULT_ADMIN_PASSWORD, 10);
|
||||||
|
}
|
||||||
|
if (process.env.DEFAULT_ADMIN_NAME) {
|
||||||
|
data.name = process.env.DEFAULT_ADMIN_NAME;
|
||||||
|
}
|
||||||
|
if (process.env.DEFAULT_ADMIN_USERNAME) {
|
||||||
|
data.username = process.env.DEFAULT_ADMIN_USERNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.seed = async (knex) => {
|
||||||
|
if (!process.env.DEFAULT_ADMIN_EMAIL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = buildData();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await knex('user_account').insert({
|
||||||
|
...data,
|
||||||
|
email: process.env.DEFAULT_ADMIN_EMAIL,
|
||||||
subscribeToOwnCards: false,
|
subscribeToOwnCards: false,
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (Object.keys(data).length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await knex('user_account').update(data).where('email', process.env.DEFAULT_ADMIN_EMAIL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue