Merge remote-tracking branch 'upstream/develop' into media-proxy
This commit is contained in:
commit
72f7baa654
28 changed files with 126 additions and 32 deletions
|
@ -20,6 +20,7 @@ def start(_type, _args) do
|
||||||
limit: 2500
|
limit: 2500
|
||||||
]]),
|
]]),
|
||||||
worker(Pleroma.Web.Federator, []),
|
worker(Pleroma.Web.Federator, []),
|
||||||
|
worker(Pleroma.Web.ChatChannel.ChatChannelState, []),
|
||||||
]
|
]
|
||||||
++ if Mix.env == :test, do: [], else: [worker(Pleroma.Web.Streamer, [])]
|
++ if Mix.env == :test, do: [], else: [worker(Pleroma.Web.Streamer, [])]
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ defp verify(user, password, _user_id) do
|
||||||
defp decode_header(conn) do
|
defp decode_header(conn) do
|
||||||
with ["Basic " <> header] <- get_req_header(conn, "authorization"),
|
with ["Basic " <> header] <- get_req_header(conn, "authorization"),
|
||||||
{:ok, userinfo} <- Base.decode64(header),
|
{:ok, userinfo} <- Base.decode64(header),
|
||||||
[username, password] <- String.split(userinfo, ":")
|
[username, password] <- String.split(userinfo, ":", parts: 2)
|
||||||
do
|
do
|
||||||
{:ok, username, password}
|
{:ok, username, password}
|
||||||
end
|
end
|
||||||
|
|
|
@ -329,4 +329,9 @@ def blocks?(user, %{ap_id: ap_id}) do
|
||||||
Enum.member?(blocks, ap_id)
|
Enum.member?(blocks, ap_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def local_user_query() do
|
||||||
|
from u in User,
|
||||||
|
where: u.local == true
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
defmodule Pleroma.Web.UserSocket do
|
defmodule Pleroma.Web.UserSocket do
|
||||||
use Phoenix.Socket
|
use Phoenix.Socket
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Comeonin.Pbkdf2
|
||||||
|
|
||||||
## Channels
|
## Channels
|
||||||
# channel "room:*", Pleroma.Web.RoomChannel
|
# channel "room:*", Pleroma.Web.RoomChannel
|
||||||
|
channel "chat:*", Pleroma.Web.ChatChannel
|
||||||
|
|
||||||
## Transports
|
## Transports
|
||||||
transport :websocket, Phoenix.Transports.WebSocket
|
transport :websocket, Phoenix.Transports.WebSocket
|
||||||
|
@ -19,8 +22,13 @@ defmodule Pleroma.Web.UserSocket do
|
||||||
#
|
#
|
||||||
# See `Phoenix.Token` documentation for examples in
|
# See `Phoenix.Token` documentation for examples in
|
||||||
# performing token verification on connect.
|
# performing token verification on connect.
|
||||||
def connect(_params, socket) do
|
def connect(%{"token" => token}, socket) do
|
||||||
{:ok, socket}
|
with {:ok, user_id} <- Phoenix.Token.verify(socket, "user socket", token, max_age: 84600),
|
||||||
|
%User{} = user <- Pleroma.Repo.get(User, user_id) do
|
||||||
|
{:ok, assign(socket, :user_name, user.nickname)}
|
||||||
|
else
|
||||||
|
_e -> :error
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Socket id's are topics that allow you to identify all sockets for a given user:
|
# Socket id's are topics that allow you to identify all sockets for a given user:
|
||||||
|
|
46
lib/pleroma/web/chat_channel.ex
Normal file
46
lib/pleroma/web/chat_channel.ex
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
defmodule Pleroma.Web.ChatChannel do
|
||||||
|
use Phoenix.Channel
|
||||||
|
alias Pleroma.Web.ChatChannel.ChatChannelState
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
|
def join("chat:public", _message, socket) do
|
||||||
|
send(self(), :after_join)
|
||||||
|
{:ok, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_info(:after_join, socket) do
|
||||||
|
push socket, "messages", %{messages: ChatChannelState.messages()}
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_in("new_msg", %{"text" => text}, %{assigns: %{user_name: user_name}} = socket) do
|
||||||
|
author = User.get_cached_by_nickname(user_name)
|
||||||
|
author = Pleroma.Web.MastodonAPI.AccountView.render("account.json", user: author)
|
||||||
|
message = ChatChannelState.add_message(%{text: text, author: author})
|
||||||
|
|
||||||
|
broadcast! socket, "new_msg", message
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ChatChannel.ChatChannelState do
|
||||||
|
use Agent
|
||||||
|
@max_messages 20
|
||||||
|
|
||||||
|
def start_link do
|
||||||
|
Agent.start_link(fn -> %{max_id: 1, messages: []} end, name: __MODULE__)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_message(message) do
|
||||||
|
Agent.get_and_update(__MODULE__, fn state ->
|
||||||
|
id = state[:max_id] + 1
|
||||||
|
message = Map.put(message, "id", id)
|
||||||
|
messages = [message | state[:messages]] |> Enum.take(@max_messages)
|
||||||
|
{message, %{max_id: id, messages: messages}}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def messages() do
|
||||||
|
Agent.get(__MODULE__, fn state -> state[:messages] |> Enum.reverse end)
|
||||||
|
end
|
||||||
|
end
|
|
@ -93,6 +93,7 @@ def user(conn, %{"id" => id}) do
|
||||||
@instance Application.get_env(:pleroma, :instance)
|
@instance Application.get_env(:pleroma, :instance)
|
||||||
|
|
||||||
def masto_instance(conn, _params) do
|
def masto_instance(conn, _params) do
|
||||||
|
user_count = Repo.aggregate(User.local_user_query, :count, :id)
|
||||||
response = %{
|
response = %{
|
||||||
uri: Web.base_url,
|
uri: Web.base_url,
|
||||||
title: Keyword.get(@instance, :name),
|
title: Keyword.get(@instance, :name),
|
||||||
|
@ -103,8 +104,8 @@ def masto_instance(conn, _params) do
|
||||||
streaming_api: String.replace(Web.base_url, ["http","https"], "wss")
|
streaming_api: String.replace(Web.base_url, ["http","https"], "wss")
|
||||||
},
|
},
|
||||||
stats: %{
|
stats: %{
|
||||||
user_count: 1,
|
|
||||||
status_count: 2,
|
status_count: 2,
|
||||||
|
user_count: user_count,
|
||||||
domain_count: 3
|
domain_count: 3
|
||||||
},
|
},
|
||||||
max_toot_chars: Keyword.get(@instance, :limit)
|
max_toot_chars: Keyword.get(@instance, :limit)
|
||||||
|
|
|
@ -19,6 +19,7 @@ def to_simple_form(user) do
|
||||||
{:"poco:preferredUsername", [nickname]},
|
{:"poco:preferredUsername", [nickname]},
|
||||||
{:"poco:displayName", [name]},
|
{:"poco:displayName", [name]},
|
||||||
{:"poco:note", [bio]},
|
{:"poco:note", [bio]},
|
||||||
|
{:summary, [bio]},
|
||||||
{:name, [nickname]},
|
{:name, [nickname]},
|
||||||
{:link, [rel: 'avatar', href: avatar_url], []}
|
{:link, [rel: 'avatar', href: avatar_url], []}
|
||||||
] ++ banner
|
] ++ banner
|
||||||
|
|
|
@ -10,7 +10,8 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
def verify_credentials(%{assigns: %{user: user}} = conn, _params) do
|
def verify_credentials(%{assigns: %{user: user}} = conn, _params) do
|
||||||
render(conn, UserView, "show.json", %{user: user})
|
token = Phoenix.Token.sign(conn, "user socket", user.id)
|
||||||
|
render(conn, UserView, "show.json", %{user: user, token: token})
|
||||||
end
|
end
|
||||||
|
|
||||||
def status_update(%{assigns: %{user: user}} = conn, %{"status" => _} = status_data) do
|
def status_update(%{assigns: %{user: user}} = conn, %{"status" => _} = status_data) do
|
||||||
|
|
|
@ -26,7 +26,7 @@ def render("user.json", %{user: user = %User{}} = assigns) do
|
||||||
|
|
||||||
user_info = User.get_cached_user_info(user)
|
user_info = User.get_cached_user_info(user)
|
||||||
|
|
||||||
%{
|
data = %{
|
||||||
"created_at" => user.inserted_at |> Utils.format_naive_asctime,
|
"created_at" => user.inserted_at |> Utils.format_naive_asctime,
|
||||||
"description" => HtmlSanitizeEx.strip_tags(user.bio),
|
"description" => HtmlSanitizeEx.strip_tags(user.bio),
|
||||||
"favourites_count" => 0,
|
"favourites_count" => 0,
|
||||||
|
@ -48,6 +48,12 @@ def render("user.json", %{user: user = %User{}} = assigns) do
|
||||||
"cover_photo" => image_url(user.info["banner"]) |> MediaProxy.url(),
|
"cover_photo" => image_url(user.info["banner"]) |> MediaProxy.url(),
|
||||||
"background_image" => image_url(user.info["background"]) |> MediaProxy.url(),
|
"background_image" => image_url(user.info["background"]) |> MediaProxy.url(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if assigns[:token] do
|
||||||
|
Map.put(data, "token", assigns[:token])
|
||||||
|
else
|
||||||
|
data
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("short.json", %{user: %User{
|
def render("short.json", %{user: %User{
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.AddLocalIndexToUser do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create index(:users, [:local])
|
||||||
|
end
|
||||||
|
end
|
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.1c9a07d790a4262baf47d33a2a3e71c5.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.8e9b51ea14e08fc9a22a.js></script><script type=text/javascript src=/static/js/vendor.6ffc1793217fe26edf39.js></script><script type=text/javascript src=/static/js/app.a4d345815ef9d13e9524.js></script></body></html>
|
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.67f64792f89a96e59442c437c7ded0b3.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.ee87253244897e08bdce.js></script><script type=text/javascript src=/static/js/vendor.50cd70f77f559bfe1f27.js></script><script type=text/javascript src=/static/js/app.fefccf252cac9e1310ea.js></script></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
priv/static/static/js/app.fefccf252cac9e1310ea.js
Normal file
6
priv/static/static/js/app.fefccf252cac9e1310ea.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/static/js/app.fefccf252cac9e1310ea.js.map
Normal file
1
priv/static/static/js/app.fefccf252cac9e1310ea.js.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,2 +0,0 @@
|
||||||
!function(e){function t(n){if(r[n])return r[n].exports;var a=r[n]={exports:{},id:n,loaded:!1};return e[n].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n=window.webpackJsonp;window.webpackJsonp=function(o,c){for(var p,s,l=0,f=[];l<o.length;l++)s=o[l],a[s]&&f.push.apply(f,a[s]),a[s]=0;for(p in c)e[p]=c[p];for(n&&n(o,c);f.length;)f.shift().call(null,t);if(c[0])return r[0]=0,t(0)};var r={},a={0:0};t.e=function(e,n){if(0===a[e])return n.call(null,t);if(void 0!==a[e])a[e].push(n);else{a[e]=[n];var r=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.src=t.p+"static/js/"+e+"."+{1:"6ffc1793217fe26edf39",2:"a4d345815ef9d13e9524"}[e]+".js",r.appendChild(o)}},t.m=e,t.c=r,t.p="/"}([]);
|
|
||||||
//# sourceMappingURL=manifest.8e9b51ea14e08fc9a22a.js.map
|
|
2
priv/static/static/js/manifest.ee87253244897e08bdce.js
Normal file
2
priv/static/static/js/manifest.ee87253244897e08bdce.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
!function(e){function t(n){if(r[n])return r[n].exports;var a=r[n]={exports:{},id:n,loaded:!1};return e[n].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n=window.webpackJsonp;window.webpackJsonp=function(c,o){for(var f,p,s=0,l=[];s<c.length;s++)p=c[s],a[p]&&l.push.apply(l,a[p]),a[p]=0;for(f in o)e[f]=o[f];for(n&&n(c,o);l.length;)l.shift().call(null,t);if(o[0])return r[0]=0,t(0)};var r={},a={0:0};t.e=function(e,n){if(0===a[e])return n.call(null,t);if(void 0!==a[e])a[e].push(n);else{a[e]=[n];var r=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.src=t.p+"static/js/"+e+"."+{1:"50cd70f77f559bfe1f27",2:"fefccf252cac9e1310ea"}[e]+".js",r.appendChild(c)}},t.m=e,t.c=r,t.p="/"}([]);
|
||||||
|
//# sourceMappingURL=manifest.ee87253244897e08bdce.js.map
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
priv/static/static/js/vendor.50cd70f77f559bfe1f27.js.map
Normal file
1
priv/static/static/js/vendor.50cd70f77f559bfe1f27.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -573,4 +573,19 @@ test "updates the user's banner" do
|
||||||
assert user["header"] != "https://placehold.it/700x335"
|
assert user["header"] != "https://placehold.it/700x335"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "get instance information" do
|
||||||
|
insert(:user, %{local: true})
|
||||||
|
user = insert(:user, %{local: true})
|
||||||
|
insert(:user, %{local: false})
|
||||||
|
|
||||||
|
{:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
|
||||||
|
|
||||||
|
conn = conn
|
||||||
|
|> get("/api/v1/instance")
|
||||||
|
|
||||||
|
assert result = json_response(conn, 200)
|
||||||
|
|
||||||
|
assert result["stats"]["user_count"] == 2
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,7 @@ test "returns a user with id, uri, name and link" do
|
||||||
<poco:preferredUsername>#{user.nickname}</poco:preferredUsername>
|
<poco:preferredUsername>#{user.nickname}</poco:preferredUsername>
|
||||||
<poco:displayName>#{user.name}</poco:displayName>
|
<poco:displayName>#{user.name}</poco:displayName>
|
||||||
<poco:note>#{user.bio}</poco:note>
|
<poco:note>#{user.bio}</poco:note>
|
||||||
|
<summary>#{user.bio}</summary>
|
||||||
<name>#{user.nickname}</name>
|
<name>#{user.nickname}</name>
|
||||||
<link rel="avatar" href="#{User.avatar_url(user)}" />
|
<link rel="avatar" href="#{User.avatar_url(user)}" />
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -22,7 +22,8 @@ test "with credentials", %{conn: conn, user: user} do
|
||||||
|> with_credentials(user.nickname, "test")
|
|> with_credentials(user.nickname, "test")
|
||||||
|> post("/api/account/verify_credentials.json")
|
|> post("/api/account/verify_credentials.json")
|
||||||
|
|
||||||
assert json_response(conn, 200) == UserView.render("show.json", %{user: user})
|
assert response = json_response(conn, 200)
|
||||||
|
assert response == UserView.render("show.json", %{user: user, token: response["token"]})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue