diff --git a/server/db/create-admin-user.js b/server/db/create-admin-user.js index a41fa5e2..23c49b9f 100644 --- a/server/db/create-admin-user.js +++ b/server/db/create-admin-user.js @@ -62,6 +62,32 @@ const input = async (fieldName, options = {}) => { process.env.DEFAULT_ADMIN_USERNAME = await input('Username'); + if (process.env.DEFAULT_ADMIN_USERNAME) { + const USERNAME_REGEX = /^[a-zA-Z0-9]+((_|\.)?[a-zA-Z0-9])*$/; + + // eslint-disable-next-line no-constant-condition + while (true) { + const isValid = + process.env.DEFAULT_ADMIN_USERNAME.length >= 3 && + process.env.DEFAULT_ADMIN_USERNAME.length <= 32 && + USERNAME_REGEX.test(process.env.DEFAULT_ADMIN_USERNAME); + + if (isValid) { + break; + } + + console.log( + 'Username must be 3-32 characters and contain only letters, digits, underscores, and dots (e.g., john_doe).', + ); + + process.env.DEFAULT_ADMIN_USERNAME = await input('Username'); + + if (!process.env.DEFAULT_ADMIN_USERNAME) { + break; + } + } + } + await knex.seed.run({ specific: 'default.js', }); diff --git a/server/db/seeds/default.js b/server/db/seeds/default.js index 3da664e4..bad40473 100644 --- a/server/db/seeds/default.js +++ b/server/db/seeds/default.js @@ -3,8 +3,12 @@ * Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md */ +/* eslint-disable no-console */ + const bcrypt = require('bcrypt'); +const USERNAME_REGEX = /^[a-zA-Z0-9]+((_|\.)?[a-zA-Z0-9])*$/; + const buildUserData = () => { const data = { role: 'admin', @@ -19,7 +23,15 @@ const buildUserData = () => { data.name = process.env.DEFAULT_ADMIN_NAME; } if (process.env.DEFAULT_ADMIN_USERNAME) { - data.username = process.env.DEFAULT_ADMIN_USERNAME.toLowerCase(); + 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;