diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..6923c59 --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +DB_NAME=pontusmail +DB_USER=root +DB_PASSWORD=passwdhere +DB_HOST=127.0.0.1 +SESSION_SECRET=secretkeyhere +ADMIN_USERNAME=admin +ADMIN_PASSWORD=admin \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8670b45..88e094b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ package-lock.json docker-compose.yml register,log donations.json -.idea/ \ No newline at end of file +.idea/ +db/ +.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 1697dbe..f3fcfd0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18 +FROM node:20 WORKDIR /usr/src/app COPY package*.json ./ RUN npm install --only=production diff --git a/README.md b/README.md index 4233b5c..cf3ec38 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,17 @@ Landing page for p0ntus mail ```bash mv donations.json.example donations.json ``` -4. Install dependencies +4. Copy the example `.env` + ```bash + mv .env.example .env + ``` + + Make sure you edit this with your MySQL server information and other values. +5. Install dependencies ```bash npm install ``` -5. Start the server +6. Start the server ```bash node app.js ``` @@ -38,6 +44,12 @@ You can also use Docker to self-host pontus-mail's frontend. Make sure you have ```bash mv docker-compose.yml.example docker-compose.yml ``` +3. Copy the example `.env` + ```bash + mv .env.example .env + ``` + + Make sure you edit this file with values matching in `docker-compose.xml`, and other desired values like admin username/password. 3. Copy the example `donations.json` ```bash mv donations.json.example donations.json diff --git a/app.js b/app.js index 8666587..9a772e2 100644 --- a/app.js +++ b/app.js @@ -1,17 +1,48 @@ const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); -const fs = require('fs'); +const session = require('express-session'); +const { Sequelize, DataTypes } = require('sequelize'); +const { error } = require('console'); +require('dotenv').config(); const app = express(); app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'src')); app.use(bodyParser.urlencoded({ extended: false })); - app.use(express.static(path.join(__dirname, 'public'))); +app.use(session({ + secret: process.env.SESSION_SECRET, + resave: false, + saveUninitialized: true +})); +const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, { + host: process.env.DB_HOST || '127.0.0.1', + dialect: 'mysql' +}); + +sequelize.authenticate() + .then(() => console.log('Database connected')) + .catch(err => console.log('Error: ' + err)); + +const Request = sequelize.define('Request', { + fullName: DataTypes.STRING, + email: DataTypes.STRING, + reason: DataTypes.TEXT, + telegram: DataTypes.STRING, + status: { + type: DataTypes.STRING, + defaultValue: 'Pending' + } +}); + +// Sync models +sequelize.sync(); + +// Routes app.get('/', (req, res) => { res.render('index', { currentPage: 'home' }); }); @@ -20,10 +51,6 @@ app.get('/services', (req, res) => { res.render('services', { currentPage: 'services' }); }); -app.get('/register', (req, res) => { - res.render('register', { currentPage: 'register' }); -}); - app.get('/donate', (req, res) => { const donations = JSON.parse(fs.readFileSync('donations.json', 'utf8')); res.render('donate', { @@ -64,7 +91,75 @@ app.get('/guides/vaultwarden/firefox', (req, res) => { res.render('guides/vaultwarden/firefox', { currentPage: 'guides' }); }); -const PORT = process.env.PORT || 3000; -app.listen(PORT, () => { - console.log(`Server is running on port ${PORT}`); +app.get('/register', (req, res) => { + res.render('register', { currentPage: 'register' }); +}); + +app.post('/register', async (req, res) => { + const { fullName, email, reason, telegram } = req.body; + await Request.create({ fullName, email, reason, telegram }); + res.render('reg-success', { currentPage: 'register' }); +}); + +app.get('/request', async (req, res) => { + console.log("Got /request"); + const { email } = req.query; + + if (!email) { + return res.status(400).render('error/email'); + } + + try { + const request = await Request.findOne({ where: { email } }); + if (!request) { + return res.status(404).render('error/404'); + } + res.render('req-status', { request }); + } catch (error) { + console.error(error); + res.status(500).render('error/500'); + } +}); + +function checkAdminAuth(req, res, next) { + if (req.session.admin) { + next(); + } else { + res.redirect('/admin', { error: null }); + } +} + +app.get('/admin', (req, res) => { + res.render('admin-login', { currentPage: 'admin', error: null }); +}); + +app.post('/admin', (req, res) => { + const { username, password } = req.body; + if (username === process.env.ADMIN_USERNAME && password === process.env.ADMIN_PASSWORD) { + req.session.admin = true; + res.redirect('/admin/dashboard'); + } else { + res.render('admin-login', { error: 'An error occurred.' }); + } +}); + +app.get('/admin/dashboard', checkAdminAuth, async (req, res) => { + const requests = await Request.findAll(); + res.render('admin-dash', { requests, currentPage: 'admin' }); +}); + +app.post('/admin/update-status', checkAdminAuth, async (req, res) => { + const { id, status } = req.body; + await Request.update({ status }, { where: { id } }); + res.redireHot('/admin/dashboard'); +}); + +app.post('/admin/delete-request', checkAdminAuth, async (req, res) => { + const { id } = req.body; + await Request.destroy({ where: { id } }); + res.redirect('/admin/dashboard'); +}); + +app.listen(3000, () => { + console.log('Server started on port 3000'); }); \ No newline at end of file diff --git a/docker-compose.yml.example b/docker-compose.yml.example index ce09d68..6f6097d 100644 --- a/docker-compose.yml.example +++ b/docker-compose.yml.example @@ -4,10 +4,23 @@ services: container_name: pontus-mail restart: always ports: - - "80:3000" + - "2424:3000" volumes: - ./register.log:/usr/src/app/register.log - ./exclusions.json:/usr/src/app/exclusions.json - ./donations.json:/usr/src/app/donations.json environment: - - NODE_ENV=production \ No newline at end of file + - NODE_ENV=production + - DB_HOST=pontus-mail-db + - DB_USER=root + - DB_PASSWORD=mysqlrootpasswdhere + - DB_NAME=pontusmail + pontus-mail-db: + image: mysql:latest + environment: + - MYSQL_ROOT_PASSWORD=mysqlrootpasswdhere + - MYSQL_DATABASE=pontusmail + ports: + - "3306:3306" + volumes: + - ./db:/var/lib/mysql \ No newline at end of file diff --git a/package.json b/package.json index 4a3b1db..74cdbff 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,15 @@ "license": "CC0-1.0", "dependencies": { "body-parser": "^1.20.3", + "dotenv": "^16.4.7", "ejs": "^3.1.10", "express": "^4.21.1", + "express-session": "^1.18.1", + "mariadb": "^3.4.0", + "mysql2": "^3.11.5", + "sequelize": "^6.37.5", "winston": "^3.17.0" }, - "devDependencies": {}, "repository": { "type": "git", "url": "git+https://github.com/ihatenodejs/pontus-mail.git" diff --git a/src/admin-dash.ejs b/src/admin-dash.ejs new file mode 100644 index 0000000..d81f858 --- /dev/null +++ b/src/admin-dash.ejs @@ -0,0 +1,50 @@ +<%- include('shards/header', { title: 'Admin Dashboard - p0ntus mail' }) %> +
ID | +Full Name | +Reason | +Telegram | +Status | +Update Status | +Delete | +|
---|---|---|---|---|---|---|---|
<%= request.id %> | +<%= request.fullName %> | +<%= request.email %> | +<%= request.reason %> | +<%= request.telegram %> | +<%= request.status %> | ++ + | ++ + | +
The requested resource could not be found.
+An unexpected error occurred. Please try again later.
+We need an email to check your request. Please enter your p0ntus mail email address below:
+ +Your request has been submitted successfully. You can check the status of your request here.
+Request Status: <%= request.status %>
+ <% if (request.status === 'Approved') { %> +Your request has been approved. You can access your p0ntus mail account here with your email as the username and abcabc for the password. FOR SECURITY, CHANGE YOUR PASSWORD ASAP.
+I also suggest you check out our guides at mail.p0ntus.com/guides.
+You can also access Vaultwarden at vaultwarden.p0ntus.com.
+If you need any help or support, contact admin@p0ntus.com.
+Your webmail can be accessed here.
+No request found for the provided email.
+ <% } %> +