Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F113411
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
22 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index a10b43b78..67f590ee8 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1,56 +1,60 @@
defmodule Pleroma.User do
use Ecto.Schema
import Ecto.Changeset
alias Pleroma.{Repo, User}
schema "users" do
field :bio, :string
field :email, :string
field :name, :string
field :nickname, :string
field :password_hash, :string
field :following, { :array, :string }, default: []
field :ap_id, :string
timestamps()
end
def ap_id(%User{nickname: nickname}) do
host =
Application.get_env(:pleroma, Pleroma.Web.Endpoint)
|> Keyword.fetch!(:url)
|> Keyword.fetch!(:host)
"https://#{host}/users/#{nickname}"
end
def ap_followers(%User{} = user) do
"#{ap_id(user)}/followers"
end
def follow_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:following])
|> validate_required([:following])
end
def follow(%User{} = follower, %User{} = followed) do
ap_followers = User.ap_followers(followed)
following = [ap_followers | follower.following]
|> Enum.uniq
follower
|> follow_changeset(%{following: following})
|> Repo.update
end
def unfollow(%User{} = follower, %User{} = followed) do
ap_followers = User.ap_followers(followed)
following = follower.following
|> List.delete(ap_followers)
follower
|> follow_changeset(%{following: following})
|> Repo.update
end
+
+ def following?(%User{} = follower, %User{} = followed) do
+ Enum.member?(follower.following, User.ap_followers(followed))
+ end
end
diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex
index 171878162..a0f20c37c 100644
--- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex
+++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex
@@ -1,20 +1,20 @@
defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
use Pleroma.Web.TwitterAPI.Representers.BaseRepresenter
alias Pleroma.Web.TwitterAPI.Representers.UserRepresenter
alias Pleroma.Activity
- def to_map(%Activity{} = activity, %{user: user}) do
+ def to_map(%Activity{} = activity, %{user: user} = opts) do
content = get_in(activity.data, ["object", "content"])
published = get_in(activity.data, ["object", "published"])
%{
"id" => activity.id,
- "user" => UserRepresenter.to_map(user),
+ "user" => UserRepresenter.to_map(user, opts),
"attentions" => [],
"statusnet_html" => content,
"text" => content,
"is_local" => true,
"is_post_verb" => true,
"created_at" => published
}
end
end
diff --git a/lib/pleroma/web/twitter_api/representers/user_representer.ex b/lib/pleroma/web/twitter_api/representers/user_representer.ex
index 079e25021..8875d26ff 100644
--- a/lib/pleroma/web/twitter_api/representers/user_representer.ex
+++ b/lib/pleroma/web/twitter_api/representers/user_representer.ex
@@ -1,26 +1,35 @@
defmodule Pleroma.Web.TwitterAPI.Representers.UserRepresenter do
use Pleroma.Web.TwitterAPI.Representers.BaseRepresenter
+ alias Pleroma.User
+
+ def to_map(user, opts \\ %{}) do
- def to_map(user, options) do
image = "https://placehold.it/48x48"
+
+ following = if opts[:for] do
+ User.following?(opts[:for], user)
+ else
+ false
+ end
+
map = %{
"id" => user.id,
"name" => user.name,
"screen_name" => user.nickname,
"description" => user.bio,
- "following" => false,
+ "following" => following,
# Fake fields
"favourites_count" => 0,
"statuses_count" => 0,
"friends_count" => 0,
"followers_count" => 0,
"profile_image_url" => image,
"profile_image_url_https" => image,
"profile_image_url_profile_size" => image,
"profile_image_url_original" => image,
"rights" => %{}
}
map
end
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index 2ef679397..58fd51a62 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -1,60 +1,60 @@
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Repo
alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
def create_status(user = %User{}, data = %{}) do
date = DateTime.utc_now() |> DateTime.to_iso8601
activity = %{
"type" => "Create",
"to" => [
User.ap_followers(user),
"https://www.w3.org/ns/activitystreams#Public"
],
"actor" => User.ap_id(user),
"object" => %{
"type" => "Note",
"content" => data["status"],
"published" => date
},
"published" => date
}
ActivityPub.insert(activity)
end
def fetch_friend_statuses(user, opts \\ %{}) do
ActivityPub.fetch_activities(user.following, opts)
- |> activities_to_statuses
+ |> activities_to_statuses(%{for: user})
end
- def fetch_public_statuses(opts \\ %{}) do
+ def fetch_public_statuses(user, opts \\ %{}) do
ActivityPub.fetch_public_activities(opts)
- |> activities_to_statuses
+ |> activities_to_statuses(%{for: user})
end
def follow(%User{} = follower, followed_id) do
with %User{} = followed <- Repo.get(User, followed_id),
{ :ok, follower } <- User.follow(follower, followed)
do
{ :ok, follower, followed }
end
end
def unfollow(%User{} = follower, followed_id) do
with %User{} = followed <- Repo.get(User, followed_id),
{ :ok, follower } <- User.unfollow(follower, followed)
do
{ :ok, follower, followed }
end
end
- defp activities_to_statuses(activities) do
+ defp activities_to_statuses(activities, opts) do
Enum.map(activities, fn(activity) ->
actor = get_in(activity.data, ["actor"])
user = Repo.get_by!(User, ap_id: actor)
- ActivityRepresenter.to_map(activity, %{user: user})
+ ActivityRepresenter.to_map(activity, Map.merge(opts, %{user: user}))
end)
end
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index d574f1003..42485933b 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -1,59 +1,58 @@
defmodule Pleroma.Web.TwitterAPI.Controller do
use Pleroma.Web, :controller
alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.Web.TwitterAPI.Representers.{UserRepresenter, ActivityRepresenter}
def verify_credentials(%{assigns: %{user: user}} = conn, _params) do
- response = user |> UserRepresenter.to_json
+ response = user |> UserRepresenter.to_json(%{for: user})
conn
|> json_reply(200, response)
end
def status_update(%{assigns: %{user: user}} = conn, status_data) do
{:ok, activity} = TwitterAPI.create_status(user, status_data)
conn
|> json_reply(200, ActivityRepresenter.to_json(activity, %{user: user}))
end
- def public_timeline(conn, params) do
- statuses = TwitterAPI.fetch_public_statuses(params)
+ def public_timeline(%{assigns: %{user: user}} = conn, params) do
+ statuses = TwitterAPI.fetch_public_statuses(user, params)
{:ok, json} = Poison.encode(statuses)
conn
|> json_reply(200, json)
end
def friends_timeline(%{assigns: %{user: user}} = conn, params) do
statuses = TwitterAPI.fetch_friend_statuses(user, params)
{:ok, json} = Poison.encode(statuses)
conn
|> json_reply(200, json)
end
def follow(%{assigns: %{user: user}} = conn, %{ "user_id" => followed_id }) do
{ :ok, _user, follower } = TwitterAPI.follow(user, followed_id)
- response = follower |> UserRepresenter.to_json
+ response = follower |> UserRepresenter.to_json(%{for: user})
conn
|> json_reply(200, response)
end
def unfollow(%{assigns: %{user: user}} = conn, %{ "user_id" => followed_id }) do
- { :ok, _user, follower } = TwitterAPI.unfollow(user, followed_id)
+ { :ok, user, follower } = TwitterAPI.unfollow(user, followed_id)
- response = follower |> UserRepresenter.to_json
+ response = follower |> UserRepresenter.to_json(%{for: user})
conn
|> json_reply(200, response)
end
-
defp json_reply(conn, status, json) do
conn
|> put_resp_content_type("application/json")
|> send_resp(status, json)
end
end
diff --git a/test/user_test.exs b/test/user_test.exs
index e11bade93..f41063e9c 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -1,48 +1,56 @@
defmodule Pleroma.UserTest do
alias Pleroma.Builders.UserBuilder
alias Pleroma.User
use Pleroma.DataCase
test "ap_id returns the activity pub id for the user" do
host =
Application.get_env(:pleroma, Pleroma.Web.Endpoint)
|> Keyword.fetch!(:url)
|> Keyword.fetch!(:host)
user = UserBuilder.build
expected_ap_id = "https://#{host}/users/#{user.nickname}"
assert expected_ap_id == User.ap_id(user)
end
test "ap_followers returns the followers collection for the user" do
user = UserBuilder.build
expected_followers_collection = "#{User.ap_id(user)}/followers"
assert expected_followers_collection == User.ap_followers(user)
end
test "follow takes a user and another user" do
{ :ok, user } = UserBuilder.insert
{ :ok, following } = UserBuilder.insert(%{nickname: "guy"})
{:ok, user } = User.follow(user, following)
user = Repo.get(User, user.id)
assert user.following == [User.ap_followers(following)]
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)]})
{:ok, user } = User.unfollow(user, following)
user = Repo.get(User, user.id)
assert user.following == []
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)]})
+
+ assert User.following?(user, followed)
+ refute User.following?(followed, user)
+ end
end
diff --git a/test/web/twitter_api/representers/activity_representer_test.exs b/test/web/twitter_api/representers/activity_representer_test.exs
index ecfd5a73f..d40455c89 100644
--- a/test/web/twitter_api/representers/activity_representer_test.exs
+++ b/test/web/twitter_api/representers/activity_representer_test.exs
@@ -1,44 +1,46 @@
defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do
use Pleroma.DataCase
alias Pleroma.{User, Activity}
alias Pleroma.Web.TwitterAPI.Representers.{UserRepresenter, ActivityRepresenter}
alias Pleroma.Builders.UserBuilder
test "an activity" do
{:ok, user} = UserBuilder.insert
+ {:ok, follower} = UserBuilder.insert(%{following: [User.ap_followers(user)]})
+
content = "Some content"
date = DateTime.utc_now() |> DateTime.to_iso8601
activity = %Activity{
id: 1,
data: %{
"type" => "Create",
"to" => [
User.ap_followers(user),
"https://www.w3.org/ns/activitystreams#Public"
],
"actor" => User.ap_id(user),
"object" => %{
"published" => date,
"type" => "Note",
"content" => content
},
"published" => date
}
}
expected_status = %{
"id" => activity.id,
- "user" => UserRepresenter.to_map(user),
+ "user" => UserRepresenter.to_map(user, %{for: follower}),
"is_local" => true,
"attentions" => [],
"statusnet_html" => content,
"text" => content,
"is_post_verb" => true,
"created_at" => date
}
- assert ActivityRepresenter.to_map(activity, %{user: user}) == expected_status
+ assert ActivityRepresenter.to_map(activity, %{user: user, for: follower}) == expected_status
end
end
diff --git a/test/web/twitter_api/representers/user_representer_test.exs b/test/web/twitter_api/representers/user_representer_test.exs
index f08e392f9..76e3bd6e6 100644
--- a/test/web/twitter_api/representers/user_representer_test.exs
+++ b/test/web/twitter_api/representers/user_representer_test.exs
@@ -1,41 +1,59 @@
defmodule Pleroma.Web.TwitterAPI.Representers.UserRepresenterTest do
use Pleroma.DataCase
alias Pleroma.User
alias Pleroma.Web.TwitterAPI.Representers.UserRepresenter
+ alias Pleroma.Builders.UserBuilder
setup do
- user = %User{
- email: "test@example.org",
- name: "Test Name",
- nickname: "testname",
- password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
- bio: "A tester."
- }
- user = Repo.insert!(user)
+ {:ok, user} = UserBuilder.insert
[user: user]
end
test "A user", %{user: user} do
image = "https://placehold.it/48x48"
represented = %{
"id" => user.id,
"name" => user.name,
"screen_name" => user.nickname,
"description" => user.bio,
# Fake fields
"favourites_count" => 0,
"statuses_count" => 0,
"friends_count" => 0,
"followers_count" => 0,
"profile_image_url" => image,
"profile_image_url_https" => image,
"profile_image_url_profile_size" => image,
"profile_image_url_original" => image,
"following" => false,
"rights" => %{}
}
assert represented == UserRepresenter.to_map(user)
end
+
+ test "A user for a given other follower", %{user: user} do
+ {:ok, follower} = UserBuilder.insert(%{following: [User.ap_followers(user)]})
+ image = "https://placehold.it/48x48"
+ represented = %{
+ "id" => user.id,
+ "name" => user.name,
+ "screen_name" => user.nickname,
+ "description" => user.bio,
+ # Fake fields
+ "favourites_count" => 0,
+ "statuses_count" => 0,
+ "friends_count" => 0,
+ "followers_count" => 0,
+ "profile_image_url" => image,
+ "profile_image_url_https" => image,
+ "profile_image_url_profile_size" => image,
+ "profile_image_url_original" => image,
+ "following" => true,
+ "rights" => %{}
+ }
+
+ assert represented == UserRepresenter.to_map(user, %{for: follower})
+ end
end
diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs
index b0a0cdb54..851d5f4a7 100644
--- a/test/web/twitter_api/twitter_api_controller_test.exs
+++ b/test/web/twitter_api/twitter_api_controller_test.exs
@@ -1,134 +1,135 @@
defmodule Pleroma.Web.TwitterAPI.ControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.Web.TwitterAPI.Representers.{UserRepresenter, ActivityRepresenter}
alias Pleroma.Builders.{ActivityBuilder, UserBuilder}
alias Pleroma.{Repo, Activity, User}
describe "POST /api/account/verify_credentials" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
conn = post conn, "/api/account/verify_credentials.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: user} do
conn = conn
|> with_credentials(user.nickname, "test")
|> post("/api/account/verify_credentials.json")
assert json_response(conn, 200) == UserRepresenter.to_map(user)
end
end
describe "POST /statuses/update.json" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
conn = post conn, "/api/statuses/update.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: user} do
conn = conn
|> with_credentials(user.nickname, "test")
|> post("/api/statuses/update.json", %{ status: "Nice meme." })
assert json_response(conn, 200) == ActivityRepresenter.to_map(Repo.one(Activity), %{user: user})
end
end
describe "GET /statuses/public_timeline.json" do
test "returns statuses", %{conn: conn} do
{:ok, user} = UserBuilder.insert
activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
ActivityBuilder.insert_list(10, %{}, %{user: user})
since_id = List.last(activities).id
conn = conn
|> get("/api/statuses/public_timeline.json", %{since_id: since_id})
response = json_response(conn, 200)
assert length(response) == 10
end
end
describe "GET /statuses/friends_timeline.json" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
conn = get conn, "/api/statuses/friends_timeline.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
{:ok, user} = UserBuilder.insert
activities = ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
- ActivityBuilder.insert_list(10, %{"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"})
ActivityBuilder.insert_list(10, %{}, %{user: other_user})
since_id = List.last(activities).id
current_user = Ecto.Changeset.change(current_user, following: [User.ap_followers(user)]) |> Repo.update!
conn = conn
|> with_credentials(current_user.nickname, "test")
|> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
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)
end
end
describe "POST /friendships/create.json" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
conn = post conn, "/api/friendships/create.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
{:ok, followed } = UserBuilder.insert(%{name: "some guy"})
conn = conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/friendships/create.json", %{user_id: followed.id})
current_user = Repo.get(User, current_user.id)
assert current_user.following == [User.ap_followers(followed)]
assert json_response(conn, 200) == UserRepresenter.to_map(followed)
end
end
describe "POST /friendships/destroy.json" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
conn = post conn, "/api/friendships/destroy.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
{:ok, followed } = UserBuilder.insert(%{name: "some guy"})
{:ok, current_user} = User.follow(current_user, followed)
assert current_user.following == [User.ap_followers(followed)]
conn = conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/friendships/destroy.json", %{user_id: followed.id})
current_user = Repo.get(User, current_user.id)
assert current_user.following == []
assert json_response(conn, 200) == UserRepresenter.to_map(followed)
end
end
defp valid_user(_context) do
{ :ok, user } = UserBuilder.insert(%{nickname: "lambda", ap_id: "lambda"})
[user: user]
end
defp with_credentials(conn, username, password) do
header_content = "Basic " <> Base.encode64("#{username}:#{password}")
put_req_header(conn, "authorization", header_content)
end
end
diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs
index 3cb3196d9..f68a49f6a 100644
--- a/test/web/twitter_api/twitter_api_test.exs
+++ b/test/web/twitter_api/twitter_api_test.exs
@@ -1,65 +1,67 @@
defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
use Pleroma.DataCase
alias Pleroma.Builders.{UserBuilder, ActivityBuilder}
alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.{Activity, User}
alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
test "create a status" do
user = UserBuilder.build
input = %{
"status" => "Hello again."
}
{ :ok, activity = %Activity{} } = TwitterAPI.create_status(user, input)
assert get_in(activity.data, ["object", "content"]) == "Hello again."
assert get_in(activity.data, ["object", "type"]) == "Note"
assert get_in(activity.data, ["actor"]) == User.ap_id(user)
assert Enum.member?(get_in(activity.data, ["to"]), User.ap_followers(user))
assert Enum.member?(get_in(activity.data, ["to"]), "https://www.w3.org/ns/activitystreams#Public")
end
test "fetch public statuses" do
%{ public: activity, user: user } = ActivityBuilder.public_and_non_public
- statuses = TwitterAPI.fetch_public_statuses()
+ {:ok, follower } = UserBuilder.insert(%{name: "dude", ap_id: "idididid", following: [User.ap_followers(user)]})
+
+ statuses = TwitterAPI.fetch_public_statuses(follower)
assert length(statuses) == 1
- assert Enum.at(statuses, 0) == ActivityRepresenter.to_map(activity, %{user: user})
+ assert Enum.at(statuses, 0) == ActivityRepresenter.to_map(activity, %{user: user, for: follower})
end
test "fetch friends' statuses" do
ActivityBuilder.public_and_non_public
{:ok, activity} = ActivityBuilder.insert(%{"to" => ["someguy/followers"]})
{:ok, user} = UserBuilder.insert(%{ap_id: "some other id", following: ["someguy/followers"]})
statuses = TwitterAPI.fetch_friend_statuses(user)
activity_user = Repo.get_by(User, ap_id: activity.data["actor"])
assert length(statuses) == 1
assert Enum.at(statuses, 0) == ActivityRepresenter.to_map(activity, %{user: activity_user})
end
test "Follow another user" do
{ :ok, user } = UserBuilder.insert
{ :ok, following } = UserBuilder.insert(%{nickname: "guy"})
{:ok, user, following } = TwitterAPI.follow(user, following.id)
user = Repo.get(User, user.id)
assert user.following == [User.ap_followers(following)]
end
test "Unfollow another user" do
{ :ok, following } = UserBuilder.insert(%{nickname: "guy"})
{ :ok, user } = UserBuilder.insert(%{following: [User.ap_followers(following)]})
{:ok, user, _following } = TwitterAPI.unfollow(user, following.id)
user = Repo.get(User, user.id)
assert user.following == []
end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Nov 25, 5:30 AM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39625
Default Alt Text
(22 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline
Log In to Comment