mirror of
https://framagit.org/les/gancio.git
synced 2025-01-31 16:42:22 +01:00
ego
This commit is contained in:
parent
5b013829fe
commit
40f7ffa99e
16 changed files with 183 additions and 51 deletions
|
@ -48,7 +48,9 @@ export default {
|
|||
enable: 'Enable',
|
||||
disable: 'Disable',
|
||||
me: 'You',
|
||||
password_updated: 'Password updated!'
|
||||
password_updated: 'Password updated!',
|
||||
username: 'Username',
|
||||
comments: 'Comments'
|
||||
},
|
||||
|
||||
login: {
|
||||
|
@ -123,7 +125,8 @@ export default {
|
|||
recurrent_2m_ordinal: '|The {n} {days} a month each two|The {n} {days} a month each two',
|
||||
due: 'due',
|
||||
from: 'From',
|
||||
image_too_big: 'Image too big! Max 4M'
|
||||
image_too_big: 'Image too big! Max 4M',
|
||||
interact_with_me_at: 'Interact with me on fediverse at'
|
||||
},
|
||||
|
||||
admin: {
|
||||
|
|
|
@ -49,7 +49,8 @@ export default {
|
|||
disable: 'Disabilita',
|
||||
me: 'Sei te',
|
||||
password_updated: 'Password modificata!',
|
||||
username: 'Nickname'
|
||||
username: 'Nickname',
|
||||
comments: 'Commenti'
|
||||
},
|
||||
|
||||
login: {
|
||||
|
@ -128,7 +129,8 @@ export default {
|
|||
each_month: 'Ogni mese',
|
||||
due: 'alle',
|
||||
from: 'Dalle',
|
||||
image_too_big: 'Immagine troppo grande! Massimo 4M'
|
||||
image_too_big: 'Immagine troppo grande! Massimo 4M',
|
||||
interact_with_me_at: 'Seguimi nel fediverso su'
|
||||
},
|
||||
|
||||
admin: {
|
||||
|
|
|
@ -60,15 +60,14 @@
|
|||
el-form-item(v-show='allow_recurrent_event' :label="$t('admin.recurrent_event_visible')")
|
||||
el-switch(v-model='recurrent_event_visible')
|
||||
|
||||
|
||||
el-divider {{$t('admin.federation')}}
|
||||
el-form(inline @submit.native.prevent='associate_mastondon_instance' label-width='240px')
|
||||
p {{$t('admin.mastodon_description')}}
|
||||
el-form-item(:label='$t("admin.mastodon_instance")')
|
||||
el-input(v-model="mastodon_instance")
|
||||
el-form-item
|
||||
el-button(native-type='submit' type='success' :disabled='!mastodon_instance') {{$t('common.associate')}}
|
||||
el-form-item(:label="$t('admin.allow_comments')")
|
||||
el-switch(v-model='allow_comments')
|
||||
el-form(inline label-width='400px')
|
||||
el-form-item(:label="$t('admin.enable_federation')")
|
||||
el-switch(v-model='enable_federation')
|
||||
|
||||
//- el-form-item(:label="$t('admin.allow_boost_like')")
|
||||
//- el-switch(v-model='allow_comments')
|
||||
|
||||
</template>
|
||||
<script>
|
||||
|
@ -130,10 +129,10 @@ export default {
|
|||
get () { return this.settings.recurrent_event_visible },
|
||||
set (value) { this.setSetting({ key: 'recurrent_event_visible', value })}
|
||||
},
|
||||
allow_comments: {
|
||||
get () { return this.settings.allow_comments },
|
||||
set (value) { this.setSetting({ key: 'allow_comments', value })}
|
||||
},
|
||||
enable_federation: {
|
||||
get () { return this.settings.enable_federation },
|
||||
set (value) { this.setSetting({ key: 'enable_federation', value })}
|
||||
},
|
||||
paginatedEvents () {
|
||||
return this.events.slice((this.eventPage-1) * this.perPage,
|
||||
this.eventPage * this.perPage)
|
||||
|
@ -151,12 +150,6 @@ export default {
|
|||
preview (id) {
|
||||
this.$router.push(`/event/${id}`)
|
||||
},
|
||||
async associate_mastondon_instance () {
|
||||
if (!this.mastodon_instance) return false
|
||||
|
||||
const url = await this.$axios.$post('/settings/getauthurl', { instance: this.mastodon_instance })
|
||||
setTimeout( () => window.location.href=url, 100);
|
||||
},
|
||||
async confirm (id) {
|
||||
try {
|
||||
this.loading = true
|
||||
|
|
|
@ -39,10 +39,11 @@
|
|||
el-button(plain type='danger' size='mini' @click.prevent='remove') {{$t('common.remove')}}
|
||||
el-button(plain type='primary' size='mini' @click='$router.replace(`/add/${event.id}`)') {{$t('common.edit')}}
|
||||
|
||||
//- comments
|
||||
#comments.card-body(v-if='event.comments.length')
|
||||
strong {{$t('common.related')}} -
|
||||
//a(:href='') {{$t('common.add')}}
|
||||
small {{event.likes.length}} - {{event.boost.length}}
|
||||
//- comments from fediverse
|
||||
#comments.card-body(v-if='settings.enable_federation')
|
||||
strong {{$t('common.comments')}} -
|
||||
<small>{{$t('event.interact_with_me_at')}} <u>{{event.user.username}}@{{settings.baseurl|url2host}}</u></small>
|
||||
|
||||
.card-header(v-for='comment in event.comments' :key='comment.id')
|
||||
a.float-right(:href='comment.data.url')
|
||||
|
|
|
@ -7,8 +7,8 @@ export default ({ app, store }) => {
|
|||
// replace links with anchors
|
||||
// TODO: remove fb tracking id
|
||||
Vue.filter('linkify', value => value.replace(/(https?:\/\/[^\s]+)/g, '<a href="$1">$1</a>'))
|
||||
|
||||
// Vue.filter('datetime', value => moment(value).locale(store.state.locale).format('ddd, D MMMM HH:mm'))
|
||||
Vue.filter('url2host', url => url.match(/^https?:\/\/(.[^/:]+)/i)[1])
|
||||
Vue.filter('datetime', value => moment(value).locale(store.state.locale).format('ddd, D MMMM HH:mm'))
|
||||
// Vue.filter('short_datetime', value => moment(value).locale(store.state.locale).format('D/MM HH:mm'))
|
||||
// Vue.filter('hour', value => moment(value).locale(store.state.locale).format('HH:mm'))
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ const crypto = require('crypto')
|
|||
const moment = require('moment')
|
||||
const { Op } = require('sequelize')
|
||||
const lodash = require('lodash')
|
||||
const { event: Event, comment: Comment, tag: Tag, place: Place, notification: Notification } = require('../models')
|
||||
const { event: Event, comment: Comment, tag: Tag, place: Place, user: User, notification: Notification } = require('../models')
|
||||
const Sequelize = require('sequelize')
|
||||
const notifier = require('../../notifier')
|
||||
|
||||
|
@ -94,6 +94,7 @@ const eventController = {
|
|||
},
|
||||
include: [
|
||||
{ model: Tag, attributes: ['tag', 'weigth'], through: { attributes: [] } },
|
||||
{ model: User, attributes: ['username'] },
|
||||
{ model: Place, attributes: ['name', 'address'] },
|
||||
Comment
|
||||
],
|
||||
|
|
|
@ -122,7 +122,9 @@ const userController = {
|
|||
// send response to client
|
||||
res.json(event)
|
||||
|
||||
federation.sendEvent(event, req.user)
|
||||
if (req.user)
|
||||
federation.sendEvent(event, req.user)
|
||||
|
||||
res.json(200)
|
||||
|
||||
// send notification (mastodon/email/confirmation)
|
||||
|
|
|
@ -101,8 +101,15 @@ api.get('/export/:type', exportController.export)
|
|||
api.get('/event/:month/:year', eventController.getAll)
|
||||
// api.get('/event/:month/:year', eventController.getAfter)
|
||||
|
||||
// mastodon oauth auth
|
||||
//api.post('/settings/getauthurl', jwt, isAuth, isAdmin, settingsController.getAuthURL)
|
||||
//api.get('/settings/oauth', jwt, isAuth, isAdmin, settingsController.code)
|
||||
// Handle 404
|
||||
api.use(function(req, res) {
|
||||
res.send('404: Page not Found', 404)
|
||||
})
|
||||
|
||||
// Handle 500
|
||||
api.use(function(error, req, res, next) {
|
||||
res.send('500: Internal Server Error', 500)
|
||||
})
|
||||
|
||||
|
||||
module.exports = api
|
||||
|
|
17
server/federation/ego.js
Normal file
17
server/federation/ego.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
const { event: Event } = require('../api/models')
|
||||
const config = require('config')
|
||||
|
||||
module.exports = {
|
||||
async boost (req, res) {
|
||||
const event_id = req.body.object.match(`${config.baseurl}/federation/m/(.*)`)[1]
|
||||
const event = await Event.findByPk(event_id)
|
||||
await event.update({ boost: [...event.boost, req.body.actor]})
|
||||
res.sendStatus(201)
|
||||
},
|
||||
async like (req, res) {
|
||||
const event_id = req.body.object.match(`${config.baseurl}/federation/m/(.*)`)[1]
|
||||
const event = await Event.findByPk(event_id)
|
||||
await event.update({ likes: [...event.likes, req.body.actor]})
|
||||
res.sendStatus(201)
|
||||
}
|
||||
}
|
|
@ -8,13 +8,12 @@ module.exports = {
|
|||
async follow (req, res, body, targetOrigin, domain) {
|
||||
if (typeof body.object !== 'string') return
|
||||
const username = body.object.replace(`${config.baseurl}/federation/u/`, '')
|
||||
console.error('someone wants to follow ' + username)
|
||||
const user = await User.findOne({ where: { username }})
|
||||
if (!user) {
|
||||
console.error('No user found!')
|
||||
res.sendStatus(404)
|
||||
return
|
||||
}
|
||||
console.error('FOLLOWERS ', user.followers)
|
||||
// check for duplicate
|
||||
if (user.followers.indexOf(body.actor) === -1) {
|
||||
console.error('ok this is a new follower: ', body.actor)
|
||||
await user.update({ followers: [...user.followers, body.actor] })
|
||||
|
@ -27,8 +26,8 @@ module.exports = {
|
|||
'actor': `${config.baseurl}/federation/u/${user.username}`,
|
||||
'object': body,
|
||||
}
|
||||
return Helpers.signAndSend(message, user, body.actor)
|
||||
|
||||
Helpers.signAndSend(message, user, body.actor)
|
||||
res.sendStatus(200)
|
||||
},
|
||||
// unfollow request from fediverse
|
||||
unfollow () {
|
||||
|
|
|
@ -55,6 +55,26 @@ const Helpers = {
|
|||
body['@context'] = 'https://www.w3.org/ns/activitystreams'
|
||||
Helpers.signAndSend(body, user, follower)
|
||||
}
|
||||
},
|
||||
|
||||
// TODO: cache
|
||||
// user: les@mastodon.cisti.org
|
||||
async getFederatedUser(address) {
|
||||
address = address.trim()
|
||||
let [ user, host ] = address.split('@')
|
||||
const url = `https://${host}/.well-known/webfinger?resource=acct:${user}@${host}`
|
||||
console.error('get federated user at => ', address, url)
|
||||
const user = await fetch(url, { headers: {'Accept': 'application/jrd+json, application/json'} })
|
||||
return user
|
||||
},
|
||||
|
||||
async verifySignature(req, res) {
|
||||
console.error(req.headers['signature'])
|
||||
// https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/
|
||||
const signature_header = req.headers['signature'].split(',')
|
||||
.map(pair => pair.split('='))
|
||||
console.error(signature_header)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ const Follows = require('./follows')
|
|||
const Users = require('./users')
|
||||
const { event: Event, user: User } = require('../api/models')
|
||||
const Comments = require('./comments')
|
||||
const Helpers = require('./helpers')
|
||||
const Ego = require('./ego')
|
||||
|
||||
/**
|
||||
* Federation is calling!
|
||||
|
@ -28,6 +30,11 @@ router.get('/m/:event_id', async (req, res) => {
|
|||
// get any message coming from federation
|
||||
// Federation is calling!
|
||||
router.post('/u/:name/inbox', async (req, res) => {
|
||||
|
||||
if (!Helpers.verifySignature(req, res)) {
|
||||
res.send('Request signature could not be verified', 401)
|
||||
}
|
||||
|
||||
const b = req.body
|
||||
console.error('> INBOX ', b.type, b)
|
||||
const targetOrigin = new URL(b.actor).origin
|
||||
|
@ -49,20 +56,18 @@ router.post('/u/:name/inbox', async (req, res) => {
|
|||
break
|
||||
case 'Announce':
|
||||
console.error('This is a boost ?')
|
||||
Ego.boost(req, res)
|
||||
break
|
||||
case 'Note':
|
||||
console.error('This is a note ! I probably should not receive this')
|
||||
break
|
||||
case 'Like':
|
||||
console.error('This is a like!')
|
||||
|
||||
Ego.like(req, res)
|
||||
break
|
||||
case 'Delete':
|
||||
console.error('Delete a comment ?!?!')
|
||||
break
|
||||
case 'Announce':
|
||||
console.error('Boost!')
|
||||
break
|
||||
case 'Create':
|
||||
// this is a reply
|
||||
if (b.object.type === 'Note' && b.object.inReplyTo) {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
const express = require('express')
|
||||
const router = express.Router()
|
||||
const { user: User } = require('../api/models')
|
||||
const cors = require('cors')
|
||||
const settingsController = require('../api/controller/settings')
|
||||
const config = require('config')
|
||||
const version = require('../../package.json').version
|
||||
|
||||
router.use(cors())
|
||||
|
||||
router.get('/', async (req, res) => {
|
||||
const ret = {
|
||||
version: '1.0',
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
const express = require('express')
|
||||
const router = express.Router()
|
||||
const { user: User } = require('../api/models')
|
||||
const cors = require('cors')
|
||||
const settingsController = require('../api/controller/settings')
|
||||
const config = require('config')
|
||||
const version = require('../../package.json').version
|
||||
|
||||
router.get('/', async (req, res) => {
|
||||
console.error('ma sono dentro webfinger ?!?!')
|
||||
router.use(cors())
|
||||
|
||||
router.get('/webfinger', async (req, res) => {
|
||||
const resource = req.query.resource
|
||||
if (!resource || !resource.includes('acct:')) {
|
||||
return res.status(400).send('Bad request. Please make sure "acct:USER@DOMAIN" is what you are sending as the "resource" query parameter.')
|
||||
|
@ -26,4 +30,78 @@ router.get('/', async (req, res) => {
|
|||
res.set('Content-Type', 'application/jrd+json; charset=utf-8')
|
||||
res.json(ret)
|
||||
})
|
||||
|
||||
router.get('/nodeinfo/:nodeinfo_version', async (req, res) => {
|
||||
const ret = {
|
||||
metadata: {
|
||||
nodeDescription: 'Gancio instance',
|
||||
nodeName: config.title
|
||||
},
|
||||
openRegistrations : settingsController.settings.allow_registration,
|
||||
protocols :['activitypub'],
|
||||
services: { inbound: [], outbound :["atom1.0"]},
|
||||
software: {
|
||||
name: 'gancio',
|
||||
version
|
||||
},
|
||||
usage: {
|
||||
localComments: 0,
|
||||
localPosts:0,
|
||||
users: {
|
||||
total:3
|
||||
}
|
||||
},
|
||||
version: req.params.nodeinfo_version
|
||||
}
|
||||
|
||||
if(req.params.nodeinfo_version === '2.1') {
|
||||
ret.software.repository = 'https://git.lattuga.net/cisti/gancio'
|
||||
}
|
||||
res.json(ret)
|
||||
})
|
||||
|
||||
router.get('/x-nodeinfo2', async (req, res) => {
|
||||
const ret = {
|
||||
version: '1.0',
|
||||
server: {
|
||||
baseUrl: config.baseurl,
|
||||
name: config.title,
|
||||
software: 'Gancio',
|
||||
version
|
||||
},
|
||||
protocols: ['activitypub'],
|
||||
openRegistrations: settingsController.settings.allow_registration,
|
||||
usage:{
|
||||
users: {
|
||||
total: 10
|
||||
}
|
||||
},
|
||||
localPost: 3,
|
||||
localComments: 0
|
||||
}
|
||||
res.json(ret)
|
||||
})
|
||||
|
||||
|
||||
router.get('/nodeinfo', async (req, res) => {
|
||||
const ret = {
|
||||
links: [
|
||||
{ href: `${config.baseurl}/.well-known/nodeinfo/2.0`, rel: `http://nodeinfo.diaspora.software/ns/schema/2.0` },
|
||||
{ href: `${config.baseurl}/.well-known/nodeinfo/2.1`, rel: `http://nodeinfo.diaspora.software/ns/schema/2.1` },
|
||||
]
|
||||
}
|
||||
res.json(ret)
|
||||
})
|
||||
|
||||
|
||||
// Handle 404
|
||||
router.use(function(req, res) {
|
||||
res.send('404: Page not Found', 404)
|
||||
})
|
||||
|
||||
// Handle 500
|
||||
router.use(function(error, req, res, next) {
|
||||
res.send('500: Internal Server Error', 500)
|
||||
})
|
||||
|
||||
module.exports = router
|
||||
|
|
|
@ -3,9 +3,12 @@ const path = require('path')
|
|||
const express = require('express')
|
||||
const consola = require('consola')
|
||||
const morgan = require('morgan')
|
||||
const cors = require('cors')
|
||||
const { Nuxt, Builder } = require('nuxt')
|
||||
|
||||
const api = require('./api')
|
||||
const federation = require('./federation')
|
||||
const webfinger = require('./federation/webfinger')
|
||||
|
||||
// Import and Set Nuxt.js options
|
||||
const nuxt_config = require('../nuxt.config.js')
|
||||
const config = require('config')
|
||||
|
@ -31,12 +34,11 @@ async function start() {
|
|||
app.use('/media/', express.static(config.upload_path))
|
||||
|
||||
// gancio standard api
|
||||
app.use('/api', require('./api/index'))
|
||||
app.use('/api', api)
|
||||
|
||||
// federation api / activitypub / webfinger / nodeinfo
|
||||
app.use('/.well-known/webfinger', cors(), require('./federation/webfinger'))
|
||||
app.use('/.well-known/x-nodeinfo2', cors(), require('./federation/nodeinfo'))
|
||||
app.use('/federation', require('./federation'))
|
||||
app.use('/.well-known', webfinger)
|
||||
app.use('/federation', federation)
|
||||
|
||||
// Give nuxt middleware to express
|
||||
app.use(nuxt.render)
|
||||
|
|
|
@ -12,7 +12,7 @@ export const state = () => ({
|
|||
allow_anon_event: true,
|
||||
allow_recurrent_event: true,
|
||||
recurrent_event_visible: false,
|
||||
allow_comments: false,
|
||||
enable_federation: false,
|
||||
},
|
||||
filters: {
|
||||
tags: [],
|
||||
|
|
Loading…
Reference in a new issue