diff --git a/.gitignore b/.gitignore index 4083037..4b879d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ local +config.json diff --git a/api/config.dev.json b/api/config.dev.json new file mode 100644 index 0000000..3b7f9b1 --- /dev/null +++ b/api/config.dev.json @@ -0,0 +1,4 @@ +{ + "secret": "CHANGEME!!!!!!!!!!@##@!!$$$$$$$$$$$$$!!", + "mail": false +} diff --git a/api/config.json.production b/api/config.json.production new file mode 100644 index 0000000..4e9a02f --- /dev/null +++ b/api/config.json.production @@ -0,0 +1,12 @@ +{ + "secret": "CHANGEME", + "mail": { + "from": "Sender Name ", + "smtp" : { + "host": "mail.example.com", + "port": 587, + "username": "sender@example.com", + "password": "hunter2" + } + } +} diff --git a/api/src/_helpers/send-email.js b/api/src/_helpers/send-email.js index 87684f8..6afabe2 100644 --- a/api/src/_helpers/send-email.js +++ b/api/src/_helpers/send-email.js @@ -1,18 +1,29 @@ const nodemailer = require('nodemailer'); -const config = require('../config/email'); +const config = require('../config'); module.exports = sendEmail; -async function sendEmail({ to, subject, html, from = config.emailFrom }) { - if (config.sendMails) { - const transporter = nodemailer.createTransport(config.smtpOptions); +async function sendEmail({ to, subject, html }) { + if (config.mail) { + const from = config.mail.from; + + const transporter = nodemailer.createTransport({ + host: config.mail.smtp.host, + port: config.mail.smtp.port, + secure: true, + auth: { + user: config.mail.smtp.username, + pass: config.mail.smtp.password, + }, + }); + await transporter.sendMail({ from, to, subject, html }); } else { - console.log({ - to, - subject, - html, - from, - }); + console.log(`========== E-Mail disabled, see contents below ========= +To: ${to} +Subject: ${subject} + +${html} +`) } } diff --git a/api/src/config.js b/api/src/config.js new file mode 100644 index 0000000..a82d2d3 --- /dev/null +++ b/api/src/config.js @@ -0,0 +1,33 @@ +const fs = require('fs'); +const Joi = require('joi'); + +const configSchema = Joi.object() + .required() + .keys({ + secret: Joi.string().min(16).max(128).required(), + + mail: Joi.alternatives().try( + Joi.object({ + from: Joi.string().required(), + smtp: Joi.object().required().keys({ + host: Joi.string().required(), + port: Joi.number().default(587), + username: Joi.string().required(), + password: Joi.string().required(), + }), + }), + Joi.boolean().valid(false), + ), + }); + +const configFiles = [ + process.env.CONFIG_FILE, + process.env.NODE_ENV === 'production' ? 'config.prod.json' : 'config.dev.json', + 'config.json', +].filter((x) => x && fs.existsSync(x)); + +if (!configFiles.length) { + throw new Error('No config file found.'); +} + +module.exports = Joi.attempt(JSON.parse(fs.readFileSync(configFiles[0], 'utf8')), configSchema); diff --git a/api/src/config/email.js b/api/src/config/email.js deleted file mode 100644 index 82deb15..0000000 --- a/api/src/config/email.js +++ /dev/null @@ -1,15 +0,0 @@ -const isProduction = process.env.NODE_ENV === 'production'; -const forcedMail = process.argv.findIndex((s) => s === '--devSendMails') !== -1; - -module.exports = { - sendMails: isProduction || forcedMail, - emailFrom: process.env.MAILSENDER, - smtpOptions: { - host: process.env.MAILSERVER, - port: 587, - auth: { - user: process.env.MAILUSER, - pass: process.env.MAILPW, - }, - }, -}; diff --git a/api/src/config/index.js b/api/src/config/index.js deleted file mode 100644 index 2982515..0000000 --- a/api/src/config/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - secret: process.env.NODE_ENV === 'production' ? process.env.SECRET : 'secret', -}; diff --git a/api/src/db.js b/api/src/db.js index a8e2ee3..cfb4f40 100644 --- a/api/src/db.js +++ b/api/src/db.js @@ -10,6 +10,6 @@ require('./models/TrackData'); require('./models/User'); require('./models/Track'); require('./models/Comment'); -require('./config/passport'); +require('./passport'); module.exports = mongoose; diff --git a/api/src/index.js b/api/src/index.js index 4dcd326..46f6ede 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -6,7 +6,7 @@ const cors = require('cors'); const errorhandler = require('errorhandler'); const passport = require('passport'); -require('./config/passport'); +require('./passport'); const isProduction = process.env.NODE_ENV === 'production'; diff --git a/api/src/config/passport.js b/api/src/passport.js similarity index 98% rename from api/src/config/passport.js rename to api/src/passport.js index 644a645..0c21436 100644 --- a/api/src/config/passport.js +++ b/api/src/passport.js @@ -4,9 +4,9 @@ const { Strategy: BearerStrategy } = require('passport-http-bearer'); const { Strategy: JwtStrategy } = require('passport-jwt'); const { Strategy: CustomStrategy } = require('passport-custom'); -const { User, AccessToken, RefreshToken } = require('../models'); +const { User, AccessToken, RefreshToken } = require('./models'); -const secret = require('../config').secret; +const secret = require('./config').secret; // used to serialize the user for the session passport.serializeUser(function (user, done) { diff --git a/api/src/routes/api/profiles.js b/api/src/routes/api/profiles.js index 9d87766..eafbd86 100644 --- a/api/src/routes/api/profiles.js +++ b/api/src/routes/api/profiles.js @@ -2,7 +2,7 @@ const router = require('express').Router(); const mongoose = require('mongoose'); const User = mongoose.model('User'); const wrapRoute = require('../../_helpers/wrapRoute'); -const auth = require('../../config/passport'); +const auth = require('../../passport'); // Preload user profile on routes with ':username' router.param('username', async function (req, res, next, username) { diff --git a/api/src/routes/api/tracks.js b/api/src/routes/api/tracks.js index ac5d63a..d976de2 100644 --- a/api/src/routes/api/tracks.js +++ b/api/src/routes/api/tracks.js @@ -5,7 +5,7 @@ const Track = mongoose.model('Track'); const Comment = mongoose.model('Comment'); const User = mongoose.model('User'); const busboy = require('connect-busboy'); -const auth = require('../../config/passport'); +const auth = require('../../passport'); const { normalizeUserAgent, buildObsver1 } = require('../../logic/tracks'); const wrapRoute = require('../../_helpers/wrapRoute'); diff --git a/api/src/routes/api/users.js b/api/src/routes/api/users.js index 8451217..0eeec5a 100644 --- a/api/src/routes/api/users.js +++ b/api/src/routes/api/users.js @@ -1,7 +1,6 @@ const router = require('express').Router(); -const passport = require('passport'); const wrapRoute = require('../../_helpers/wrapRoute'); -const auth = require('../../config/passport'); +const auth = require('../../passport'); router.get( '/user', diff --git a/api/src/routes/auth.js b/api/src/routes/auth.js index 8c6c6c7..0e059b3 100644 --- a/api/src/routes/auth.js +++ b/api/src/routes/auth.js @@ -4,7 +4,7 @@ const { URL } = require('url'); const { createChallenge } = require('pkce'); const { AuthorizationCode, AccessToken, RefreshToken, Client } = require('../models'); -const auth = require('../config/passport'); +const auth = require('../passport'); const wrapRoute = require('../_helpers/wrapRoute'); // Check whether the "bigScope" fully includes the "smallScope". diff --git a/docker-compose.yaml b/docker-compose.yaml index 34e11b5..4eb2450 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -20,6 +20,7 @@ services: - ./local/api-data:/data - ./api/.migrations.js:/opt/obs/api/.migrations.js - ./api/migrations:/opt/obs/api/migrations/ + - ./api/config.dev.json:/opt/obs/api/config.json environment: - PORT=3000 - MONGODB_URL=mongodb://mongo/obsTest