From beebca7ab9ab6d5c26bb79428d63315b65954bca Mon Sep 17 00:00:00 2001 From: les Date: Fri, 6 Sep 2019 11:58:11 +0200 Subject: [PATCH] refactoring email notification, closes #8 --- locales/email/en.json | 23 +++++++++---- locales/email/es.json | 23 +++++++++---- locales/email/it.json | 24 ++++++++----- locales/it.js | 9 ++++- pages/add/_edit.vue | 28 +++++++-------- pages/admin.vue | 3 +- pages/event/_id.vue | 2 +- pages/register.vue | 10 +++--- pages/user_confirm/_code.vue | 44 +++++------------------- plugins/vue-awesome.js | 1 + server/api/controller/user.js | 16 ++++++--- server/api/mail.js | 10 ++++-- server/api/models/event.js | 2 ++ server/emails/admin_register/html.pug | 4 +++ server/emails/admin_register/subject.pug | 1 + server/emails/admin_register/text.pug | 6 ++++ server/emails/confirm/html.pug | 15 ++------ server/emails/confirm/subject.pug | 2 +- server/emails/confirm/text.pug | 1 + server/emails/event/html.pug | 41 +++++++++++----------- server/emails/event/text.pug | 21 +++++++++++ server/emails/layout.pug | 13 +++++++ server/emails/recover/html.pug | 14 ++------ server/emails/recover/subject.pug | 2 +- server/emails/recover/text.pug | 1 + server/emails/register/html.pug | 8 ++--- server/emails/register/subject.pug | 2 +- server/emails/register/text.pug | 2 +- server/emails/user_confirm/html.pug | 13 ++----- server/emails/user_confirm/subject.pug | 2 +- server/emails/user_confirm/text.pug | 1 + 31 files changed, 195 insertions(+), 149 deletions(-) create mode 100644 server/emails/admin_register/html.pug create mode 100644 server/emails/admin_register/subject.pug create mode 100644 server/emails/admin_register/text.pug create mode 100644 server/emails/confirm/text.pug create mode 100644 server/emails/event/text.pug create mode 100644 server/emails/layout.pug create mode 100644 server/emails/recover/text.pug create mode 100644 server/emails/user_confirm/text.pug diff --git a/locales/email/en.json b/locales/email/en.json index 257092aa..d27010cf 100644 --- a/locales/email/en.json +++ b/locales/email/en.json @@ -1,8 +1,17 @@ { - "email.registration": "email.registration", - "email.register.subject": "email.register.subject", - "email.register": "email.register", - "email.confirm": "email.confirm", - "email.recover": "email.recover", - "email.press_here": "email.press_here" -} \ No newline at end of file + "register":{ + "subject": "Richiesta registrazione ricevuta", + "content": "Abbiamo ricevuto la richiesta di registrazione. La confermeremo quanto prima.\n Ciao" + }, + "confirm": { + "subject": "Puoi iniziare a pubblicare eventi", + "content": "Ciao, il tuo account su {{config.title}} è stato creato. Confermalo." + }, + "recover": { + "subject": "Recupero password", + "content": "Ciao, hai richiesto un recupero della password su {{config.title}}." + }, + "common": { + "press_here": "Premi qui" + } +} diff --git a/locales/email/es.json b/locales/email/es.json index 257092aa..d27010cf 100644 --- a/locales/email/es.json +++ b/locales/email/es.json @@ -1,8 +1,17 @@ { - "email.registration": "email.registration", - "email.register.subject": "email.register.subject", - "email.register": "email.register", - "email.confirm": "email.confirm", - "email.recover": "email.recover", - "email.press_here": "email.press_here" -} \ No newline at end of file + "register":{ + "subject": "Richiesta registrazione ricevuta", + "content": "Abbiamo ricevuto la richiesta di registrazione. La confermeremo quanto prima.\n Ciao" + }, + "confirm": { + "subject": "Puoi iniziare a pubblicare eventi", + "content": "Ciao, il tuo account su {{config.title}} è stato creato. Confermalo." + }, + "recover": { + "subject": "Recupero password", + "content": "Ciao, hai richiesto un recupero della password su {{config.title}}." + }, + "common": { + "press_here": "Premi qui" + } +} diff --git a/locales/email/it.json b/locales/email/it.json index 1b52696d..6b16400b 100644 --- a/locales/email/it.json +++ b/locales/email/it.json @@ -1,10 +1,18 @@ { - "email.register.subject": "Richiesta registrazione ricevuta", - "email.register": "Abbiamo ricevuto la richiesta di registrazione. La confermeremo quanto prima.\n Ciao", - "email.confirm": "Il tuo account su {{config.title}} è stato attivato e quindi puoi cominciare a pubblicare eventi", - "email.recover.subject": "Recupero password", - "email.recover": "Ciao, hai richiesto un recupero della password su {{config.title}}.", - "email.press_here": "Premi qui", - "email.confirm.subject": "Registrazione confermata", - "email.user_confirm": "Ciao, il tuo account su {{config.title}} è stato creato. Confermalo." + "register":{ + "subject": "Richiesta registrazione ricevuta", + "content": "Abbiamo ricevuto la richiesta di registrazione. La confermeremo quanto prima.\n Ciao" + }, + "confirm": { + "subject": "Puoi iniziare a pubblicare eventi", + "content": "Ciao, il tuo account su {{config.title}} è stato creato. Confermalo." + }, + "recover": { + "subject": "Recupero password", + "content": "Ciao, hai richiesto un recupero della password su {{config.title}}. Premi qui per confermare" + }, + "admin_register":{ + "subject": "Nuova registrazione", + "content": "{{user.username}} si è registrato/a a {{config.title}} scrivendo:
{{user.description}}

