Merge branch 'develop' of ssh.gitgud.io:lambadalambda/pleroma into feature/user-timeline

This commit is contained in:
dtluna 2017-04-16 17:08:17 +03:00
commit 5229b01944
22 changed files with 143 additions and 47 deletions

View file

@ -18,6 +18,31 @@ defmodule Pleroma.Upload do
}
end
def store(%{"img" => "data:image/" <> image_data}) do
parsed = Regex.named_captures(~r/(?<filetype>jpeg|png|gif);base64,(?<data>.*)/, image_data)
data = Base.decode64!(parsed["data"])
uuid = Ecto.UUID.generate
upload_folder = Path.join(upload_path(), uuid)
File.mkdir_p!(upload_folder)
filename = Base.encode16(:crypto.hash(:sha256, data)) <> ".#{parsed["filetype"]}"
result_file = Path.join(upload_folder, filename)
File.write!(result_file, data)
content_type = "image/#{parsed["filetype"]}"
%{
"type" => "Image",
"url" => [%{
"type" => "Link",
"mediaType" => content_type,
"href" => url_for(Path.join(uuid, filename))
}],
"name" => filename,
"uuid" => uuid
}
end
defp upload_path do
Application.get_env(:pleroma, Pleroma.Upload)
|> Keyword.fetch!(:uploads)

View file

@ -13,6 +13,7 @@ defmodule Pleroma.User do
field :password_confirmation, :string, virtual: true
field :following, { :array, :string }, default: []
field :ap_id, :string
field :avatar, :map
timestamps()
end

View file

@ -174,7 +174,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
Repo.all(query)
end
def upload(%Plug.Upload{} = file) do
def upload(file) do
data = Upload.store(file)
Repo.insert(%Object{data: data})
end

View file

@ -46,5 +46,6 @@ defmodule Pleroma.Web.Router do
post "/favorites/create", TwitterAPI.Controller, :favorite
post "/favorites/destroy/:id", TwitterAPI.Controller, :unfavorite
post "/statuses/retweet/:id", TwitterAPI.Controller, :retweet
post "/qvitter/update_avatar", TwitterAPI.Controller, :update_avatar
end
end

View file

@ -4,8 +4,10 @@ defmodule Pleroma.Web.TwitterAPI.Representers.UserRepresenter do
alias Pleroma.User
def to_map(user, opts) do
image = "https://placehold.it/48x48"
image = case user.avatar do
%{"url" => [%{"href" => href} | _]} -> href
_ -> "https://placehold.it/48x48"
end
following = if opts[:for] do
User.following?(opts[:for], user)

View file

@ -3,6 +3,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.Web.TwitterAPI.Representers.{UserRepresenter, ActivityRepresenter}
alias Pleroma.{Repo, Activity}
alias Pleroma.Web.ActivityPub.ActivityPub
def verify_credentials(%{assigns: %{user: user}} = conn, _params) do
response = user |> UserRepresenter.to_json(%{for: user})
@ -154,6 +155,18 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
end
end
def update_avatar(%{assigns: %{user: user}} = conn, params) do
{:ok, object} = ActivityPub.upload(params)
change = Ecto.Changeset.change(user, %{avatar: object.data})
{:ok, user} = Repo.update(change)
response = UserRepresenter.to_map(user, %{for: user})
|> Poison.encode!
conn
|> json_reply(200, response)
end
defp bad_request_reply(conn, error_message) do
json = Poison.encode!(%{"error" => error_message})
json_reply(conn, 400, json)

View file

@ -0,0 +1,9 @@
defmodule Pleroma.Repo.Migrations.AddAvatarObjectToUsers do
use Ecto.Migration
def change do
alter table(:users) do
add :avatar, :map
end
end
end

View file

