Files
planka/server/db/seeds/default.js
T
2026-09-17 00:44:37 +02:00

165 lines
4.6 KiB
JavaScript

/*!
* Copyright (c) 2024 PLANKA Software GmbH
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
/* eslint-disable no-console */
const bcrypt = require('bcrypt');
const validator = require('validator');
const USERNAME_REGEX = /^[a-zA-Z0-9]+((_|\.)?[a-zA-Z0-9])*$/;
const buildUserData = () => {
const data = {
role: 'admin',
isDeactivated: false,
};
if (process.env.DEFAULT_ADMIN_PASSWORD) {
data.password = bcrypt.hashSync(process.env.DEFAULT_ADMIN_PASSWORD, 10);
}
if (process.env.DEFAULT_ADMIN_NAME) {
if (process.env.DEFAULT_ADMIN_NAME.length > 128) {
console.warn('Warning: DEFAULT_ADMIN_NAME exceeds 128 characters; truncating.');
data.name = process.env.DEFAULT_ADMIN_NAME.slice(0, 128);
} else {
data.name = process.env.DEFAULT_ADMIN_NAME;
}
}
if (process.env.DEFAULT_ADMIN_USERNAME) {
const username = process.env.DEFAULT_ADMIN_USERNAME.toLowerCase();
if (username.length < 3 || username.length > 32 || !USERNAME_REGEX.test(username)) {
console.warn(
`Warning: DEFAULT_ADMIN_USERNAME "${process.env.DEFAULT_ADMIN_USERNAME}" is invalid; skipping.`,
);
} else {
data.username = username;
}
}
return data;
};
const buildInternalConfigData = () => {
const data = {};
if (process.env.STORAGE_LIMIT) {
data.storageLimit = process.env.STORAGE_LIMIT;
}
if (process.env.ACTIVE_USERS_LIMIT) {
const activeUsersLimit = parseInt(process.env.ACTIVE_USERS_LIMIT, 10);
if (Number.isInteger(activeUsersLimit)) {
data.activeUsersLimit = activeUsersLimit;
}
}
return data;
};
exports.seed = async (knex) => {
const defaultAdminEmail =
process.env.DEFAULT_ADMIN_EMAIL && process.env.DEFAULT_ADMIN_EMAIL.toLowerCase();
if (defaultAdminEmail) {
if (!validator.isEmail(defaultAdminEmail)) {
throw new Error(
`DEFAULT_ADMIN_EMAIL "${process.env.DEFAULT_ADMIN_EMAIL}" is not a valid e-mail address.`,
);
}
if (defaultAdminEmail.length > 256) {
throw new Error(
`DEFAULT_ADMIN_EMAIL "${process.env.DEFAULT_ADMIN_EMAIL}" exceeds 256 characters.`,
);
}
const existingEmailUser = await knex('user_account').where('email', defaultAdminEmail).first();
if (existingEmailUser) {
throw new Error(`User with DEFAULT_ADMIN_EMAIL "${defaultAdminEmail}" already exists.`);
}
const userData = buildUserData();
if (userData.username) {
const existingUsernameUser = await knex('user_account')
.where('username', userData.username)
.first();
if (existingUsernameUser) {
throw new Error(`User with DEFAULT_ADMIN_USERNAME "${userData.username}" already exists.`);
}
}
let userId;
try {
[{ id: userId }] = await knex('user_account').insert(
{
...userData,
email: defaultAdminEmail,
subscribeToOwnCards: false,
subscribeToCardWhenCommenting: true,
turnOffRecentCardHighlighting: false,
enableFavoritesByDefault: true,
defaultEditorMode: 'wysiwyg',
defaultHomeView: 'groupedProjects',
defaultProjectsOrder: 'byDefault',
createdAt: new Date().toISOString(),
},
'id',
);
} catch (error) {
/* empty */
}
if (!userId) {
await knex('user_account').update(userData).where('email', defaultAdminEmail);
}
}
const internalConfigData = buildInternalConfigData();
let activeUsersLimit;
if (Object.keys(internalConfigData).length > 0) {
[{ active_users_limit: activeUsersLimit }] = await knex('internal_config')
.update(internalConfigData)
.returning('active_users_limit');
} else {
({ active_users_limit: activeUsersLimit } = await knex('internal_config')
.select('active_users_limit')
.first());
}
if (Number.isInteger(activeUsersLimit)) {
let orderByQuery;
let orderByQueryValues;
if (defaultAdminEmail) {
orderByQuery = 'CASE WHEN email = ? THEN 0 WHEN role = ? THEN 1 ELSE 2 END';
orderByQueryValues = [defaultAdminEmail, 'admin'];
} else {
orderByQuery = 'CASE WHEN role = ? THEN 0 ELSE 1 END';
orderByQueryValues = 'admin';
}
const users = await knex('user_account')
.select('id')
.where('is_deactivated', false)
.orderByRaw(orderByQuery, orderByQueryValues)
.orderBy('id')
.offset(activeUsersLimit);
if (users.length > 0) {
const userIds = users.map(({ id }) => id);
await knex('user_account')
.update({
isDeactivated: true,
})
.whereIn('id', userIds);
}
}
};