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
Pleroma
pleroma
Commits
078b8b6d
Commit
078b8b6d
authored
Dec 17, 2018
by
lain
Browse files
Merge branch 'phoenix14' into 'develop'
Upgrade to Phoenix 1.4 Closes
#451
See merge request
!560
parents
56735979
ba9ef77b
Pipeline
#5483
failed with stages
in 2 minutes and 1 second
Changes
16
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
config/config.exs
View file @
078b8b6d
...
...
@@ -50,6 +50,15 @@
# Configures the endpoint
config
:pleroma
,
Pleroma
.
Web
.
Endpoint
,
url:
[
host:
"localhost"
],
http:
[
dispatch:
[
{
:_
,
[
{
"/api/v1/streaming"
,
Elixir
.
Pleroma
.
Web
.
MastodonAPI
.
WebsocketHandler
,
[]},
{
:_
,
Plug
.
Adapters
.
Cowboy
.
Handler
,
{
Pleroma
.
Web
.
Endpoint
,
[]}}
]}
]
],
protocol:
"https"
,
secret_key_base:
"aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl"
,
signing_salt:
"CqaoopA2"
,
...
...
config/test.exs
View file @
078b8b6d
...
...
@@ -4,7 +4,8 @@
# you can enable the server option below.
config
:pleroma
,
Pleroma
.
Web
.
Endpoint
,
http:
[
port:
4001
],
server:
false
url:
[
port:
4001
],
server:
true
# Print only warnings and errors during test
config
:logger
,
level:
:warn
...
...
lib/pleroma/plugs/federating_plug.ex
View file @
078b8b6d
...
...
@@ -11,7 +11,8 @@ def call(conn, _opts) do
else
conn
|>
put_status
(
404
)
|>
Phoenix
.
Controller
.
render
(
Pleroma
.
Web
.
ErrorView
,
"404.json"
)
|>
Phoenix
.
Controller
.
put_view
(
Pleroma
.
Web
.
ErrorView
)
|>
Phoenix
.
Controller
.
render
(
"404.json"
)
|>
halt
()
end
end
...
...
lib/pleroma/web/channels/user_socket.ex
View file @
078b8b6d
...
...
@@ -6,10 +6,6 @@ defmodule Pleroma.Web.UserSocket do
# channel "room:*", Pleroma.Web.RoomChannel
channel
(
"chat:*"
,
Pleroma
.
Web
.
ChatChannel
)
## Transports
transport
(
:websocket
,
Phoenix
.
Transports
.
WebSocket
)
# transport :longpoll, Phoenix.Transports.LongPoll
# Socket params are passed from the client and can
# be used to verify and authenticate a user. After
# verification, you can put default assigns into
...
...
lib/pleroma/web/endpoint.ex
View file @
078b8b6d
...
...
@@ -3,8 +3,6 @@ defmodule Pleroma.Web.Endpoint do
socket
(
"/socket"
,
Pleroma
.
Web
.
UserSocket
)
socket
(
"/api/v1"
,
Pleroma
.
Web
.
MastodonAPI
.
MastodonSocket
)
# Serve at "/" the static files from "priv/static" directory.
#
# You should set gzip to true if you are running phoenix.digest
...
...
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
View file @
078b8b6d
...
...
@@ -226,7 +226,8 @@ def home_timeline(%{assigns: %{user: user}} = conn, params) do
conn
|>
add_link_headers
(
:home_timeline
,
activities
)
|>
render
(
StatusView
,
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
|>
put_view
(
StatusView
)
|>
render
(
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
end
def
public_timeline
(%{
assigns:
%{
user:
user
}}
=
conn
,
params
)
do
...
...
@@ -244,7 +245,8 @@ def public_timeline(%{assigns: %{user: user}} = conn, params) do
conn
|>
add_link_headers
(
:public_timeline
,
activities
,
false
,
%{
"local"
=>
local_only
})
|>
render
(
StatusView
,
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
|>
put_view
(
StatusView
)
|>
render
(
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
end
def
user_statuses
(%{
assigns:
%{
user:
reading_user
}}
=
conn
,
params
)
do
...
...
@@ -259,7 +261,8 @@ def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do
conn
|>
add_link_headers
(
:user_statuses
,
activities
,
params
[
"id"
])
|>
render
(
StatusView
,
"index.json"
,
%{
|>
put_view
(
StatusView
)
|>
render
(
"index.json"
,
%{
activities:
activities
,
for:
reading_user
,
as:
:activity
...
...
@@ -278,13 +281,16 @@ def dm_timeline(%{assigns: %{user: user}} = conn, params) do
conn
|>
add_link_headers
(
:dm_timeline
,
activities
)
|>
render
(
StatusView
,
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
|>
put_view
(
StatusView
)
|>
render
(
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
end
def
get_status
(%{
assigns:
%{
user:
user
}}
=
conn
,
%{
"id"
=>
id
})
do
with
%
Activity
{}
=
activity
<-
Repo
.
get
(
Activity
,
id
),
true
<-
ActivityPub
.
visible_for_user?
(
activity
,
user
)
do
try_render
(
conn
,
StatusView
,
"status.json"
,
%{
activity:
activity
,
for:
user
})
conn
|>
put_view
(
StatusView
)
|>
try_render
(
"status.json"
,
%{
activity:
activity
,
for:
user
})
end
end
...
...
@@ -347,7 +353,9 @@ def post_status(%{assigns: %{user: user}} = conn, %{"status" => _} = params) do
{
:ok
,
activity
}
=
Cachex
.
fetch!
(
:idempotency_cache
,
idempotency_key
,
fn
_
->
CommonAPI
.
post
(
user
,
params
)
end
)
try_render
(
conn
,
StatusView
,
"status.json"
,
%{
activity:
activity
,
for:
user
,
as:
:activity
})
conn
|>
put_view
(
StatusView
)
|>
try_render
(
"status.json"
,
%{
activity:
activity
,
for:
user
,
as:
:activity
})
end
def
delete_status
(%{
assigns:
%{
user:
user
}}
=
conn
,
%{
"id"
=>
id
})
do
...
...
@@ -363,28 +371,36 @@ def delete_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
def
reblog_status
(%{
assigns:
%{
user:
user
}}
=
conn
,
%{
"id"
=>
ap_id_or_id
})
do
with
{
:ok
,
announce
,
_activity
}
<-
CommonAPI
.
repeat
(
ap_id_or_id
,
user
)
do
try_render
(
conn
,
StatusView
,
"status.json"
,
%{
activity:
announce
,
for:
user
,
as:
:activity
})
conn
|>
put_view
(
StatusView
)
|>
try_render
(
"status.json"
,
%{
activity:
announce
,
for:
user
,
as:
:activity
})
end
end
def
unreblog_status
(%{
assigns:
%{
user:
user
}}
=
conn
,
%{
"id"
=>
ap_id_or_id
})
do
with
{
:ok
,
_unannounce
,
%{
data:
%{
"id"
=>
id
}}}
<-
CommonAPI
.
unrepeat
(
ap_id_or_id
,
user
),
%
Activity
{}
=
activity
<-
Activity
.
get_create_activity_by_object_ap_id
(
id
)
do
try_render
(
conn
,
StatusView
,
"status.json"
,
%{
activity:
activity
,
for:
user
,
as:
:activity
})
conn
|>
put_view
(
StatusView
)
|>
try_render
(
"status.json"
,
%{
activity:
activity
,
for:
user
,
as:
:activity
})
end
end
def
fav_status
(%{
assigns:
%{
user:
user
}}
=
conn
,
%{
"id"
=>
ap_id_or_id
})
do
with
{
:ok
,
_fav
,
%{
data:
%{
"id"
=>
id
}}}
<-
CommonAPI
.
favorite
(
ap_id_or_id
,
user
),
%
Activity
{}
=
activity
<-
Activity
.
get_create_activity_by_object_ap_id
(
id
)
do
try_render
(
conn
,
StatusView
,
"status.json"
,
%{
activity:
activity
,
for:
user
,
as:
:activity
})
conn
|>
put_view
(
StatusView
)
|>
try_render
(
"status.json"
,
%{
activity:
activity
,
for:
user
,
as:
:activity
})
end
end
def
unfav_status
(%{
assigns:
%{
user:
user
}}
=
conn
,
%{
"id"
=>
ap_id_or_id
})
do
with
{
:ok
,
_
,
_
,
%{
data:
%{
"id"
=>
id
}}}
<-
CommonAPI
.
unfavorite
(
ap_id_or_id
,
user
),
%
Activity
{}
=
activity
<-
Activity
.
get_create_activity_by_object_ap_id
(
id
)
do
try_render
(
conn
,
StatusView
,
"status.json"
,
%{
activity:
activity
,
for:
user
,
as:
:activity
})
conn
|>
put_view
(
StatusView
)
|>
try_render
(
"status.json"
,
%{
activity:
activity
,
for:
user
,
as:
:activity
})
end
end
...
...
@@ -433,7 +449,10 @@ def relationships(%{assigns: %{user: user}} = conn, %{"id" => id}) do
id
=
List
.
wrap
(
id
)
q
=
from
(
u
in
User
,
where:
u
.
id
in
^
id
)
targets
=
Repo
.
all
(
q
)
render
(
conn
,
AccountView
,
"relationships.json"
,
%{
user:
user
,
targets:
targets
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"relationships.json"
,
%{
user:
user
,
targets:
targets
})
end
# Instead of returning a 400 when no "id" params is present, Mastodon returns an empty array.
...
...
@@ -452,7 +471,10 @@ def update_media(%{assigns: %{user: user}} = conn, data) do
|>
Repo
.
update
()
attachment_data
=
Map
.
put
(
new_data
,
"id"
,
object
.
id
)
render
(
conn
,
StatusView
,
"attachment.json"
,
%{
attachment:
attachment_data
})
conn
|>
put_view
(
StatusView
)
|>
render
(
"attachment.json"
,
%{
attachment:
attachment_data
})
end
end
...
...
@@ -463,7 +485,10 @@ def upload(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do
description:
Map
.
get
(
data
,
"description"
)
)
do
attachment_data
=
Map
.
put
(
object
.
data
,
"id"
,
object
.
id
)
render
(
conn
,
StatusView
,
"attachment.json"
,
%{
attachment:
attachment_data
})
conn
|>
put_view
(
StatusView
)
|>
render
(
"attachment.json"
,
%{
attachment:
attachment_data
})
end
end
...
...
@@ -471,7 +496,10 @@ def favourited_by(conn, %{"id" => id}) do
with
%
Activity
{
data:
%{
"object"
=>
%{
"likes"
=>
likes
}}}
<-
Repo
.
get
(
Activity
,
id
)
do
q
=
from
(
u
in
User
,
where:
u
.
ap_id
in
^
likes
)
users
=
Repo
.
all
(
q
)
render
(
conn
,
AccountView
,
"accounts.json"
,
%{
users:
users
,
as:
:user
})
conn
|>
put_view
(
AccountView
)
|>
render
(
AccountView
,
"accounts.json"
,
%{
users:
users
,
as:
:user
})
else
_
->
json
(
conn
,
[])
end
...
...
@@ -481,7 +509,10 @@ def reblogged_by(conn, %{"id" => id}) do
with
%
Activity
{
data:
%{
"object"
=>
%{
"announcements"
=>
announces
}}}
<-
Repo
.
get
(
Activity
,
id
)
do
q
=
from
(
u
in
User
,
where:
u
.
ap_id
in
^
announces
)
users
=
Repo
.
all
(
q
)
render
(
conn
,
AccountView
,
"accounts.json"
,
%{
users:
users
,
as:
:user
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"accounts.json"
,
%{
users:
users
,
as:
:user
})
else
_
->
json
(
conn
,
[])
end
...
...
@@ -503,7 +534,8 @@ def hashtag_timeline(%{assigns: %{user: user}} = conn, params) do
conn
|>
add_link_headers
(
:hashtag_timeline
,
activities
,
params
[
"tag"
],
%{
"local"
=>
local_only
})
|>
render
(
StatusView
,
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
|>
put_view
(
StatusView
)
|>
render
(
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
end
def
followers
(%{
assigns:
%{
user:
for_user
}}
=
conn
,
%{
"id"
=>
id
})
do
...
...
@@ -516,7 +548,9 @@ def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
true
->
followers
end
render
(
conn
,
AccountView
,
"accounts.json"
,
%{
users:
followers
,
as:
:user
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"accounts.json"
,
%{
users:
followers
,
as:
:user
})
end
end
...
...
@@ -530,13 +564,17 @@ def following(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
true
->
followers
end
render
(
conn
,
AccountView
,
"accounts.json"
,
%{
users:
followers
,
as:
:user
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"accounts.json"
,
%{
users:
followers
,
as:
:user
})
end
end
def
follow_requests
(%{
assigns:
%{
user:
followed
}}
=
conn
,
_params
)
do
with
{
:ok
,
follow_requests
}
<-
User
.
get_follow_requests
(
followed
)
do
render
(
conn
,
AccountView
,
"accounts.json"
,
%{
users:
follow_requests
,
as:
:user
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"accounts.json"
,
%{
users:
follow_requests
,
as:
:user
})
end
end
...
...
@@ -552,7 +590,9 @@ def authorize_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}
object:
follow_activity
.
data
[
"id"
],
type:
"Accept"
})
do
render
(
conn
,
AccountView
,
"relationship.json"
,
%{
user:
followed
,
target:
follower
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"relationship.json"
,
%{
user:
followed
,
target:
follower
})
else
{
:error
,
message
}
->
conn
...
...
@@ -572,7 +612,9 @@ def reject_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) d
object:
follow_activity
.
data
[
"id"
],
type:
"Reject"
})
do
render
(
conn
,
AccountView
,
"relationship.json"
,
%{
user:
followed
,
target:
follower
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"relationship.json"
,
%{
user:
followed
,
target:
follower
})
else
{
:error
,
message
}
->
conn
...
...
@@ -591,7 +633,9 @@ def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
follower
,
followed
)
do
render
(
conn
,
AccountView
,
"relationship.json"
,
%{
user:
follower
,
target:
followed
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"relationship.json"
,
%{
user:
follower
,
target:
followed
})
else
{
:error
,
message
}
->
conn
...
...
@@ -604,7 +648,9 @@ def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
with
%
User
{}
=
followed
<-
Repo
.
get_by
(
User
,
nickname:
uri
),
{
:ok
,
follower
}
<-
User
.
maybe_direct_follow
(
follower
,
followed
),
{
:ok
,
_activity
}
<-
ActivityPub
.
follow
(
follower
,
followed
)
do
render
(
conn
,
AccountView
,
"account.json"
,
%{
user:
followed
,
for:
follower
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"account.json"
,
%{
user:
followed
,
for:
follower
})
else
{
:error
,
message
}
->
conn
...
...
@@ -617,7 +663,9 @@ def unfollow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
with
%
User
{}
=
followed
<-
Repo
.
get
(
User
,
id
),
{
:ok
,
_activity
}
<-
ActivityPub
.
unfollow
(
follower
,
followed
),
{
:ok
,
follower
,
_
}
<-
User
.
unfollow
(
follower
,
followed
)
do
render
(
conn
,
AccountView
,
"relationship.json"
,
%{
user:
follower
,
target:
followed
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"relationship.json"
,
%{
user:
follower
,
target:
followed
})
end
end
...
...
@@ -625,7 +673,9 @@ def block(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
with
%
User
{}
=
blocked
<-
Repo
.
get
(
User
,
id
),
{
:ok
,
blocker
}
<-
User
.
block
(
blocker
,
blocked
),
{
:ok
,
_activity
}
<-
ActivityPub
.
block
(
blocker
,
blocked
)
do
render
(
conn
,
AccountView
,
"relationship.json"
,
%{
user:
blocker
,
target:
blocked
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"relationship.json"
,
%{
user:
blocker
,
target:
blocked
})
else
{
:error
,
message
}
->
conn
...
...
@@ -638,7 +688,9 @@ def unblock(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
with
%
User
{}
=
blocked
<-
Repo
.
get
(
User
,
id
),
{
:ok
,
blocker
}
<-
User
.
unblock
(
blocker
,
blocked
),
{
:ok
,
_activity
}
<-
ActivityPub
.
unblock
(
blocker
,
blocked
)
do
render
(
conn
,
AccountView
,
"relationship.json"
,
%{
user:
blocker
,
target:
blocked
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"relationship.json"
,
%{
user:
blocker
,
target:
blocked
})
else
{
:error
,
message
}
->
conn
...
...
@@ -763,7 +815,8 @@ def favourites(%{assigns: %{user: user}} = conn, _) do
|>
Enum
.
reverse
()
conn
|>
render
(
StatusView
,
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
|>
put_view
(
StatusView
)
|>
render
(
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
end
def
get_lists
(%{
assigns:
%{
user:
user
}}
=
conn
,
opts
)
do
...
...
@@ -831,7 +884,9 @@ def remove_from_list(%{assigns: %{user: user}} = conn, %{"id" => id, "account_id
def
list_accounts
(%{
assigns:
%{
user:
user
}}
=
conn
,
%{
"id"
=>
id
})
do
with
%
Pleroma
.
List
{}
=
list
<-
Pleroma
.
List
.
get
(
id
,
user
),
{
:ok
,
users
}
=
Pleroma
.
List
.
get_following
(
list
)
do
render
(
conn
,
AccountView
,
"accounts.json"
,
%{
users:
users
,
as:
:user
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"accounts.json"
,
%{
users:
users
,
as:
:user
})
end
end
...
...
@@ -864,7 +919,8 @@ def list_timeline(%{assigns: %{user: user}} = conn, %{"list_id" => id} = params)
|>
Enum
.
reverse
()
conn
|>
render
(
StatusView
,
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
|>
put_view
(
StatusView
)
|>
render
(
"index.json"
,
%{
activities:
activities
,
for:
user
,
as:
:activity
})
else
_e
->
conn
...
...
@@ -968,7 +1024,8 @@ def index(%{assigns: %{user: user}} = conn, _params) do
conn
|>
put_layout
(
false
)
|>
render
(
MastodonView
,
"index.html"
,
%{
initial_state:
initial_state
})
|>
put_view
(
MastodonView
)
|>
render
(
"index.html"
,
%{
initial_state:
initial_state
})
else
conn
|>
redirect
(
to:
"/web/login"
)
...
...
@@ -1041,7 +1098,9 @@ def relationship_noop(%{assigns: %{user: user}} = conn, %{"id" => id}) do
Logger
.
debug
(
"Unimplemented, returning unmodified relationship"
)
with
%
User
{}
=
target
<-
Repo
.
get
(
User
,
id
)
do
render
(
conn
,
AccountView
,
"relationship.json"
,
%{
user:
user
,
target:
target
})
conn
|>
put_view
(
AccountView
)
|>
render
(
"relationship.json"
,
%{
user:
user
,
target:
target
})
end
end
...
...
@@ -1242,9 +1301,9 @@ def suggestions(%{assigns: %{user: user}} = conn, _) do
end
end
def
try_render
(
conn
,
renderer
,
target
,
params
)
def
try_render
(
conn
,
target
,
params
)
when
is_binary
(
target
)
do
res
=
render
(
conn
,
renderer
,
target
,
params
)
res
=
render
(
conn
,
target
,
params
)
if
res
==
nil
do
conn
...
...
@@ -1255,7 +1314,7 @@ def try_render(conn, renderer, target, params)
end
end
def
try_render
(
conn
,
_
,
_
,
_
)
do
def
try_render
(
conn
,
_
,
_
)
do
conn
|>
put_status
(
501
)
|>
json
(%{
error:
"Can't display this activity"
})
...
...
lib/pleroma/web/mastodon_api/mastodon_socket.ex
deleted
100644 → 0
View file @
56735979
defmodule
Pleroma
.
Web
.
MastodonAPI
.
MastodonSocket
do
use
Phoenix
.
Socket
alias
Pleroma
.
Web
.
OAuth
.
Token
alias
Pleroma
.
{
User
,
Repo
}
transport
(
:websocket
,
Phoenix
.
Transports
.
WebSocket
.
Raw
,
# We never receive data.
timeout:
:infinity
)
@spec
connect
(
params
::
map
(),
Phoenix
.
Socket
.
t
())
::
{
:ok
,
Phoenix
.
Socket
.
t
()}
|
:error
def
connect
(%{
"access_token"
=>
token
}
=
params
,
socket
)
do
with
%
Token
{
user_id:
user_id
}
<-
Repo
.
get_by
(
Token
,
token:
token
),
%
User
{}
=
user
<-
Repo
.
get
(
User
,
user_id
),
stream
when
stream
in
[
"public"
,
"public:local"
,
"public:media"
,
"public:local:media"
,
"user"
,
"direct"
,
"list"
,
"hashtag"
]
<-
params
[
"stream"
]
do
topic
=
case
stream
do
"hashtag"
->
"hashtag:
#{
params
[
"tag"
]
}
"
"list"
->
"list:
#{
params
[
"list"
]
}
"
_
->
stream
end
socket
=
socket
|>
assign
(
:topic
,
topic
)
|>
assign
(
:user
,
user
)
Pleroma
.
Web
.
Streamer
.
add_socket
(
topic
,
socket
)
{
:ok
,
socket
}
else
_e
->
:error
end
end
def
connect
(%{
"stream"
=>
stream
}
=
params
,
socket
)
when
stream
in
[
"public"
,
"public:local"
,
"hashtag"
]
do
topic
=
case
stream
do
"hashtag"
->
"hashtag:
#{
params
[
"tag"
]
}
"
_
->
stream
end
socket
=
socket
|>
assign
(
:topic
,
topic
)
Pleroma
.
Web
.
Streamer
.
add_socket
(
topic
,
socket
)
{
:ok
,
socket
}
end
def
connect
(
_params
,
_socket
),
do
:
:error
def
id
(
_
),
do
:
nil
def
handle
(
:text
,
message
,
_state
)
do
# | :ok
# | state
# | {:text, message}
# | {:text, message, state}
# | {:close, "Goodbye!"}
{
:text
,
message
}
end
def
handle
(
:closed
,
_
,
%{
socket:
socket
})
do
topic
=
socket
.
assigns
[
:topic
]
Pleroma
.
Web
.
Streamer
.
remove_socket
(
topic
,
socket
)
end
end
lib/pleroma/web/mastodon_api/websocket_handler.ex
0 → 100644
View file @
078b8b6d
defmodule
Pleroma
.
Web
.
MastodonAPI
.
WebsocketHandler
do
require
Logger
alias
Pleroma
.
Web
.
OAuth
.
Token
alias
Pleroma
.
{
User
,
Repo
}
@behaviour
:cowboy_websocket_handler
@streams
[
"public"
,
"public:local"
,
"public:media"
,
"public:local:media"
,
"user"
,
"direct"
,
"list"
,
"hashtag"
]
@anonymous_streams
[
"public"
,
"public:local"
,
"hashtag"
]
# Handled by periodic keepalive in Pleroma.Web.Streamer.
@timeout
:infinity
def
init
(
_type
,
_req
,
_opts
)
do
{
:upgrade
,
:protocol
,
:cowboy_websocket
}
end
def
websocket_init
(
_type
,
req
,
_opts
)
do
with
{
qs
,
req
}
<-
:cowboy_req
.
qs
(
req
),
params
<-
:cow_qs
.
parse_qs
(
qs
),
access_token
<-
List
.
keyfind
(
params
,
"access_token"
,
0
),
{
_
,
stream
}
<-
List
.
keyfind
(
params
,
"stream"
,
0
),
{
:ok
,
user
}
<-
allow_request
(
stream
,
access_token
),
topic
when
is_binary
(
topic
)
<-
expand_topic
(
stream
,
params
)
do
send
(
self
(),
:subscribe
)
{
:ok
,
req
,
%{
user:
user
,
topic:
topic
},
@timeout
}
else
{
:error
,
code
}
->
Logger
.
debug
(
"
#{
__MODULE__
}
denied connection:
#{
inspect
(
code
)
}
-
#{
inspect
(
req
)
}
"
)
{
:ok
,
req
}
=
:cowboy_req
.
reply
(
code
,
req
)
{
:shutdown
,
req
}
error
->
Logger
.
debug
(
"
#{
__MODULE__
}
denied connection:
#{
inspect
(
error
)
}
-
#{
inspect
(
req
)
}
"
)
{
:shutdown
,
req
}
end
end
# We never receive messages.
def
websocket_handle
(
_frame
,
req
,
state
)
do
{
:ok
,
req
,
state
}
end
def
websocket_info
(
:subscribe
,
req
,
state
)
do
Logger
.
debug
(
"
#{
__MODULE__
}
accepted websocket connection for user
#{
(
state
.
user
||
%{
id:
"anonymous"
}
).id
}, topic
#{
state
.
topic
}
"
)
Pleroma
.
Web
.
Streamer
.
add_socket
(
state
.
topic
,
streamer_socket
(
state
))
{
:ok
,
req
,
state
}
end
def
websocket_info
({
:text
,
message
},
req
,
state
)
do
{
:reply
,
{
:text
,
message
},
req
,
state
}
end
def
websocket_terminate
(
reason
,
_req
,
state
)
do
Logger
.
debug
(
"
#{
__MODULE__
}
terminating websocket connection for user
#{
(
state
.
user
||
%{
id:
"anonymous"
}
).id
}, topic
#{
state
.
topic
||
"?"
}
:
#{
inspect
(
reason
)
}
"
)
Pleroma
.
Web
.
Streamer
.
remove_socket
(
state
.
topic
,
streamer_socket
(
state
))
:ok
end
# Public streams without authentication.
defp
allow_request
(
stream
,
nil
)
when
stream
in
@anonymous_streams
do
{
:ok
,
nil
}
end
# Authenticated streams.
defp
allow_request
(
stream
,
{
"access_token"
,
access_token
})
when
stream
in
@streams
do
with
%
Token
{
user_id:
user_id
}
<-
Repo
.
get_by
(
Token
,
token:
access_token
),
user
=
%
User
{}
<-
Repo
.
get
(
User
,
user_id
)
do
{
:ok
,
user
}
else
_
->
{
:error
,
403
}
end
end
# Not authenticated.
defp
allow_request
(
stream
,
_
)
when
stream
in
@streams
,
do
:
{
:error
,
403
}
# No matching stream.
defp
allow_request
(
_
,
_
),
do
:
{
:error
,
404
}
defp
expand_topic
(
"hashtag"
,
params
)
do
case
List
.
keyfind
(
params
,
"tag"
,
0
)
do
{
_
,
tag
}
->
"hashtag:
#{
tag
}
"
_
->
nil
end