Warning
The TypeScript migration is still in progress and currently unstable.
Prepare to run tsc yourself, automatic transpiling is not yet implemented.
To run this project, you will need to have docker and docker compose installed. You also need a mail server to send emails, or at least a mail account with IMAP access.
You also have to create a .env file containing the password/key environment variables.
For a secure production environment, you should create long and random passwords (using a generator).
Your .env file should look like this:
DOCKER_NAME='project_name'
POSTGRES_PASSWORD='PASS'
EXPRESS_SESSION_SECRET_KEY='KEY'
PGADMIN_DEFAULT_EMAIL='mail@mail.mail'
PGADMIN_DEFAULT_PASSWORD='PASS'
TESTUSER_USER='USER'
TESTUSER_PASS='val1dP@ssw0rd'
TESTUSER_EMAIL='admin+testuser@mail.mail'
MAIL_HOST='mail.mail'
MAIL_USER='admin@mail.mail'
MAIL_PASS='PASS'
STRIPE_API_KEY='sk_...'
STRIPE_ENDPOINT_SECRET='whsec_...'
NODE_ENV='development' # OR 'production'Attention: The testuser password should be valid, according to the password policy. If not, the automated end-to-end tests will fail.
Also: You should use the same inbox for TESTUSER_EMAIL as for MAIL_USER, because the
end-to-end tests will check the MAIL_USER inbox for the confirmation email.
If you want to open the ports for testing in a local environment, you can add a
docker-compose.override.yml to the folder that opens the ports. Be careful about
opening ports in production.
We also added a command devStart that will start the server with nodemon, so it will
automatically restart when you change the server.js file (or other files).
Before starting the server in prod mode, ejs files will be minified and testing tags
will be removed. For dev/test mode, we don't care about that, so we mount the views/dev
folder to the container.
You can do it like this:
name: lnqz
services:
web:
command: [ "pnpm", "devStart" ]
volumes:
- ./src:/usr/src/app/src
ports:
- "8080:8080"
db:
ports:
- "5433:5432"
pgadmin:
ports:
- "15433:80"To test if the stripe code works correctly, there is a local stripe cli. For installation refer to the stripe docs
The command to start it is stripe listen --forward-to localhost:8080/api/webhook
To get your API key to put it in the .env file, you need to go to the stripe dashboard.
The most important files are:
server.js- The main file that starts the server (using express.js)Dockerfileanddocker-compose.yml- The files that define the docker project, including the webserver, database (and the pgadmin interface)package.json- The file that defines the dependencies and scripts for the project
Then we have the src folder, which contains all backend code, like logging, mail sending,
database setup and update migrations, mail templates and locales. It also stores the logs and
the downloaded spam mail blacklist.
The static folder contains the frontend css and js files. We use SCSS, which needs to be compiled.
This is taken care of by sass, which is run at the start of the server.
The views folder contains the ejs templates that are rendered by the server, which is like html
but with some scripting stuff which express.js can use.
We are using i18n for translations. The translations are stored in the locales folder.
There is a list that contains all pages that are supposed to be translatable, and also a middleware
called validateLang that checks requests for translatable pages and adds a language code to the url.
For some forms we added an invisible attribute l that will be available as req.body.l in their respective
POST routes. Generally you should be able to use req.session.lang to get the language code.
We are using Jest for unit/integration testing, and Cypress for end-to-end testing. For the tests to work you need to be in development or test mode (because it adds some needed endpoints that are only active in dev/test mode).
To run the tests, you can use the following command
pnpm testIt will run the unit tests first and then the end-to-end tests. The server needs to be running for the tests to work.
If you use Ideolog to highlight the logs, you can use the following regex to highlight the logs:
^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z)\s(debug|http|info|warn|error):\s(.*)$To ensure data safety, you should run regular backups of the PostgreSQL database. To make backups even safer, you should encrypt them. You can use the following bash script as a cron job to create encrypted backups of your Lnqz database every day. Make sure to adjust the paths and parameters as needed.
The procedure works as follows:
- Dump the PostgreSQL database to a SQL file.
- Generate a random AES key and use it to encrypt the SQL backup file.
- Encrypt the AES key with a public RSA key.
- Store the encrypted backup and encrypted AES key in the specified backup directory.
- Delete backups older than 7 days.
#!/bin/bash
# Adjust these paths as needed
## Where your Lnqz docker folder is located
LNQZ_DIR="/docker/Lnqz"
## Where to store the backups
BACKUP_DIR="/mnt/backup/lnqz"
## Public key for encryption
PUBLIC_KEY="/docker/backup_public.pem"
## Name of the database container
DB_CONTAINER="lnqz-db-1"
## Database user
DB_USER="postgres"
## Database name
DB_NAME="postgres"
# Load environment variables
export $(cat $LNQZ_DIR/.env | xargs)
DATE=$(date +\%Y-\%m-\%d_\%H-\%M-\%S)
BACKUP_FILE="$BACKUP_DIR/backup_$DATE.sql"
# Backup-Ordner und Datenbank-Infos aus der .env
DATE=$(date +\%Y-\%m-\%d_\%H-\%M-\%S)
BACKUP_FILE="$BACKUP_DIR/backup_$DATE.sql.enc"
BACKUP_FILE_KEY="$BACKUP_DIR/backup_$DATE.bin.enc"
# Dump database
docker exec -t $DB_CONTAINER pg_dump -U $DB_USER -d $DB_NAME > /tmp/backup_$DATE.sql
# Encrypt backup
# Generate random AES key
openssl rand -out /tmp/aes_key.bin 32
# Encrypt backup with 256 bit AES
openssl enc -aes-256-cbc -salt -in /tmp/backup_$DATE.sql -out /tmp/backup_$DATE.sql.enc -pass file:/tmp/aes_key.bin -pbkdf2
# Encrypt AES key with public RSA key
openssl pkeyutl -encrypt -inkey $PUBLIC_KEY -pubin -in /tmp/aes_key.bin -out /tmp/aes_key.bin.enc
# Delete unencrypted files
rm /tmp/backup_$DATE.sql /tmp/aes_key.bin
# Move encrypted backup to backup path
mv /tmp/backup_$DATE.sql.enc $BACKUP_FILE
mv /tmp/aes_key.bin.enc $BACKUP_FILE_KEY
# Delete old backups
find $BACKUP_DIR -type f -name "*.sql" -mtime +7 -exec rm {} \;