@ -1 +1 @@
<!DOCTYPE html><html><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.a86c13eb46180b1b975a1acd59b52cc6.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.da7ea91e505330123f38.js></script><script type=text/javascript src=/static/js/vendor.d7d8813599feb765b152.js></script><script type=text/javascript src=/static/js/app.dcc60205ebdef9eb3d87.js></script></body></html>
<!DOCTYPE html><html><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.a86c13eb46180b1b975a1acd59b52cc6.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.66d994092e61600982a8.js></script><script type=text/javascript src=/static/js/vendor.d7d8813599feb765b152.js></script><script type=text/javascript src=/static/js/app.d4e0a640b375c4b52997.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

View 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(o,c){for(var p,s,l=0,i=[];l<o.length;l++)s=o[l],a[s]&&i.push.apply(i,a[s]),a[s]=0;for(p in c)e[p]=c[p];for(n&&n(o,c);i.length;)i.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:"d7d8813599feb765b152",2:"d4e0a640b375c4b52997"}[e]+".js",r.appendChild(o)}},t.m=e,t.c=r,t.p="/"}([]);
//# sourceMappingURL=manifest.66d994092e61600982a8.js.map

View file

@ -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(c,o){for(var p,s,l=0,d=[];l<c.length;l++)s=c[l],a[s]&&d.push.apply(d,a[s]),a[s]=0;for(p in o)e[p]=o[p];for(n&&n(c,o);d.length;)d.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:"d7d8813599feb765b152",2:"dcc60205ebdef9eb3d87"}[e]+".js",r.appendChild(c)}},t.m=e,t.c=r,t.p="/"}([]);
//# sourceMappingURL=manifest.da7ea91e505330123f38.js.map

View file

@ -3,7 +3,7 @@ defmodule Pleroma.Builders.ActivityBuilder do
alias Pleroma.Web.ActivityPub.ActivityPub
def build(data \\ %{}, opts \\ %{}) do
user = opts[:user] || UserBuilder.build
user = opts[:user] || Pleroma.Factory.insert(:user)
activity = %{
"id" => 1,
"actor" => user.ap_id,
@ -29,7 +29,7 @@ defmodule Pleroma.Builders.ActivityBuilder do
end
def public_and_non_public do
{:ok, user} = UserBuilder.insert
user = Pleroma.Factory.insert(:user)
public = build(%{"id" => 1}, %{user: user})
non_public = build(%{"id" => 2, "to" => []}, %{user: user})

View file

@ -3,6 +3,8 @@ defmodule Pleroma.UserTest do
alias Pleroma.User
use Pleroma.DataCase
import Pleroma.Factory
test "ap_id returns the activity pub id for the user" do
host =
Application.get_env(:pleroma, Pleroma.Web.Endpoint)
@ -25,21 +27,21 @@ defmodule Pleroma.UserTest do
end
test "follow takes a user and another user" do
{ :ok, user } = UserBuilder.insert
{ :ok, following } = UserBuilder.insert(%{nickname: "guy"})
user = insert(:user)
followed = insert(:user)
{:ok, user } = User.follow(user, following)
{:ok, user } = User.follow(user, followed)
user = Repo.get(User, user.id)
assert user.following == [User.ap_followers(following)]
assert user.following == [User.ap_followers(followed)]
end
test "unfollow takes a user and another user" do
{ :ok, following } = UserBuilder.insert(%{nickname: "guy"})
{ :ok, user } = UserBuilder.insert(%{following: [User.ap_followers(following)]})
followed = insert(:user)
user = insert(:user, %{following: [User.ap_followers(followed)]})
{:ok, user } = User.unfollow(user, following)
{:ok, user } = User.unfollow(user, followed)
user = Repo.get(User, user.id)
@ -47,8 +49,8 @@ defmodule Pleroma.UserTest do
end
test "test if a user is following another user" do
{ :ok, followed } = UserBuilder.insert(%{nickname: "guy"})
{ :ok, user } = UserBuilder.insert(%{following: [User.ap_followers(followed)]})
followed = insert(:user)
user = insert(:user, %{following: [User.ap_followers(followed)]})
assert User.following?(user, followed)
refute User.following?(followed, user)

File diff suppressed because one or more lines are too long

View file

@ -45,8 +45,11 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do
test "an activity" do
{:ok, user} = UserBuilder.insert
{:ok, mentioned_user } = UserBuilder.insert(%{nickname: "shp", ap_id: "shp"})
{:ok, follower} = UserBuilder.insert(%{following: [User.ap_followers(user)]})
# {:ok, mentioned_user } = UserBuilder.insert(%{nickname: "shp", ap_id: "shp"})
mentioned_user = insert(:user, %{nickname: "shp"})
# {:ok, follower} = UserBuilder.insert(%{following: [User.ap_followers(user)]})
follower = insert(:user, %{following: [User.ap_followers(user)]})
object = %Object{
data: %{
@ -62,7 +65,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do
}
}
content_html = "Some content mentioning <a href='shp'>@shp</shp>"
content_html = "Some content mentioning <a href='#{mentioned_user.ap_id}'>@shp</shp>"
content = HtmlSanitizeEx.strip_tags(content_html)
date = DateTime.from_naive!(~N[2016-05-24 13:26:08.003], "Etc/UTC") |> DateTime.to_iso8601

View file

@ -5,13 +5,23 @@ defmodule Pleroma.Web.TwitterAPI.Representers.UserRepresenterTest do
alias Pleroma.Web.TwitterAPI.Representers.UserRepresenter
alias Pleroma.Builders.UserBuilder
import Pleroma.Factory
setup do
{:ok, user} = UserBuilder.insert
user = insert(:user)
[user: user]
end
test "A user with an avatar object", %{user: user} do
image = "image"
user = %{ user | avatar: %{ "url" => [%{"href" => image}] }}
represented = UserRepresenter.to_map(user)
assert represented["profile_image_url"] == image
end
test "A user", %{user: user} do
image = "https://placehold.it/48x48"
represented = %{
"id" => user.id,
"name" => user.name,

View file

@ -94,10 +94,10 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
end
test "with credentials", %{conn: conn, user: current_user} do
{:ok, user} = UserBuilder.insert
user = insert(:user)
activities = ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
returned_activities = ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
{:ok, other_user} = UserBuilder.insert(%{ap_id: "glimmung", nickname: "nockame"})
other_user = insert(:user)
ActivityBuilder.insert_list(10, %{}, %{user: other_user})
since_id = List.last(activities).id
@ -110,7 +110,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
response = json_response(conn, 200)
assert length(response) == 10
assert response == Enum.map(returned_activities, fn (activity) -> ActivityRepresenter.to_map(activity, %{user: user, for: current_user}) end)
assert response == Enum.map(returned_activities, fn (activity) -> ActivityRepresenter.to_map(activity, %{user: User.get_cached_by_ap_id(activity.data["actor"]), for: current_user}) end)
end
end
@ -122,7 +122,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
end
test "with credentials", %{conn: conn, user: current_user} do
{:ok, followed } = UserBuilder.insert(%{name: "some guy"})
followed = insert(:user)
conn = conn
|> with_credentials(current_user.nickname, "test")
@ -142,7 +142,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
end
test "with credentials", %{conn: conn, user: current_user} do
{:ok, followed } = UserBuilder.insert(%{name: "some guy"})
followed = insert(:user)
{:ok, current_user} = User.follow(current_user, followed)
assert current_user.following == [User.ap_followers(followed)]
@ -157,6 +157,24 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
end
end
describe "POST /api/qvitter/update_avatar.json" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
conn = post conn, "/api/qvitter/update_avatar.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
conn = conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/qvitter/update_avatar.json", %{img: Pleroma.Web.ActivityPub.ActivityPubTest.data_uri})
current_user = Repo.get(User, current_user.id)
assert is_map(current_user.avatar)
assert json_response(conn, 200) == UserRepresenter.to_map(current_user, %{for: current_user})
end
end
describe "POST /api/favorites/create/:id" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do

View file

@ -78,7 +78,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
test "fetch public statuses" do
%{ public: activity, user: user } = ActivityBuilder.public_and_non_public
{:ok, follower } = UserBuilder.insert(%{name: "dude", ap_id: "idididid", following: [User.ap_followers(user)]})
follower = insert(:user, following: [User.ap_followers(user)])
statuses = TwitterAPI.fetch_public_statuses(follower)
@ -87,19 +88,18 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
end
test "fetch friends' statuses" do
ActivityBuilder.public_and_non_public
user = insert(:user, %{following: ["someguy/followers"]})
{:ok, activity} = ActivityBuilder.insert(%{"to" => ["someguy/followers"]})
{:ok, direct_activity} = ActivityBuilder.insert(%{"to" => ["some other id"]})
{:ok, user} = UserBuilder.insert(%{ap_id: "some other id", following: ["someguy/followers"]})
{:ok, direct_activity} = ActivityBuilder.insert(%{"to" => [user.ap_id]})
statuses = TwitterAPI.fetch_friend_statuses(user)
activity_user = Repo.get_by(User, ap_id: activity.data["actor"])
direct_activity_user = Repo.get_by(User, ap_id: direct_activity.data["actor"])
assert length(statuses) == 2
assert Enum.at(statuses, 0) == ActivityRepresenter.to_map(activity, %{user: activity_user})
assert Enum.at(statuses, 1) == ActivityRepresenter.to_map(direct_activity, %{user: activity_user, mentioned: [user]})
assert Enum.at(statuses, 1) == ActivityRepresenter.to_map(direct_activity, %{user: direct_activity_user, mentioned: [user]})
end
test "get a user by params" do
@ -145,8 +145,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
end
test "Follow another user" do
{ :ok, user } = UserBuilder.insert
{ :ok, following } = UserBuilder.insert(%{nickname: "guy"})
user = insert(:user)
following = insert(:user)
{:ok, user, following, activity } = TwitterAPI.follow(user, following.id)
@ -158,8 +158,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
end
test "Unfollow another user" do
{ :ok, following } = UserBuilder.insert(%{nickname: "guy"})
{ :ok, user } = UserBuilder.insert(%{following: [User.ap_followers(following)]})
following = insert(:user)
user = insert(:user, %{following: [User.ap_followers(following)]})
{:ok, user, _following } = TwitterAPI.unfollow(user, following.id)
@ -192,8 +192,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
test "it can parse mentions and return the relevant users" do
text = "@gsimg According to @archaeme , that is @daggsy."
{:ok, gsimg} = UserBuilder.insert(%{nickname: "gsimg"})
{:ok, archaeme} = UserBuilder.insert(%{nickname: "archaeme"})
gsimg = insert(:user, %{nickname: "gsimg"})
archaeme = insert(:user, %{nickname: "archaeme"})
expected_result = [
{"@gsimg", gsimg},
@ -206,11 +206,11 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
test "it adds user links to an existing text" do
text = "@gsimg According to @archaeme , that is @daggsy."
{:ok, _gsimg} = UserBuilder.insert(%{nickname: "gsimg", ap_id: "first_link" })
{:ok, _archaeme} = UserBuilder.insert(%{nickname: "archaeme", ap_id: "second_link"})
gsimg = insert(:user, %{nickname: "gsimg"})
archaeme = insert(:user, %{nickname: "archaeme"})
mentions = TwitterAPI.parse_mentions(text)
expected_text = "<a href='first_link'>@gsimg</a> According to <a href='second_link'>@archaeme</a> , that is @daggsy."
expected_text = "<a href='#{gsimg.ap_id}'>@gsimg</a> According to <a href='#{archaeme.ap_id}'>@archaeme</a> , that is @daggsy."
assert TwitterAPI.add_user_links(text, mentions) == expected_text
end