Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85826480
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
22 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index d9ff7e530..b5b829ca0 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -1,215 +1,220 @@
defmodule Pleroma.Web.TwitterAPI.Controller do
use Pleroma.Web, :controller
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})
conn
|> json_reply(200, response)
end
def status_update(%{assigns: %{user: user}} = conn, %{"status" => status_text} = status_data) do
if status_text |> String.trim |> String.length != 0 do
media_ids = extract_media_ids(status_data)
{:ok, activity} = TwitterAPI.create_status(user, Map.put(status_data, "media_ids", media_ids ))
conn
|> json_reply(200, ActivityRepresenter.to_json(activity, %{user: user}))
else
empty_status_reply(conn)
end
end
def status_update(conn, _status_data) do
empty_status_reply(conn)
end
defp empty_status_reply(conn) do
bad_request_reply(conn, "Client must provide a 'status' parameter with a value.")
end
defp extract_media_ids(status_data) do
with media_ids when not is_nil(media_ids) <- status_data["media_ids"],
split_ids <- String.split(media_ids, ","),
clean_ids <- Enum.reject(split_ids, fn (id) -> String.length(id) == 0 end)
do
clean_ids
else _e -> []
end
end
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 user_timeline(%{assigns: %{user: user}} = conn, params) do
case TwitterAPI.get_user(user, params) do
{:ok, target_user} ->
params = Map.merge(params, %{"actor_id" => target_user.ap_id})
statuses = TwitterAPI.fetch_user_statuses(user, params)
conn
|> json_reply(200, statuses |> Poison.encode!)
{:error, msg} ->
bad_request_reply(conn, msg)
end
end
def mentions_timeline(%{assigns: %{user: user}} = conn, params) do
statuses = TwitterAPI.fetch_mentions(user, params)
{:ok, json} = Poison.encode(statuses)
conn
|> json_reply(200, json)
end
def follow(%{assigns: %{user: user}} = conn, params) do
case TwitterAPI.follow(user, params) do
{ :ok, user, followed, _activity } ->
response = followed |> UserRepresenter.to_json(%{for: user})
conn
|> json_reply(200, response)
{ :error, msg } -> forbidden_json_reply(conn, msg)
end
end
def unfollow(%{assigns: %{user: user}} = conn, params) do
case TwitterAPI.unfollow(user, params) do
{ :ok, user, unfollowed, } ->
response = unfollowed |> UserRepresenter.to_json(%{for: user})
conn
|> json_reply(200, response)
{ :error, msg } -> forbidden_json_reply(conn, msg)
end
end
def fetch_status(%{assigns: %{user: user}} = conn, %{ "id" => id }) do
response = TwitterAPI.fetch_status(user, id) |> Poison.encode!
conn
|> json_reply(200, response)
end
def fetch_conversation(%{assigns: %{user: user}} = conn, %{ "id" => id }) do
id = String.to_integer(id)
response = TwitterAPI.fetch_conversation(user, id) |> Poison.encode!
conn
|> json_reply(200, response)
end
def upload(conn, %{"media" => media}) do
response = TwitterAPI.upload(media)
conn
|> put_resp_content_type("application/atom+xml")
|> send_resp(200, response)
end
def help_test(conn, _params) do
conn |> json_reply(200, Poison.encode!("ok"))
end
def upload_json(conn, %{"media" => media}) do
response = TwitterAPI.upload(media, "json")
conn
|> json_reply(200, response)
end
def config(conn, _params) do
response = %{
site: %{
name: Pleroma.Web.base_url,
server: Pleroma.Web.base_url,
textlimit: -1
}
}
|> Poison.encode!
conn
|> json_reply(200, response)
end
def favorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do
activity = Repo.get(Activity, id)
{:ok, status} = TwitterAPI.favorite(user, activity)
response = Poison.encode!(status)
conn
|> json_reply(200, response)
end
def unfavorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do
activity = Repo.get(Activity, id)
{:ok, status} = TwitterAPI.unfavorite(user, activity)
response = Poison.encode!(status)
conn
|> json_reply(200, response)
end
def retweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do
activity = Repo.get(Activity, id)
- {:ok, status} = TwitterAPI.retweet(user, activity)
- response = Poison.encode!(status)
+ if activity.data["actor"] == user.ap_id do
+ bad_request_reply(conn, "You cannot repeat your own notice.")
+ else
+ {:ok, status} = TwitterAPI.retweet(user, activity)
+ response = Poison.encode!(status)
- conn
- |> json_reply(200, response)
+ conn
+
+ |> json_reply(200, response)
+ end
end
def register(conn, params) do
with {:ok, user} <- TwitterAPI.register_user(params) do
conn
|> json_reply(200, Poison.encode!(user))
else
{:error, errors} ->
conn
|> json_reply(400, Poison.encode!(errors))
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 = error_json(conn, error_message)
json_reply(conn, 400, json)
end
defp json_reply(conn, status, json) do
conn
|> put_resp_content_type("application/json")
|> send_resp(status, json)
end
defp forbidden_json_reply(conn, error_message) do
json = error_json(conn, error_message)
json_reply(conn, 403, json)
end
defp error_json(conn, error_message) do
%{"error" => error_message, "request" => conn.request_path} |> Poison.encode!
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 766268ce9..6c249be7d 100644
--- a/test/web/twitter_api/twitter_api_controller_test.exs
+++ b/test/web/twitter_api/twitter_api_controller_test.exs
@@ -1,395 +1,405 @@
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, Object}
alias Pleroma.Web.ActivityPub.ActivityPub
import Pleroma.Factory
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_with_creds = conn |> with_credentials(user.nickname, "test")
request_path = "/api/statuses/update.json"
error_response = %{"request" => request_path,
"error" => "Client must provide a 'status' parameter with a value."}
conn = conn_with_creds |> post(request_path)
assert json_response(conn, 400) == error_response
conn = conn_with_creds |> post(request_path, %{ status: "" })
assert json_response(conn, 400) == error_response
conn = conn_with_creds |> post(request_path, %{ status: " " })
assert json_response(conn, 400) == error_response
conn = conn_with_creds |> post(request_path, %{ 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/show/:id.json" do
test "returns one status", %{conn: conn} do
{:ok, user} = UserBuilder.insert
{:ok, activity} = ActivityBuilder.insert(%{}, %{user: user})
actor = Repo.get_by!(User, ap_id: activity.data["actor"])
conn = conn
|> get("/api/statuses/show/#{activity.id}.json")
response = json_response(conn, 200)
assert response == ActivityRepresenter.to_map(activity, %{user: actor})
end
end
describe "GET /statusnet/conversation/:id.json" do
test "returns the statuses in the conversation", %{conn: conn} do
{:ok, _user} = UserBuilder.insert
{:ok, _activity} = ActivityBuilder.insert(%{"statusnetConversationId" => 1, "context" => "2hu"})
{:ok, _activity_two} = ActivityBuilder.insert(%{"statusnetConversationId" => 1,"context" => "2hu"})
{:ok, _activity_three} = ActivityBuilder.insert(%{"context" => "3hu"})
conn = conn
|> get("/api/statusnet/conversation/1.json")
response = json_response(conn, 200)
assert length(response) == 2
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
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})
other_user = insert(:user)
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.get_cached_by_ap_id(activity.data["actor"]), for: current_user}) end)
end
end
describe "GET /statuses/mentions.json" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
conn = get conn, "/api/statuses/mentions.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
{:ok, activity} = ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: current_user})
conn = conn
|> with_credentials(current_user.nickname, "test")
|> get("/api/statuses/mentions.json")
response = json_response(conn, 200)
assert length(response) == 1
assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: current_user, mentioned: [current_user]})
end
end
describe "GET /statuses/user_timeline.json" do
setup [:valid_user]
test "without any params", %{conn: conn} do
conn = get(conn, "/api/statuses/user_timeline.json")
assert json_response(conn, 400) == %{"error" => "You need to specify screen_name or user_id", "request" => "/api/statuses/user_timeline.json"}
end
test "with user_id", %{conn: conn} do
user = insert(:user)
{:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
response = json_response(conn, 200)
assert length(response) == 1
assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
end
test "with screen_name", %{conn: conn} do
user = insert(:user)
{:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
response = json_response(conn, 200)
assert length(response) == 1
assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
end
test "with credentials", %{conn: conn, user: current_user} do
{:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
conn = conn
|> with_credentials(current_user.nickname, "test")
|> get("/api/statuses/user_timeline.json")
response = json_response(conn, 200)
assert length(response) == 1
assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: current_user})
end
test "with credentials with user_id", %{conn: conn, user: current_user} do
user = insert(:user)
{:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
conn = conn
|> with_credentials(current_user.nickname, "test")
|> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
response = json_response(conn, 200)
assert length(response) == 1
assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
end
test "with credentials screen_name", %{conn: conn, user: current_user} do
user = insert(:user)
{:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
conn = conn
|> with_credentials(current_user.nickname, "test")
|> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
response = json_response(conn, 200)
assert length(response) == 1
assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
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
followed = insert(:user)
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, %{for: current_user})
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
followed = insert(:user)
{: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, %{for: current_user})
end
end
describe "GET /help/test.json" do
test "returns \"ok\"", %{conn: conn} do
conn = get conn, "/api/help/test.json"
assert json_response(conn, 200) == "ok"
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
note_activity = insert(:note_activity)
conn = post conn, "/api/favorites/create/#{note_activity.id}.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
note_activity = insert(:note_activity)
conn = conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/favorites/create/#{note_activity.id}.json")
assert json_response(conn, 200)
end
end
describe "POST /api/favorites/destroy/:id" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
note_activity = insert(:note_activity)
conn = post conn, "/api/favorites/destroy/#{note_activity.id}.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
note_activity = insert(:note_activity)
object = Object.get_by_ap_id(note_activity.data["object"]["id"])
ActivityPub.like(current_user, object)
conn = conn
|> with_credentials(current_user.nickname, "test")
|> post("/api/favorites/destroy/#{note_activity.id}.json")
assert json_response(conn, 200)
end
end
describe "POST /api/statuses/retweet/:id" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
note_activity = insert(:note_activity)
conn = post conn, "/api/statuses/retweet/#{note_activity.id}.json"
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
note_activity = insert(:note_activity)
- conn = conn
- |> with_credentials(current_user.nickname, "test")
- |> post("/api/statuses/retweet/#{note_activity.id}.json")
+ request_path = "/api/statuses/retweet/#{note_activity.id}.json"
- assert json_response(conn, 200)
+ user = Repo.get_by(User, ap_id: note_activity.data["actor"])
+ response = conn
+ |> with_credentials(user.nickname, "test")
+ |> post(request_path)
+ assert json_response(response, 400) == %{"error" => "You cannot repeat your own notice.",
+ "request" => request_path}
+
+ response = conn
+ |> with_credentials(current_user.nickname, "test")
+ |> post(request_path)
+ activity = Repo.get(Activity, note_activity.id)
+ activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
+ assert json_response(response, 200) == ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
end
end
describe "POST /api/account/register" do
test "it creates a new user", %{conn: conn} do
data = %{
"nickname" => "lain",
"email" => "lain@wired.jp",
"fullname" => "lain iwakura",
"bio" => "close the world.",
"password" => "bear",
"confirm" => "bear"
}
conn = conn
|> post("/api/account/register", data)
user = json_response(conn, 200)
fetched_user = Repo.get_by(User, nickname: "lain")
assert user == UserRepresenter.to_map(fetched_user)
end
test "it returns errors on a problem", %{conn: conn} do
data = %{
"email" => "lain@wired.jp",
"fullname" => "lain iwakura",
"bio" => "close the world.",
"password" => "bear",
"confirm" => "bear"
}
conn = conn
|> post("/api/account/register", data)
errors = json_response(conn, 400)
assert is_binary(errors["error"])
end
end
defp valid_user(_context) do
user = insert(:user)
[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
setup do
Supervisor.terminate_child(Pleroma.Supervisor, ConCache)
Supervisor.restart_child(Pleroma.Supervisor, ConCache)
:ok
end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Oct 30, 7:34 AM (22 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1799797
Default Alt Text
(22 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline