Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
les
gancio
Commits
40f7ffa9
Commit
40f7ffa9
authored
Aug 02, 2019
by
les
Browse files
ego
parent
5b013829
Changes
16
Hide whitespace changes
Inline
Side-by-side
locales/en.js
View file @
40f7ffa9
...
...
@@ -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
:
{
...
...
locales/it.js
View file @
40f7ffa9
...
...
@@ -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
:
{
...
...
pages/admin.vue
View file @
40f7ffa9
...
...
@@ -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
...
...
pages/event/_id.vue
View file @
40f7ffa9
...
...
@@ -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')
...
...
plugins/filters.js
View file @
40f7ffa9
...
...
@@ -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'))
...
...
server/api/controller/event.js
View file @
40f7ffa9
...
...
@@ -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
],
...
...
server/api/controller/user.js
View file @
40f7ffa9
...
...
@@ -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)
...
...
server/api/index.js
View file @
40f7ffa9
...
...
@@ -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
server/federation/ego.js
0 → 100644
View file @
40f7ffa9
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
)
}
}
\ No newline at end of file
server/federation/follows.js
View file @
40f7ffa9
...
...
@@ -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
()
{
...
...
server/federation/helpers.js
View file @
40f7ffa9
...
...
@@ -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
}
}
...
...
server/federation/index.js
View file @
40f7ffa9
...
...
@@ -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
)
{
...
...
server/federation/nodeinfo.js
View file @
40f7ffa9
const
express
=
require
(
'
express
'
)
const
router
=
express
.
Router
()
const
{
user
:
User
}
=
require
(
'
../api/model
s
'
)
const
cors
=
require
(
'
cor
s
'
)
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
'
,
...
...
server/federation/webfinger.js
View file @
40f7ffa9
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
server/index.js
View file @
40f7ffa9
...
...
@@ -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
)
...
...
store/index.js
View file @
40f7ffa9
...
...
@@ -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
:
[],
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment