diff --git a/components/admin/SMTP.vue b/components/admin/SMTP.vue index 54584059..b866a446 100644 --- a/components/admin/SMTP.vue +++ b/components/admin/SMTP.vue @@ -52,7 +52,7 @@ export default { async testSMTP () { this.loading = true try { - this.setSetting({ key: 'smtp', value: this.smtp }) + await this.setSetting({ key: 'smtp', value: this.smtp }) await this.$axios.$post('/settings/smtp', { smtp: this.smtp }) this.$root.$message(this.$t('admin.smtp_test_success', { admin_email: this.admin_email }), { color: 'success' }) } catch (e) { diff --git a/server/api/controller/event.js b/server/api/controller/event.js index bc4d8703..aa0b70b5 100644 --- a/server/api/controller/event.js +++ b/server/api/controller/event.js @@ -301,15 +301,17 @@ const eventController = { const body = req.body const recurrent = body.recurrent ? JSON.parse(body.recurrent) : null - if (!body.place_name) { - log.warn('Place is required') - return res.status(400).send('Place is required') + const required_fields = ['place_name', 'title', 'start_datetime'] + const missing_field = required_fields.find(required_field => !body[required_field]) + if (missing_field) { + log.warn(`${missing_field} is required`) + return res.status(400).send(`${missing_field} is required`) } const eventDetails = { title: body.title, // remove html tags - description: helpers.sanitizeHTML(linkifyHtml(body.description)), + description: helpers.sanitizeHTML(linkifyHtml(body.description || '')), multidate: body.multidate, start_datetime: body.start_datetime, end_datetime: body.end_datetime, @@ -567,14 +569,15 @@ const eventController = { * Select events based on params */ async select (req, res) { + const settings = res.locals.settings const start = req.query.start || dayjs().unix() const end = req.query.end const tags = req.query.tags const places = req.query.places const max = req.query.max - const show_recurrent = settingsController.settings.allow_recurrent_event && - typeof req.query.show_recurrent !== 'undefined' ? req.query.show_recurrent === 'true' : settingsController.settings.recurrent_event_visible + const show_recurrent = settings.allow_recurrent_event && + typeof req.query.show_recurrent !== 'undefined' ? req.query.show_recurrent === 'true' : settings.recurrent_event_visible res.json(await eventController._select({ start, end, places, tags, show_recurrent, max diff --git a/server/api/controller/export.js b/server/api/controller/export.js index 63322369..21474351 100644 --- a/server/api/controller/export.js +++ b/server/api/controller/export.js @@ -5,7 +5,6 @@ const Tag = require('../models/tag') const { Op, literal } = require('sequelize') const moment = require('dayjs') const ics = require('ics') -const settingsController = require('./settings') const exportController = { @@ -70,7 +69,7 @@ const exportController = { }, feed (req, res, events) { - const settings = settingsController.settings + const settings = res.locals.settings res.type('application/rss+xml; charset=UTF-8') res.render('feed/rss.pug', { events, settings, moment }) }, @@ -81,7 +80,7 @@ const exportController = { * @param {*} alarms https://github.com/adamgibbons/ics#attributes (alarms) */ ics (req, res, events, alarms = []) { - const settings = settingsController.settings + const settings = res.locals.settings const eventsMap = events.map(e => { const tmpStart = moment.unix(e.start_datetime) const tmpEnd = moment.unix(e.end_datetime) diff --git a/server/api/controller/user.js b/server/api/controller/user.js index f1f7bf96..4410a456 100644 --- a/server/api/controller/user.js +++ b/server/api/controller/user.js @@ -99,7 +99,7 @@ const userController = { log.info('Register user ', req.body.email) const user = await User.create(req.body) log.info(`Sending registration email to ${user.email}`) - mail.send(user.email, 'register', { user, config }, res.locales.locale) + mail.send(user.email, 'register', { user, config }, res.locals.locale) mail.send(settingsController.settings.admin_email, 'admin_register', { user, config }) res.sendStatus(200) } catch (e) { @@ -113,7 +113,7 @@ const userController = { req.body.is_active = true req.body.recover_code = crypto.randomBytes(16).toString('hex') const user = await User.scope('withRecover').create(req.body) - mail.send(user.email, 'user_confirm', { user, config }, res.locales.locale) + mail.send(user.email, 'user_confirm', { user, config }, res.locals.locale) res.json(user) } catch (e) { log.error('User creation error:', e) diff --git a/server/federation/follows.js b/server/federation/follows.js index 74354cf2..35d025e5 100644 --- a/server/federation/follows.js +++ b/server/federation/follows.js @@ -8,10 +8,11 @@ module.exports = { // follow request from fediverse async follow (req, res) { const body = req.body + const settings = res.locals.settings if (typeof body.object !== 'string') { return } const username = body.object.replace(`${config.baseurl}/federation/u/`, '') - if (username !== settingsController.settings.instance_name) { - log.warn(`Following the wrong user: ${username} instead of ${settingsController.settings.instance_name} (could be a wrong config.baseurl)`) + if (username !== settings.instance_name) { + log.warn(`Following the wrong user: ${username} instead of ${settings.instance_name} (could be a wrong config.baseurl)`) return res.status(404).send('User not found') } @@ -35,10 +36,11 @@ module.exports = { // unfollow request from fediverse async unfollow (req, res) { + const settings = res.locals.settings const body = req.body const username = body.object.object.replace(`${config.baseurl}/federation/u/`, '') - if (username !== settingsController.settings.instance_name) { - log.warn(`Unfollowing wrong user: ${username} instead of ${settingsController.settings.instance_name}`) + if (username !== settings.instance_name) { + log.warn(`Unfollowing wrong user: ${username} instead of ${settings.instance_name}`) return res.status(404).send('User not found') } diff --git a/server/federation/resources.js b/server/federation/resources.js index ff2f853e..9b798b9c 100644 --- a/server/federation/resources.js +++ b/server/federation/resources.js @@ -1,7 +1,6 @@ const Event = require('../api/models/event') const Resource = require('../api/models/resource') const APUser = require('../api/models/ap_user') -const settingsController = require('../api/controller/settings') const log = require('../log') const helpers = require('../helpers') @@ -11,7 +10,8 @@ module.exports = { // create a resource from AP Note async create (req, res) { - if (!settingsController.settings.enable_resources) { + + if (!res.locals.settings.enable_resources) { log.info('Ignore resource as it is disabled in settings') return } @@ -45,7 +45,7 @@ module.exports = { log.debug(`resource from ${req.body.actor} to "${event.title}"`) - body.object.content = helpers.sanitizeHTML(linkifyHtml(body.object.content)) + body.object.content = helpers.sanitizeHTML(linkifyHtml(body.object.content || '')) await Resource.create({ activitypub_id: body.object.id, diff --git a/server/federation/users.js b/server/federation/users.js index 82f6f768..074ea0b3 100644 --- a/server/federation/users.js +++ b/server/federation/users.js @@ -60,6 +60,7 @@ module.exports = { }, async followers (req, res) { + const settings = settingsController.settings const name = req.params.name const page = req.query.page log.debug(`Retrieve ${name} followers`) @@ -76,20 +77,20 @@ module.exports = { log.debug('No pagination') return res.json({ '@context': 'https://www.w3.org/ns/activitystreams', - id: `${config.baseurl}/federation/u/${name}/followers`, + id: `${settings.baseurl}/federation/u/${name}/followers`, type: 'OrderedCollection', totalItems: followers.length, - first: `${config.baseurl}/federation/u/${name}/followers?page=true` + first: `${settings.baseurl}/federation/u/${name}/followers?page=true` // last: `${config.baseurl}/federation/u/${name}/followers?page=true`, // orderedItems: followers.map(f => f.ap_id) }) } return res.json({ '@context': 'https://www.w3.org/ns/activitystreams', - id: `${config.baseurl}/federation/u/${name}/followers?page=${page}`, + id: `${settings.baseurl}/federation/u/${name}/followers?page=${page}`, type: 'OrderedCollectionPage', totalItems: followers.length, - partOf: `${config.baseurl}/federation/u/${name}/followers`, + partOf: `${settings.baseurl}/federation/u/${name}/followers`, orderedItems: followers.map(f => f.ap_id) }) }, @@ -109,32 +110,32 @@ module.exports = { } const events = await Event.findAll({ include: [{ model: Tag, required: false }, Place], limit: 10 }) - log.debug(`${config.baseurl} Inside ${name} outbox, should return all events from this instance: ${events.length}`) + log.debug(`${settings.baseurl} Inside ${name} outbox, should return all events from this instance: ${events.length}`) // https://www.w3.org/TR/activitypub/#outbox res.type('application/activity+json; charset=utf-8') if (!page) { return res.json({ '@context': 'https://www.w3.org/ns/activitystreams', - id: `${config.baseurl}/federation/u/${name}/outbox`, + id: `${settings.baseurl}/federation/u/${name}/outbox`, type: 'OrderedCollection', totalItems: events.length, first: { - id: `${config.baseurl}/federation/u/${name}/outbox?page=true`, + id: `${settings.baseurl}/federation/u/${name}/outbox?page=true`, type: 'OrderedCollectionPage', // totalItems: events.length, - partOf: `${config.baseurl}/federation/u/${name}/outbox`, - // prev: `${config.baseurl}/federation/u/${name}/outbox`, - // next: page !== 'last' && `${config.baseurl}/federation/u/${name}/outbox?page=last`, + partOf: `${settings.baseurl}/federation/u/${name}/outbox`, + // prev: `${settings.baseurl}/federation/u/${name}/outbox`, + // next: page !== 'last' && `${settings.baseurl}/federation/u/${name}/outbox?page=last`, orderedItems: page === 'last' ? [] : events.map(e => ({ - id: `${config.baseurl}/federation/m/${e.id}#create`, + id: `${settings.baseurl}/federation/m/${e.id}#create`, type: 'Create', to: ['https://www.w3.org/ns/activitystreams#Public'], - cc: [`${config.baseurl}/federation/u/${name}/followers`], + cc: [`${settings.baseurl}/federation/u/${name}/followers`], published: dayjs(e.createdAt).utc().format(), - actor: `${config.baseurl}/federation/u/${name}`, + actor: `${settings.baseurl}/federation/u/${name}`, object: e.toAP(name, settings.instance_locale) })) } diff --git a/server/helpers.js b/server/helpers.js index 47c7f805..95bbd68d 100644 --- a/server/helpers.js +++ b/server/helpers.js @@ -85,8 +85,8 @@ module.exports = { delete res.locals.settings.publicKey res.locals.settings.baseurl = config.baseurl res.locals.settings.hostname = config.hostname - res.locals.settings.title = settings.title || config.title - res.locals.settings.description = settings.description || config.description + res.locals.settings.title = res.locals.settings.title || config.title + res.locals.settings.description = res.locals.settings.description || config.description res.locals.settings.version = pkg.version // set user locale @@ -95,20 +95,19 @@ module.exports = { }, serveStatic () { - const settings = settingsController.settings const router = express.Router() // serve event's images/thumb router.use('/media/', express.static(config.upload_path, { immutable: true, maxAge: '1y' } )) router.use('/noimg.svg', express.static('./static/noimg.svg')) router.use('/logo.png', (req, res, next) => { - const logoPath = settings.logo || './static/gancio' + const logoPath = res.locals.settings.logo || './static/gancio' return express.static(logoPath + '.png')(req, res, next) }) router.use('/favicon.ico', (req, res, next) => { - const faviconPath = settings.logo || './assets/favicon' - return express.static(faviconPath + '.ico')(req, res, next) + const faviconPath = res.locals.settings.logo ? res.locals.settings.logo + '.png' : './assets/favicon.ico' + return express.static(faviconPath)(req, res, next) }) return router diff --git a/server/routes.js b/server/routes.js index f5a5e3b1..2c10543a 100644 --- a/server/routes.js +++ b/server/routes.js @@ -37,6 +37,7 @@ const app = express() app.enable('trust proxy') app.use(helpers.logRequest) +app.use(helpers.initSettings) app.use(helpers.setUserLocale) app.use(helpers.serveStatic()) @@ -83,7 +84,6 @@ app.use((error, req, res, next) => { // remaining request goes to nuxt // first nuxt component is ./pages/index.vue (with ./layouts/default.vue) // prefill current events, tags, places and announcements (used in every path) -app.use(helpers.initSettings) app.use(async (req, res, next) => { // const start_datetime = getUnixTime(startOfWeek(startOfMonth(new Date()))) // req.events = await eventController._select(start_datetime, 100)