implement validation of email and password, ratelimiting, add ci for builds

This commit is contained in:
Aidan 2025-02-15 02:27:10 -05:00
parent edc18c2c18
commit acefa334a5
4 changed files with 91 additions and 3 deletions

View File

@ -0,0 +1,30 @@
name: Build and Push Docker Image
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build_and_push:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Log in to Gitea Package Registry
run: echo "${{ secrets.PACKAGE_TOKEN }}" | docker login $SERVER_URL -u $USERNAME --password-stdin
env:
SERVER_URL: ${{ secrets.SERVER_URL }}
USERNAME: ${{ secrets.USERNAME }}
PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }}
- name: Build Docker Image
run: docker build -t git.pontusmail.org/librecloud/mail-connect:latest .
- name: Push Docker Image
run: docker push git.pontusmail.org/librecloud/mail-connect:latest

View File

@ -11,7 +11,10 @@
"dependencies": {
"child_process": "^1.0.2",
"dockerode": "^4.0.4",
"express": "^4.21.2"
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"password-validator": "^5.3.0",
"validator": "^13.12.0"
},
"trustedDependencies": [
"protobufjs"

10
ratelimit.json Normal file
View File

@ -0,0 +1,10 @@
{
"/list": {
"windowMs": 60000,
"max": 20
},
"/add": {
"windowMs": 60000,
"max": 10
}
}

View File

@ -1,10 +1,53 @@
const express = require('express');
const fs = require('fs');
const rateLimit = require('express-rate-limit');
const Docker = require('dockerode');
const validator = require('validator');
const docker = new Docker({ socketPath: '/var/run/docker.sock' });
const app = express();
app.use(express.json());
// Rate limiting
let rateLimitConfig = {};
try {
const data = fs.readFileSync('./ratelimit.json', 'utf8');
rateLimitConfig = JSON.parse(data);
} catch (err) {
console.error('Error loading rate limit config:', err);
}
function createLimiter(options) {
return rateLimit({
windowMs: options.windowMs,
max: options.max,
message: "Too many requests, please try again another time.",
});
}
if (rateLimitConfig['/list']) {
app.use('/list', createLimiter(rateLimitConfig['/list']));
}
if (rateLimitConfig['/add']) {
app.use('/add', createLimiter(rateLimitConfig['/add']));
}
// Utility fxns
function validateEmail(email) {
return typeof email === 'string' && validator.isEmail(email);
}
const PasswordValidator = require('password-validator');
const passwordSchema = new PasswordValidator();
passwordSchema
.is().min(8)
.is().max(64)
.has().letters()
.has().digits()
.has().not().spaces();
function listAccounts() {
return new Promise((resolve, reject) => {
const container = docker.getContainer('mailserver');
@ -49,6 +92,8 @@ function listAccounts() {
});
}
// Routes
app.get('/list', (req, res) => {
listAccounts()
.then(accounts => res.json({ accounts }))
@ -57,8 +102,8 @@ app.get('/list', (req, res) => {
app.post('/add', (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({ error: "Email and password are required." });
if (!email || !validateEmail(email) || !password) {
return res.status(400).json({ error: "A valid email and password is required." });
}
const container = docker.getContainer('mailserver');