Puoi confermarlo qui." + } } diff --git a/locales/it.js b/locales/it.js index d1c49790..8508bbe9 100644 --- a/locales/it.js +++ b/locales/it.js @@ -50,7 +50,8 @@ export default { me: 'Sei te', password_updated: 'Password modificata!', username: 'Nickname', - comments: 'nessun commento|un commento|{n} commenti' + comments: 'nessun commento|un commento|{n} commenti', + activate_user: 'Confermato' }, login: { @@ -170,6 +171,12 @@ export default { email_taken: 'Questa email è già registrata' }, + confirm: { + title: 'Conferma utente', + not_valid: 'Mmmmm qualcosa è andato storto.', + valid: 'Il tuo account è stato confermato, ora puoi entrare', + }, + ordinal: { 1: 'primo', 2: 'secondo', diff --git a/pages/add/_edit.vue b/pages/add/_edit.vue index a41a90b2..eb74517d 100644 --- a/pages/add/_edit.vue +++ b/pages/add/_edit.vue @@ -90,7 +90,7 @@ el-time-select(v-model='time.end' :picker-options="{start: '00:00', step: '00:30', end: '24:00'}") - List(v-if='event.type==="normal"' :events='todayEvents' :title='$t("event.same_day")') + List(v-if='event.type==="normal" && todayEvents.length' :events='todayEvents' :title='$t("event.same_day")') el-button.float-right(@click='next' type='succes' :disabled='!couldProceed') {{$t('common.next')}} //- MEDIA / FLYER / POSTER @@ -193,14 +193,14 @@ export default { data.event.place.name = event.place.name data.event.place.address = event.place.address || '' if (event.multidate) { - data.date = { start: new Date(event.start_datetime*1000), end: new Date(event.end_datetime*1000) } + data.date = { start: moment.unix(event.start_datetime), end: moment.unix(event.end_datetime) } data.event.type = 'multidate' } else if (event.recurrent ) { data.event.type = 'recurrent' data.event.recurrent = JSON.parse(event.recurrent) } else { data.event.type = 'normal' - data.date = new Date(event.start_datetime*1000) + data.date = moment.unix(event.start_datetime) } data.time.start = moment.unix(event.start_datetime).format('HH:mm') @@ -251,19 +251,19 @@ export default { const date_end = moment(this.date.end) return this.events.filter(e => !e.multidate ? - date_start.isSame(e.start_datetime, 'day') || - date_start.isBefore(e.start_datime) && date_end.isAfter(e.start_datetime) : - date_start.isSame(e.start_datetime, 'day') || date_start.isSame(e.end_datetime) || - date_start.isAfter(e.start_datetime) && date_start.isBefore(e.end_datetime)) + date_start.isSame(moment.unix(e.start_datetime), 'day') || + date_start.isBefore(moment.unix(e.start_datime)) && date_end.isAfter(moment.unix(e.start_datetime)) : + date_start.isSame(moment.unix(e.start_datetime), 'day') || date_start.isSame(moment.unix(e.end_datetime)) || + date_start.isAfter(moment.unix(e.start_datetime)) && date_start.isBefore(moment.unix(e.end_datetime))) } else if (this.event.type === 'recurrent' ) { } else { const date = moment(this.date) return this.events.filter(e => !e.multidate ? - !e.recurrent && date.isSame(moment(e.start_datetime), 'day') : - moment(e.start_datetime).isSame(date, 'day') || - moment(e.start_datetime).isBefore(date) && moment(e.end_datetime).isAfter(date) + !e.recurrent && date.isSame(moment.unix(e.start_datetime), 'day') : + moment.unix(e.start_datetime).isSame(date, 'day') || + moment.unix(e.start_datetime).isBefore(date) && moment.unix(e.end_datetime).isAfter(date) ) } }, @@ -273,13 +273,13 @@ export default { attributes.push ({ key: 'today', dates: new Date(), highlight: { color: 'yellow' }}) attributes = attributes.concat(this.filteredEvents - .filter(e => !e.multidate) - .map(e => ({ key: e.id, dot: {}, dates: new Date(e.start_datetime)}))) + .filter(e => !e.multidate && !e.recurrent) + .map(e => ({ key: e.id, dot: {}, dates: moment.unix(e.start_datetime).toDate()}))) attributes = attributes.concat(this.filteredEvents - .filter(e => e.multidate) + .filter(e => e.multidate && !e.recurrent) .map( e => ({ key: e.id, highlight: {}, dates: { - start: new Date(e.start_datetime), end: new Date(e.end_datetime) }}))) + start: moment.unix(e.start_datetime).toDate(), end: moment.unix(e.end_datetime).toDate() }}))) if (this.event.type === 'recurrent' && this.event.recurrent.frequency) { const recurrent = {} diff --git a/pages/admin.vue b/pages/admin.vue index c0f764f3..40778faa 100644 --- a/pages/admin.vue +++ b/pages/admin.vue @@ -1,7 +1,8 @@ diff --git a/plugins/vue-awesome.js b/plugins/vue-awesome.js index 272a74f5..cf51e673 100644 --- a/plugins/vue-awesome.js +++ b/plugins/vue-awesome.js @@ -31,6 +31,7 @@ import 'vue-awesome/icons/envelope' import 'vue-awesome/icons/calendar-day' import 'vue-awesome/icons/calendar-week' import 'vue-awesome/icons/calendar-alt' +import 'vue-awesome/icons/circle-notch' import Icon from 'vue-awesome/components/Icon' diff --git a/server/api/controller/user.js b/server/api/controller/user.js index ce09cfab..72a875db 100644 --- a/server/api/controller/user.js +++ b/server/api/controller/user.js @@ -186,7 +186,12 @@ const userController = { if (!recover_code) return res.sendStatus(400) const user = await User.findOne({ where: { recover_code: { [Op.eq]: recover_code } } }) if (!user) return res.sendStatus(400) - res.json(user) + try { + await user.update({ recover_code: ''}) + res.sendStatus(200) + } catch (e) { + res.sendStatus(400) + } }, async updatePasswordWithRecoverCode(req, res) { @@ -195,6 +200,7 @@ const userController = { if (!recover_code || !password) return res.sendStatus(400) const user = await User.findOne({ where: { recover_code: { [Op.eq]: recover_code } } }) if (!user) return res.sendStatus(400) + user.recover_code = '' user.password = password try { await user.save() @@ -218,8 +224,8 @@ const userController = { async update(req, res) { const user = await User.findByPk(req.body.id) if (user) { - if (!user.is_active && req.body.is_active) { - await mail.send(user.email, 'confirm', { user, config }) + if (!user.is_active && req.body.is_active && user.recover_code) { + mail.send(user.email, 'confirm', { user, config }) } await user.update(req.body) res.json(user) @@ -240,9 +246,11 @@ const userController = { req.body.is_active = false } + req.body.recover_code = crypto.randomBytes(16).toString('hex') const user = await User.create(req.body) try { - mail.send([user.email, config.admin], 'register', { user, config }) + mail.send(user.email, 'register', { user, config }) + mail.send(config.admin, 'admin_register', { user, config }) } catch (e) { return res.status(400).json(e) } diff --git a/server/api/mail.js b/server/api/mail.js index e6072898..aa29674c 100644 --- a/server/api/mail.js +++ b/server/api/mail.js @@ -3,10 +3,12 @@ const path = require('path') const moment = require('moment') const config = require('config') const settings = require('./controller/settings') +const debug = require('debug')('email') moment.locale('it') const mail = { send(addresses, template, locals) { + debug(`Send ${template} email to ${addresses}`) const email = new Email({ views: { root: path.join(__dirname, '..', 'emails') }, htmlToText: false, @@ -18,15 +20,17 @@ const mail = { } }, message: { - from: `${config.title} <${config.smtp.auth.user}>` + from: `${config.title} <${config.admin}>` }, send: true, i18n: { directory: path.join(__dirname, '..', '..', 'locales', 'email'), + objectNotation: true, syncFiles: false, updateFiles: false, defaultLocale: settings.locale, - locales: ['en', 'it'] + locale: settings.locale, + locales: ['it', 'es'], }, transport: config.smtp }) @@ -45,7 +49,7 @@ const mail = { } return email.send(msg) .catch(e => { - console.error(e) + debug('Error sending email =>', e) }) } } diff --git a/server/api/models/event.js b/server/api/models/event.js index b0033135..fbfe85f1 100644 --- a/server/api/models/event.js +++ b/server/api/models/event.js @@ -36,11 +36,13 @@ module.exports = (sequelize, DataTypes) => { event.hasMany(models.comment) } + // event.prototype.toAP = function (username, follower) { const tags = this.tags && '-' + this.tags.map(t => '#' + t.tag).join(' ') const content = `${this.title} @${this.place.name} ${moment.unix(this.start_datetime).format('dddd, D MMMM (HH:mm)')}
${this.description.length > 200 ? this.description.substr(0, 200) + '...' : this.description} ${tags}
` + return { id: `${config.baseurl}/federation/m/c_${this.id}`, type: 'Create', diff --git a/server/emails/admin_register/html.pug b/server/emails/admin_register/html.pug new file mode 100644 index 00000000..ed6530f9 --- /dev/null +++ b/server/emails/admin_register/html.pug @@ -0,0 +1,4 @@ +extends ../layout.pug + +block content + p !{t('admin_register.content', { user, config })} diff --git a/server/emails/admin_register/subject.pug b/server/emails/admin_register/subject.pug new file mode 100644 index 00000000..3bd1d5de --- /dev/null +++ b/server/emails/admin_register/subject.pug @@ -0,0 +1 @@ +| [#{config.title}] #{t('admin_register.subject')} diff --git a/server/emails/admin_register/text.pug b/server/emails/admin_register/text.pug new file mode 100644 index 00000000..f86b83e2 --- /dev/null +++ b/server/emails/admin_register/text.pug @@ -0,0 +1,6 @@ +p= t('admin_register.content', { user, config }) + +hr +small #{config.title} / #{config.description} +br +small #{config.baseurl} diff --git a/server/emails/confirm/html.pug b/server/emails/confirm/html.pug index 091b2829..bd40b296 100644 --- a/server/emails/confirm/html.pug +++ b/server/emails/confirm/html.pug @@ -1,12 +1,3 @@ - -html(lang="en") - head - meta(charset="UTF-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0") - meta(http-equiv="X-UA-Compatible", content="ie=edge") - title #{config.title} - body - p= t('email.confirm', { config }) - - hr - #{config.title} - #{config.description} +extends ../layout.pug +block content + p !{t('confirm.content', { config, user })} \ No newline at end of file diff --git a/server/emails/confirm/subject.pug b/server/emails/confirm/subject.pug index 52cb1fb6..72a6cbae 100644 --- a/server/emails/confirm/subject.pug +++ b/server/emails/confirm/subject.pug @@ -1 +1 @@ -| [#{config.title}] #{t('email.confirm.subject')} \ No newline at end of file +| [#{config.title}] #{t('confirm.subject')} \ No newline at end of file diff --git a/server/emails/confirm/text.pug b/server/emails/confirm/text.pug new file mode 100644 index 00000000..5d6afacb --- /dev/null +++ b/server/emails/confirm/text.pug @@ -0,0 +1 @@ +p !{t('confirm.content', { config })} \ No newline at end of file diff --git a/server/emails/event/html.pug b/server/emails/event/html.pug index b69a1962..71f28eb2 100644 --- a/server/emails/event/html.pug +++ b/server/emails/event/html.pug @@ -1,22 +1,21 @@ -h3 #{event.title} -p Dove: #{event.place.name} - #{event.place.address} -p Quando: #{datetime(event.start_datetime)} -br -if event.image_path -
- -
-p #{event.description} +extends ../layout.pug +block content + h3 #{event.title} + p Dove: #{event.place.name} - #{event.place.address} + p Quando: #{datetime(event.start_datetime)} + br + if event.image_path +
+ +
+ p #{event.description} -each tag in event.tags - span ##{tag.tag} -br -#{config.baseurl}/event/#{event.id} -hr -if to_confirm - p Puoi confermare questo evento qui -else - p Puoi eliminare queste notifiche qui - -hr -#{config.title} - #{config.description} + each tag in event.tags + span ##{tag.tag} + br + #{config.baseurl}/event/#{event.id} + hr + if to_confirm + p Puoi confermare questo evento qui + else + p Puoi eliminare queste notifiche qui diff --git a/server/emails/event/text.pug b/server/emails/event/text.pug new file mode 100644 index 00000000..71f28eb2 --- /dev/null +++ b/server/emails/event/text.pug @@ -0,0 +1,21 @@ +extends ../layout.pug +block content + h3 #{event.title} + p Dove: #{event.place.name} - #{event.place.address} + p Quando: #{datetime(event.start_datetime)} + br + if event.image_path +
+ +
+ p #{event.description} + + each tag in event.tags + span ##{tag.tag} + br + #{config.baseurl}/event/#{event.id} + hr + if to_confirm + p Puoi confermare questo evento qui + else + p Puoi eliminare queste notifiche qui diff --git a/server/emails/layout.pug b/server/emails/layout.pug new file mode 100644 index 00000000..5ff2bf28 --- /dev/null +++ b/server/emails/layout.pug @@ -0,0 +1,13 @@ + +html(lang="en") + head + meta(charset="UTF-8") + meta(name="viewport", content="width=device-width, initial-scale=1.0") + meta(http-equiv="X-UA-Compatible", content="ie=edge") + title #{config.title} + body + block content + hr + small #{config.title} / #{config.description} + br + #{config.baseurl} \ No newline at end of file diff --git a/server/emails/recover/html.pug b/server/emails/recover/html.pug index d7b24e56..306d2690 100644 --- a/server/emails/recover/html.pug +++ b/server/emails/recover/html.pug @@ -1,12 +1,4 @@ - -html(lang="en") - head - meta(charset="UTF-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0") - meta(http-equiv="X-UA-Compatible", content="ie=edge") - title #{config.title} - body - p= t('email.recover', {config}) +extends ../layout.pug - hr - #{t('email.press_here')} +block content + p !{t('recover.content', {config, user})} \ No newline at end of file diff --git a/server/emails/recover/subject.pug b/server/emails/recover/subject.pug index 156103ca..2308d051 100644 --- a/server/emails/recover/subject.pug +++ b/server/emails/recover/subject.pug @@ -1 +1 @@ -= `[#{config.title}] ${t('email.recover')}` +| [#{config.title}] #{t('recover.subject')} diff --git a/server/emails/recover/text.pug b/server/emails/recover/text.pug new file mode 100644 index 00000000..4c47b008 --- /dev/null +++ b/server/emails/recover/text.pug @@ -0,0 +1 @@ +p= !t('recover.content', {config, user}) \ No newline at end of file diff --git a/server/emails/register/html.pug b/server/emails/register/html.pug index aef84feb..ec74ade9 100644 --- a/server/emails/register/html.pug +++ b/server/emails/register/html.pug @@ -1,6 +1,4 @@ -p= t('email.register') +extends ../layout.pug -hr -small #{config.title} / #{config.description} -br - #{config.baseurl} \ No newline at end of file +block content + p !{t('register.content', { user, config })} \ No newline at end of file diff --git a/server/emails/register/subject.pug b/server/emails/register/subject.pug index 6a7be433..c7613a90 100644 --- a/server/emails/register/subject.pug +++ b/server/emails/register/subject.pug @@ -1 +1 @@ -| [#{config.title}] #{t('email.register.subject')} +| [#{config.title}] #{t('register.subject')} diff --git a/server/emails/register/text.pug b/server/emails/register/text.pug index 7785b0cf..a4cb45f9 100644 --- a/server/emails/register/text.pug +++ b/server/emails/register/text.pug @@ -1,4 +1,4 @@ -p= t('email.register') +p= t('register.content', { config, user }) hr small #{config.title} / #{config.description} diff --git a/server/emails/user_confirm/html.pug b/server/emails/user_confirm/html.pug index 37f6aa32..7fcd2ce1 100644 --- a/server/emails/user_confirm/html.pug +++ b/server/emails/user_confirm/html.pug @@ -1,10 +1,3 @@ - -html(lang="en") - head - meta(charset="UTF-8") - meta(name="viewport", content="width=device-width, initial-scale=1.0") - meta(http-equiv="X-UA-Compatible", content="ie=edge") - title #{config.title} - body - - p !{t('email.user_confirm', { config, user })} +extends ../layout.pug +block content + p !{t('confirm.content', { config, user })} diff --git a/server/emails/user_confirm/subject.pug b/server/emails/user_confirm/subject.pug index 6d0067a6..72a6cbae 100644 --- a/server/emails/user_confirm/subject.pug +++ b/server/emails/user_confirm/subject.pug @@ -1 +1 @@ -= `[Gancio] Richiesta password recovery` +| [#{config.title}] #{t('confirm.subject')} \ No newline at end of file diff --git a/server/emails/user_confirm/text.pug b/server/emails/user_confirm/text.pug new file mode 100644 index 00000000..89326a44 --- /dev/null +++ b/server/emails/user_confirm/text.pug @@ -0,0 +1 @@ +p !{t('confirm.content', { config, user })}