feat: enhance user management by adding CSV support and password hashing

- Update .gitignore to include user credential files (users.csv, demo-users.csv).
- Modify Dockerfile to install bcryptjs globally for password hashing.
- Add script to hash passwords and copy it into the Docker image.
- Update setup.sh to create users from a CSV file if it exists, with error handling for password hashing.
- Introduce users.csv.example as a template for user data input.

This change improves user management by allowing bulk user creation from a CSV file and ensures secure password handling.
This commit is contained in:
Rohit Amarnath 2025-09-23 12:53:16 -04:00
parent 09a1a8b80d
commit 008d5a36f1
4 changed files with 77 additions and 5 deletions

5
.gitignore vendored
View file

@ -46,6 +46,11 @@ dist
# Ignore local SA JSON files
**/*.sa.json
# User credentials
users.csv
demo-users.csv
*.users.csv
# JetBrains Products
.idea/

View file

@ -14,7 +14,17 @@ RUN apt-get update && apt-get install -y \
RUN yarn install
# Install bcryptjs globally for password hashing
RUN npm install -g bcryptjs
ADD /packages/db ./packages/db
ADD /packages/db/setup.sh ./packages/db/setup.sh
# Copy the hash-password script
COPY packages/api/scripts/hash-password.js /usr/local/bin/hash-password.js
RUN chmod +x /usr/local/bin/hash-password.js
# Copy users.csv if it exists (optional file)
COPY packages/db/users.csv* /app/packages/db/ 2>/dev/null || true
CMD ["yarn", "workspace", "@omnivore/db", "migrate"]

View file

@ -17,13 +17,66 @@ PG_USER=$POSTGRES_USER PG_PASSWORD=$PGPASSWORD yarn workspace @omnivore/db migra
psql --host $PG_HOST --username $POSTGRES_USER --dbname $PG_DB --command "GRANT omnivore_user TO app_user;" || true
echo "granted omnivore_user to app_user"
# create demo user with configurable credentials
if [ -z "${NO_DEMO_USER}" ]; then
# Create users from CSV file if it exists
USERS_FILE="/app/packages/db/users.csv"
if [ -f "$USERS_FILE" ] && [ -z "${NO_DEMO_USER}" ]; then
echo "Creating users from $USERS_FILE..."
# Skip header line and process each user
tail -n +2 "$USERS_FILE" | while IFS=',' read -r email password name username; do
# Skip empty lines
[ -z "$email" ] && continue
# Generate UUID for user
USER_ID=$(uuidgen)
# Generate password hash
echo "Creating user: $email"
HASH_OUTPUT=$(node /usr/local/bin/hash-password.js "$password" 2>&1)
PASSWORD_HASH=$(echo "$HASH_OUTPUT" | grep "^Hash: " | sed 's/^Hash: //')
if [ -z "$PASSWORD_HASH" ]; then
echo "Failed to generate password hash for $email"
continue
fi
# Insert user into database
psql --host $PG_HOST --username $POSTGRES_USER --dbname $PG_DB --command \
"INSERT INTO omnivore.user (id, source, email, source_user_id, name, password)
VALUES ('$USER_ID', 'EMAIL', '$email', '$email', '$name', '$PASSWORD_HASH')
ON CONFLICT(email) DO NOTHING;
INSERT INTO omnivore.user_profile (user_id, username)
VALUES ('$USER_ID', '$username')
ON CONFLICT(user_id) DO NOTHING;" || true
echo "Created user: $email"
done
elif [ -z "${NO_DEMO_USER}" ]; then
# Fall back to single demo user from environment variables
echo "No users.csv found, creating single demo user from environment..."
USER_ID=$(uuidgen)
DEMO_EMAIL=${DEMO_USER_EMAIL:-"demo@omnivore.app"}
DEMO_PASSWORD_HASH=${DEMO_USER_PASSWORD_HASH:-'$2a$10$41G6b1BDUdxNjH1QFPJYDOM29EE0C9nTdjD1FoseuQ8vZU1NWtrh6'}
# Generate hash from plaintext if provided
if [ -n "$DEMO_USER_PASSWORD" ]; then
HASH_OUTPUT=$(node /usr/local/bin/hash-password.js "$DEMO_USER_PASSWORD" 2>&1)
DEMO_PASSWORD_HASH=$(echo "$HASH_OUTPUT" | grep "^Hash: " | sed 's/^Hash: //')
else
DEMO_PASSWORD_HASH=${DEMO_USER_PASSWORD_HASH:-'$2a$10$41G6b1BDUdxNjH1QFPJYDOM29EE0C9nTdjD1FoseuQ8vZU1NWtrh6'}
fi
DEMO_NAME=${DEMO_USER_NAME:-"Demo User"}
DEMO_USERNAME=${DEMO_USERNAME:-"demo_user"}
psql --host $PG_HOST --username $POSTGRES_USER --dbname $PG_DB --command "INSERT INTO omnivore.user (id, source, email, source_user_id, name, password) VALUES ('$USER_ID', 'EMAIL', '$DEMO_EMAIL', '$DEMO_EMAIL', '$DEMO_NAME', '$DEMO_PASSWORD_HASH') ON CONFLICT(email) DO NOTHING; INSERT INTO omnivore.user_profile (user_id, username) VALUES ('$USER_ID', '$DEMO_USERNAME') ON CONFLICT(user_id) DO NOTHING;"
echo "created demo user with email: $DEMO_EMAIL"
psql --host $PG_HOST --username $POSTGRES_USER --dbname $PG_DB --command \
"INSERT INTO omnivore.user (id, source, email, source_user_id, name, password)
VALUES ('$USER_ID', 'EMAIL', '$DEMO_EMAIL', '$DEMO_EMAIL', '$DEMO_NAME', '$DEMO_PASSWORD_HASH')
ON CONFLICT(email) DO NOTHING;
INSERT INTO omnivore.user_profile (user_id, username)
VALUES ('$USER_ID', '$DEMO_USERNAME')
ON CONFLICT(user_id) DO NOTHING;"
echo "Created demo user with email: $DEMO_EMAIL"
fi

View file

@ -0,0 +1,4 @@
email,password,name,username
demo@omnivore.app,demo_password,Demo User,demo_user
admin@example.com,admin123,Admin User,admin
test@example.com,test456,Test User,testuser