From 5883589e19effff0ea2e420ba7d258b6d328b180 Mon Sep 17 00:00:00 2001 From: lesion Date: Thu, 7 Mar 2019 14:59:28 +0100 Subject: [PATCH] stream of consciousness --- .dockerignore | 3 +- .env | 3 + Dockerfile | 2 +- app/api.js | 23 ++- app/auth.js | 10 ++ app/config.js | 7 +- app/controller/bot.js | 107 ++++++------ app/controller/event.js | 31 +++- app/controller/user.js | 22 ++- app/model.js | 4 +- app/models/event.js | 13 +- client/.env | 3 - client/README.md | 20 ++- client/src/App.vue | 4 +- client/src/api.js | 3 + client/src/components/Admin.vue | 98 +++++++++-- client/src/components/Calendar.vue | 4 + client/src/components/Event.vue | 8 +- client/src/components/EventDetail.vue | 39 ++++- client/src/components/Export.vue | 18 +- client/src/components/Home.vue | 3 +- client/src/components/Nav.vue | 2 +- client/src/components/Register.vue | 7 +- client/src/components/Search.vue | 1 + client/src/components/Timeline.vue | 32 ++-- client/src/components/Typeahead.vue | 240 -------------------------- client/src/components/newEvent.vue | 12 +- client/src/locale/it.js | 7 + client/src/main.js | 4 +- client/src/store.js | 4 +- client/vue.config.js | 5 + client/yarn.lock | 11 +- docker-compose.yml | 2 + package.json | 1 + views/feed/rss.pug | 3 +- 35 files changed, 347 insertions(+), 409 deletions(-) delete mode 100644 client/.env delete mode 100644 client/src/components/Typeahead.vue diff --git a/.dockerignore b/.dockerignore index cf709889..3f05250c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,2 @@ -**/node_modules +client/node_modules +node_modules diff --git a/.env b/.env index 45a8838d..87485af9 100644 --- a/.env +++ b/.env @@ -1,5 +1,8 @@ BASE_URL=http://localhost:12300 +TITLE=Gancio +DESCRIPTION=diocane + ADMIN_EMAIL=admin@example.com SMTP_HOST=mail.example.com diff --git a/Dockerfile b/Dockerfile index 790a72cb..0c140f99 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ WORKDIR /usr/src/app COPY package.json . # install backend dependencies -RUN yarn install +RUN yarn # copy source COPY . . diff --git a/app/api.js b/app/api.js index c77ed637..c6fa75e3 100644 --- a/app/api.js +++ b/app/api.js @@ -1,6 +1,5 @@ const express = require('express') -const { isAuth, isAdmin } = require('./auth') - +const { fillUser, isAuth, isAdmin } = require('./auth') const eventController = require('./controller/event') const exportController = require('./controller/export') // const botController = require('./controller/bot') @@ -12,8 +11,7 @@ const api = express.Router() // USER API const userController = require('./controller/user') -api.route('/login') - .post(userController.login) +api.post('/login', userController.login) api.route('/user') .post(userController.register) @@ -25,23 +23,22 @@ api.put('/tag', isAuth, isAdmin, eventController.updateTag) api.put('/place', isAuth, isAdmin, eventController.updatePlace) api.route('/user/event') - .post(isAuth, upload.single('image'), userController.addEvent) + .post(fillUser, upload.single('image'), userController.addEvent) .get(isAuth, userController.getMyEvents) .put(isAuth, upload.single('image'), userController.updateEvent) -api.route('/user/event/:id') - .delete(isAuth, userController.delEvent) +api.delete('/user/event/:id', isAuth, userController.delEvent) api.get('/event/meta', eventController.getMeta) -api.route('/event/:event_id') - .get(eventController.get) +api.get('/event/unconfirmed', isAuth, isAdmin, eventController.getUnconfirmed) +api.post('/event/reminder', eventController.addReminder) + +api.get('/event/:event_id', eventController.get) +api.get('/event/confirm/:event_id', isAuth, isAdmin, eventController.confirm) -// api.get('/export/feed', exportController.feed) -// api.get('/export/ics', exportController.ics) api.get('/export/:type', exportController.export) -api.route('/event/:year/:month') - .get(eventController.getAll) +api.get('/event/:year/:month', eventController.getAll) api.post('/user/getauthurl', isAuth, userController.getAuthURL) api.post('/user/code', isAuth, userController.code) diff --git a/app/auth.js b/app/auth.js index efb45bc3..71396057 100644 --- a/app/auth.js +++ b/app/auth.js @@ -3,6 +3,16 @@ const config = require('./config') const User = require('./models/user') const Auth = { + async fillUser (req, res, next) { + const token = req.body.token || req.params.token || req.headers['x-access-token'] + console.log('[AUTH] ', token) + if (!token) next() + jwt.verify(token, config.secret, async (err, decoded) => { + if (err) next() + req.user = await User.findOne({ where: { email: decoded.email, is_active: true } }) + next() + }) + }, async isAuth (req, res, next) { const token = req.body.token || req.params.token || req.headers['x-access-token'] console.log('[AUTH] ', token) diff --git a/app/config.js b/app/config.js index 0a020d38..355c9a94 100644 --- a/app/config.js +++ b/app/config.js @@ -1,4 +1,7 @@ +/* backend configuration */ let db = {} +let apiurl + if (process.env.NODE_ENV === 'production') { db = { host: process.env.DB_HOST, @@ -7,11 +10,13 @@ if (process.env.NODE_ENV === 'production') { database: process.env.DB_NAME, dialect: 'postgres' } + apiurl = process.env.BASE_URL + '/api' } else { db = { dialect: 'sqlite', storage: './db.sqlite' } + apiurl = 'http://localhost:9000' } module.exports = { @@ -21,7 +26,7 @@ module.exports = { description: process.env.DESCRIPTION || 'A calendar for radical communities', baseurl: process.env.BASE_URL || 'http://localhost:8080', - apiurl: process.env.API_URL || 'http://localhost:9000', + apiurl, db, admin: process.env.ADMIN_EMAIL, diff --git a/app/controller/bot.js b/app/controller/bot.js index 885a91d2..d2c0104e 100644 --- a/app/controller/bot.js +++ b/app/controller/bot.js @@ -7,64 +7,65 @@ const moment = require('moment') moment.locale('it') const botController = { bots: [], - async initialize () { - console.log('initialize bots') - const botUsers = await User.findAll({ where: { mastodon_auth: { [Op.ne]: null } } }) - console.log(botUsers) - botController.bots = botUsers.map(user => { - console.log('initialize bot ', user.name) - console.log('.. ', user.mastodon_auth) - const { client_id, client_secret, access_token } = user.mastodon_auth - const bot = new Mastodon({ access_token, api_url: `https://${user.mastodon_instance}/api/v1/` }) - const listener = bot.stream('streaming/direct') - listener.on('message', botController.message) - listener.on('error', botController.error) - return { email: user.email, bot } - }) - console.log(botController.bots) - }, - add (user, token) { - const bot = new Mastodon({ access_token: user.mastodon_auth.access_token, api_url: `https://${user.mastodon_instance}/api/v1/` }) - const listener = bot.stream('streaming/direct') - listener.on('message', botController.message) - listener.on('error', botController.error) - botController.bots.push({ email: user.email, bot }) - }, + // async initialize () { + // console.log('initialize bots') + // const botUsers = await User.findAll({ where: { mastodon_auth: { [Op.ne]: null } } }) + // console.log(botUsers) + // botController.bots = botUsers.map(user => { + // console.log('initialize bot ', user.name) + // console.log('.. ', user.mastodon_auth) + // const { client_id, client_secret, access_token } = user.mastodon_auth + // const bot = new Mastodon({ access_token, api_url: `https://${user.mastodon_instance}/api/v1/` }) + // const listener = bot.stream('streaming/direct') + // listener.on('message', botController.message) + // listener.on('error', botController.error) + // return { email: user.email, bot } + // }) + // console.log(botController.bots) + // }, + // add (user, token) { + // const bot = new Mastodon({ access_token: user.mastodon_auth.access_token, api_url: `https://${user.mastodon_instance}/api/v1/` }) + // const listener = bot.stream('streaming/direct') + // listener.on('message', botController.message) + // listener.on('error', botController.error) + // botController.bots.push({ email: user.email, bot }) + // }, post (user, event) { - const { bot } = botController.bots.filter(b => b.email === user.email)[0] + const { client_id, client_secret, access_token } = user.mastodon_auth + const bot = new Mastodon({ access_token, api_url: `https://${user.mastodon_instance}/api/v1/` }) const status = `${event.title} @ ${event.place.name} ${moment(event.start_datetime).format('ddd, D MMMM HH:mm')} - ${event.description} - ${event.tags.map(t => '#' + t.tag).join(' ')} ${config.baseurl}/event/${event.id}` return bot.post('/statuses', { status, visibility: 'private' }) - }, - async message (msg) { - console.log(msg) - console.log(msg.data.accounts) - const replyid = msg.data.in_reply_to_id || msg.data.last_status.in_reply_to_id - if (!replyid) return - // const event = await Event.findOne({ where: { activitypub_id: replyid } }) - // if (!event) { - // check for comment.. - // const comment = await Comment.findOne( {where: { }}) - // } - // const comment = await Comment.create({activitypub_id: msg.data.last_status.id, text: msg.data.last_status.content, author: msg.data.accounts[0].username }) - // event.addComment(comment) - // console.log(event) - // const comment = await Comment.findOne( { where: {activitypub_id: msg.data.in_reply_to}} ) - // console.log('dentro message ', data) - - // add comment to specified event - // let comment - // if (!event) { - // const comment = await Comment.findOne({where: {activitypub_id: req.body.id}, include: Event}) - // event = comment.event - // } - // const comment = new Comment(req.body) - // event.addComment(comment) - }, - error (err) { - console.log('error ', err) } + // async message (msg) { + // console.log(msg) + // console.log(msg.data.accounts) + // const replyid = msg.data.in_reply_to_id || msg.data.last_status.in_reply_to_id + // if (!replyid) return + // const event = await Event.findOne({ where: { activitypub_id: replyid } }) + // if (!event) { + // check for comment.. + // const comment = await Comment.findOne( {where: { }}) + // } + // const comment = await Comment.create({activitypub_id: msg.data.last_status.id, text: msg.data.last_status.content, author: msg.data.accounts[0].username }) + // event.addComment(comment) + // console.log(event) + // const comment = await Comment.findOne( { where: {activitypub_id: msg.data.in_reply_to}} ) + // console.log('dentro message ', data) + + // add comment to specified event + // let comment + // if (!event) { + // const comment = await Comment.findOne({where: {activitypub_id: req.body.id}, include: Event}) + // event = comment.event + // } + // const comment = new Comment(req.body) + // event.addComment(comment) + // }, + // error (err) { + // console.log('error ', err) + // } } -setTimeout(botController.initialize, 2000) +// setTimeout(botController.initialize, 2000) module.exports = botController diff --git a/app/controller/event.js b/app/controller/event.js index 397b66e4..5a89d33e 100644 --- a/app/controller/event.js +++ b/app/controller/event.js @@ -1,4 +1,4 @@ -const { User, Event, Comment, Tag, Place } = require('../model') +const { User, Event, Comment, Tag, Place, MailReminder } = require('../model') const moment = require('moment') const Sequelize = require('sequelize') @@ -32,22 +32,51 @@ const eventController = { res.send(404) } }, + async updatePlace (req, res) { const place = await Place.findByPk(req.body.id) await place.update(req.body) res.json(place) }, + async get (req, res) { const id = req.params.event_id const event = await Event.findByPk(id, { include: [User, Tag, Comment, Place] }) res.json(event) }, + async confirm (req, res) { + const id = req.params.event_id + const event = await Event.findByPk(id) + try { + await event.update({ is_visible: true }) + res.send(200) + } catch (e) { + res.send(404) + } + }, + + async getUnconfirmed (req, res) { + const events = await Event.findAll({ + where: { + is_visible: false + }, + order: [['start_datetime', 'ASC']], + include: [Tag, Place] + }) + res.json(events) + }, + + async addReminder (req, res) { + await MailReminder.create(req.body.reminder) + res.json(200) + }, async getAll (req, res) { const start = moment().year(req.params.year).month(req.params.month).startOf('month').subtract(1, 'week') const end = moment().year(req.params.year).month(req.params.month).endOf('month').add(1, 'week') const events = await Event.findAll({ where: { + is_visible: true, [Sequelize.Op.and]: [ { start_datetime: { [Sequelize.Op.gte]: start } }, { start_datetime: { [Sequelize.Op.lte]: end } } diff --git a/app/controller/user.js b/app/controller/user.js index 9241229c..9c2d0008 100644 --- a/app/controller/user.js +++ b/app/controller/user.js @@ -15,10 +15,9 @@ const userController = { res.status(404).json({ success: false, message: 'AUTH_FAIL' }) } else if (user) { if (!user.is_active) { - res.status(403).json({ success: false, message: 'NOT)CONFIRMED' }) - } + res.status(403).json({ success: false, message: 'NOT_CONFIRMED' }) // check if password matches - else if (!await user.comparePassword(req.body.password)) { + } else if (!await user.comparePassword(req.body.password)) { res.status(403).json({ success: false, message: 'AUTH_FAIL' }) } else { // if user is found and password is right @@ -48,21 +47,26 @@ const userController = { await event.destroy() res.sendStatus(200) } else { - res.sendStatus(404) + res.sendStatus(403) } }, + // ADD EVENT async addEvent (req, res) { const body = req.body + + // remove description tag and create anchor tag const description = body.description .replace(/(<([^>]+)>)/ig, '') .replace(/(https?:\/\/[^\s]+)/g, '$1') + const eventDetails = { title: body.title, description, multidate: body.multidate, start_datetime: body.start_datetime, - end_datetime: body.end_datetime + end_datetime: body.end_datetime, + is_visible: req.user ? true : false } if (req.file) { @@ -88,14 +92,18 @@ const userController = { const tags = await Tag.findAll({ where: { tag: body.tags } }) await event.addTags(tags) } - await req.user.addEvent(event) + if (req.user) await req.user.addEvent(event) event = await Event.findByPk(event.id, { include: [User, Tag, Place] }) + // check if bot exists - if (req.user.mastodon_auth) { + if (req.user && req.user.mastodon_auth) { const post = await bot.post(req.user, event) event.activitypub_id = post.id event.save() } + + mail.send(config.admin, 'event', { event }) + return res.json(event) }, diff --git a/app/model.js b/app/model.js index c1d20a91..8948a26b 100644 --- a/app/model.js +++ b/app/model.js @@ -1,4 +1,4 @@ const User = require('./models/user') -const { Event, Comment, Tag, Place } = require('./models/event') +const { Event, Comment, Tag, Place, MailReminder } = require('./models/event') -module.exports = { User, Event, Comment, Tag, Place } +module.exports = { User, Event, Comment, Tag, Place, MailReminder } diff --git a/app/models/event.js b/app/models/event.js index 411006d6..ccb45d25 100644 --- a/app/models/event.js +++ b/app/models/event.js @@ -4,12 +4,13 @@ const User = require('./user') const Event = db.define('event', { title: Sequelize.STRING, - description: Sequelize.STRING, + description: Sequelize.TEXT, multidate: Sequelize.BOOLEAN, start_datetime: { type: Sequelize.DATE, index: true }, end_datetime: { type: Sequelize.DATE, index: true }, image_path: Sequelize.STRING, - activitypub_id: { type: Sequelize.INTEGER, index: true } + activitypub_id: { type: Sequelize.INTEGER, index: true }, + is_visible: Sequelize.BOOLEAN }) const Tag = db.define('tag', { @@ -23,11 +24,11 @@ const Comment = db.define('comment', { text: Sequelize.STRING }) -const MailSubscription = db.define('subscription', { +const MailReminder = db.define('reminder', { filters: Sequelize.JSON, - mail: Sequelize.TEXT, + mail: Sequelize.STRING, send_on_add: Sequelize.BOOLEAN, - send_reminder: Sequelize.INTEGER + send_reminder: Sequelize.BOOLEAN }) const Place = db.define('place', { @@ -47,4 +48,4 @@ Event.belongsTo(Place) User.hasMany(Event) Place.hasMany(Event) -module.exports = { Event, Comment, Tag, Place, MailSubscription } +module.exports = { Event, Comment, Tag, Place, MailReminder } diff --git a/client/.env b/client/.env deleted file mode 100644 index c4e197cc..00000000 --- a/client/.env +++ /dev/null @@ -1,3 +0,0 @@ -VUE_BASE_URL=https://localhost:8080/ -VUE_INSTANCE_API=https://localhost:9000/ -VUE_APP_TITLE=Eventi diff --git a/client/README.md b/client/README.md index 7b957bd1..aa6102de 100644 --- a/client/README.md +++ b/client/README.md @@ -1,4 +1,17 @@ # Gancio +an event manager for local communities + +##Install +We provide a docker way to run **gancio**. + +``` +git clone +``` + +##Development +``` +``` + ## Project setup ``` @@ -13,9 +26,4 @@ yarn run serve ### Compiles and minifies for production ``` yarn run build -``` - -### Lints and fixes files -``` -yarn run lint -``` +``` \ No newline at end of file diff --git a/client/src/App.vue b/client/src/App.vue index f0b34e4f..e53ba9a2 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -5,6 +5,7 @@ transition(name="fade" mode="out-in") router-view(name='modal') + +// export default { +// components: {event}, +// computed: mapState(['events', 'logged']) +// } +// diff --git a/client/src/components/Typeahead.vue b/client/src/components/Typeahead.vue deleted file mode 100644 index dc3a1410..00000000 --- a/client/src/components/Typeahead.vue +++ /dev/null @@ -1,240 +0,0 @@ - - - - - diff --git a/client/src/components/newEvent.vue b/client/src/components/newEvent.vue index 63e075ad..213df357 100644 --- a/client/src/components/newEvent.vue +++ b/client/src/components/newEvent.vue @@ -1,5 +1,4 @@