diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/activity.ex | 6 | ||||
-rw-r--r-- | lib/pleroma/formatter.ex | 6 | ||||
-rw-r--r-- | lib/pleroma/upload.ex | 4 | ||||
-rw-r--r-- | lib/pleroma/user.ex | 13 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/handlers/delete_handler.ex | 1 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/handlers/note_handler.ex | 5 | ||||
-rw-r--r-- | lib/pleroma/web/router.ex | 34 | ||||
-rw-r--r-- | lib/pleroma/web/salmon/salmon.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/controllers/util_controller.ex | 53 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/representers/activity_representer.ex | 19 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api.ex | 6 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api_controller.ex | 43 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/utils.ex | 11 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/views/user_view.ex | 7 | ||||
-rw-r--r-- | lib/pleroma/web/web_finger/web_finger.ex | 30 |
16 files changed, 206 insertions, 36 deletions
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 0b7188aba..f226c4c5f 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -15,11 +15,17 @@ defmodule Pleroma.Activity do where: fragment("(?)->>'id' = ?", activity.data, ^to_string(ap_id))) end + # Wrong name, only returns create activities def all_by_object_ap_id_q(ap_id) do from activity in Activity, where: fragment("(?)->'object'->>'id' = ?", activity.data, ^to_string(ap_id)) end + def all_non_create_by_object_ap_id_q(ap_id) do + from activity in Activity, + where: fragment("(?)->>'object' = ?", activity.data, ^to_string(ap_id)) + end + def all_by_object_ap_id(ap_id) do Repo.all(all_by_object_ap_id_q(ap_id)) end diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex index 179c33560..e95a314b4 100644 --- a/lib/pleroma/formatter.ex +++ b/lib/pleroma/formatter.ex @@ -1,7 +1,7 @@ defmodule Pleroma.Formatter do alias Pleroma.User - @link_regex ~r/https?:\/\/[\w\.\/?=\-#%&]+[\w]/ + @link_regex ~r/https?:\/\/[\w\.\/?=\-#%&]+[\w]/u def linkify(text) do Regex.replace(@link_regex, text, "<a href='\\0'>\\0</a>") end @@ -14,7 +14,7 @@ defmodule Pleroma.Formatter do def parse_mentions(text) do # Modified from https://www.w3.org/TR/html5/forms.html#valid-e-mail-address - regex = ~r/@[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@?[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/ + regex = ~r/@[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@?[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/u Regex.scan(regex, text) |> List.flatten @@ -91,7 +91,7 @@ defmodule Pleroma.Formatter do ] Enum.reduce(emoji_list, text, fn (emoji, text) -> - String.replace(text, ":#{String.replace(emoji, "_", "")}:", "<img height='32px' width='32px' alt='#{emoji}' title='#{emoji}' src='#{Pleroma.Web.Endpoint.static_url}/finmoji/128px/#{emoji}-128.png' />") + String.replace(text, ":#{String.replace(emoji, "_", "")}:", "<img height='32px' width='32px' alt='#{emoji}' title='#{String.replace(emoji, "_", "")}' src='#{Pleroma.Web.Endpoint.static_url}/finmoji/128px/#{emoji}-128.png' />") end) end end diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 9275eff87..2717377a3 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -13,7 +13,7 @@ defmodule Pleroma.Upload do "url" => [%{ "type" => "Link", "mediaType" => file.content_type, - "href" => url_for(Path.join(uuid, file.filename)) + "href" => url_for(Path.join(uuid, :cow_uri.urlencode(file.filename))) }], "name" => file.filename, "uuid" => uuid @@ -38,7 +38,7 @@ defmodule Pleroma.Upload do "url" => [%{ "type" => "Link", "mediaType" => content_type, - "href" => url_for(Path.join(uuid, filename)) + "href" => url_for(Path.join(uuid, :cow_uri.urlencode(filename))) }], "name" => filename, "uuid" => uuid diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index f28f0deb0..4f5fcab5b 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -80,6 +80,15 @@ defmodule Pleroma.User do end end + def update_changeset(struct, params \\ %{}) do + changeset = struct + |> cast(params, [:bio, :name]) + |> unique_constraint(:nickname) + |> validate_format(:nickname, ~r/^[a-zA-Z\d]+$/) + |> validate_length(:bio, min: 1, max: 1000) + |> validate_length(:name, min: 1, max: 100) + end + def register_changeset(struct, params \\ %{}) do changeset = struct |> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation]) @@ -89,8 +98,8 @@ defmodule Pleroma.User do |> unique_constraint(:nickname) |> validate_format(:nickname, ~r/^[a-zA-Z\d]+$/) |> validate_format(:email, @email_regex) - |> validate_length(:bio, max: 1000) - |> validate_length(:name, max: 100) + |> validate_length(:bio, min: 1, max: 1000) + |> validate_length(:name, min: 1, max: 100) if changeset.valid? do hashed = Pbkdf2.hashpwsalt(changeset.changes[:password]) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 69a2d8f4e..fbe259f50 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -119,7 +119,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do def fetch_activities(recipients, opts \\ %{}) do base_query = from activity in Activity, limit: 20, - order_by: [desc: :inserted_at] + order_by: [desc: :id] base_query |> restrict_recipients(recipients) diff --git a/lib/pleroma/web/ostatus/handlers/delete_handler.ex b/lib/pleroma/web/ostatus/handlers/delete_handler.ex index 2e5f9469b..f54a037a0 100644 --- a/lib/pleroma/web/ostatus/handlers/delete_handler.ex +++ b/lib/pleroma/web/ostatus/handlers/delete_handler.ex @@ -7,6 +7,7 @@ defmodule Pleroma.Web.OStatus.DeleteHandler do with id <- XML.string_from_xpath("//id", entry), object when not is_nil(object) <- Object.get_by_ap_id(id) do Repo.delete(object) + Repo.delete_all(Activity.all_non_create_by_object_ap_id_q(id)) Repo.delete_all(Activity.all_by_object_ap_id_q(id)) nil end diff --git a/lib/pleroma/web/ostatus/handlers/note_handler.ex b/lib/pleroma/web/ostatus/handlers/note_handler.ex index e67f67b37..f9aa463a0 100644 --- a/lib/pleroma/web/ostatus/handlers/note_handler.ex +++ b/lib/pleroma/web/ostatus/handlers/note_handler.ex @@ -55,8 +55,9 @@ defmodule Pleroma.Web.OStatus.NoteHandler do end def get_mentions(entry) do - get_people_mentions(entry) - ++ get_collection_mentions(entry) + (get_people_mentions(entry) + ++ get_collection_mentions(entry)) + |> Enum.filter(&(&1)) end def make_to_list(actor, mentions) do diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 34207a62f..2b22140ee 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -23,11 +23,31 @@ defmodule Pleroma.Web.Router do plug :accepts, ["xml", "xrd+xml"] end + pipeline :config do + plug :accepts, ["json", "xml"] + end + + pipeline :masto_config do + plug :accepts, ["json"] + end + + scope "/api/v1", Pleroma.Web do + pipe_through :masto_config + # TODO: Move this + get "/instance", TwitterAPI.UtilController, :masto_instance + end + scope "/api", Pleroma.Web do - pipe_through :api + pipe_through :config get "/help/test", TwitterAPI.UtilController, :help_test + post "/help/test", TwitterAPI.UtilController, :help_test get "/statusnet/config", TwitterAPI.UtilController, :config + get "/statusnet/version", TwitterAPI.UtilController, :version + end + + scope "/api", Pleroma.Web do + pipe_through :api get "/statuses/public_timeline", TwitterAPI.Controller, :public_timeline get "/statuses/public_and_external_timeline", TwitterAPI.Controller, :public_and_external_timeline @@ -49,6 +69,10 @@ defmodule Pleroma.Web.Router do get "/account/verify_credentials", TwitterAPI.Controller, :verify_credentials post "/account/verify_credentials", TwitterAPI.Controller, :verify_credentials + post "/account/update_profile", TwitterAPI.Controller, :update_profile + post "/account/update_profile_banner", TwitterAPI.Controller, :update_banner + post "/qvitter/update_background_image", TwitterAPI.Controller, :update_background + post "/account/most_recent_notification", TwitterAPI.Controller, :update_most_recent_notification get "/statuses/home_timeline", TwitterAPI.Controller, :friends_timeline @@ -107,5 +131,11 @@ end defmodule Fallback.RedirectController do use Pleroma.Web, :controller - def redirector(conn, _params), do: (if Mix.env != :test, do: send_file(conn, 200, "priv/static/index.html")) + def redirector(conn, _params) do + if Mix.env != :test do + conn + |> put_resp_content_type("text/html") + |> send_file(200, "priv/static/index.html") + end + end end diff --git a/lib/pleroma/web/salmon/salmon.ex b/lib/pleroma/web/salmon/salmon.ex index eadf0773b..4f6dfed65 100644 --- a/lib/pleroma/web/salmon/salmon.ex +++ b/lib/pleroma/web/salmon/salmon.ex @@ -60,7 +60,7 @@ defmodule Pleroma.Web.Salmon do [modulus, exponent] = magickey |> String.split(".") - |> Enum.map(&Base.url_decode64!/1) + |> Enum.map(fn (n) -> Base.url_decode64!(n, padding: false) end) |> Enum.map(make_integer) {:RSAPublicKey, modulus, exponent} diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index 6d6fd2202..285b4d105 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -7,12 +7,51 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end def config(conn, _params) do - json(conn, %{ - site: %{ - name: Web.base_url, - server: Web.base_url, - textlimit: -1 - } - }) + case get_format(conn) do + "xml" -> + response = """ + <config> + <site> + <name>#{Web.base_url}</name> + <site>#{Web.base_url}</site> + <textlimit>5000</textlimit> + </site> + </config> + """ + conn + |> put_resp_content_type("application/xml") + |> send_resp(200, response) + _ -> + json(conn, %{ + site: %{ + name: Web.base_url, + server: Web.base_url, + textlimit: 5000 + } + }) + end + end + + def version(conn, _params) do + case get_format(conn) do + "xml" -> + response = "<version>Pleroma Dev</version>" + conn + |> put_resp_content_type("application/xml") + |> send_resp(200, response) + _ -> json(conn, "Pleroma Dev") + end + end + + # TODO: Move this + def masto_instance(conn, _params) do + response = %{ + uri: Web.base_url, + title: Web.base_url, + description: "A Pleroma instance, an alternative fediverse server", + version: "dev" + } + + json(conn, response) 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 10aab919a..bc3de0e90 100644 --- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex +++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex @@ -29,7 +29,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do "created_at" => created_at, "retweeted_status" => retweeted_status, "statusnet_conversation_id" => conversation_id(announced_activity), - "external_url" => activity.data["id"] + "external_url" => activity.data["id"], + "activity_type" => "repeat" } end @@ -49,7 +50,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do "uri" => "tag:#{activity.data["id"]}:objectType=Favourite", "created_at" => created_at, "in_reply_to_status_id" => liked_activity.id, - "external_url" => activity.data["id"] + "external_url" => activity.data["id"], + "activity_type" => "like" } end @@ -68,7 +70,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do "is_post_verb" => false, "created_at" => created_at, "in_reply_to_status_id" => nil, - "external_url" => activity.data["id"] + "external_url" => activity.data["id"], + "activity_type" => "follow" } end @@ -88,7 +91,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do "is_post_verb" => false, "created_at" => created_at, "in_reply_to_status_id" => nil, - "external_url" => activity.data["id"] + "external_url" => activity.data["id"], + "activity_type" => "undo" } end @@ -108,6 +112,9 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do conversation_id = conversation_id(activity) + tags = activity.data["object"]["tag"] || [] + possibly_sensitive = Enum.member?(tags, "nsfw") + %{ "id" => activity.id, "user" => UserView.render("show.json", %{user: user, for: opts[:for]}), @@ -125,7 +132,9 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do "favorited" => to_boolean(favorited), "repeated" => to_boolean(repeated), "external_url" => object["external_url"], - "tags" => activity.data["object"]["tag"] || [] + "tags" => tags, + "activity_type" => "post", + "possibly_sensitive" => possibly_sensitive } end diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index dc66e27ad..de39834ca 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -270,7 +270,11 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do user = User.get_cached_by_ap_id(actor) # mentioned_users = Repo.all(from user in User, where: user.ap_id in ^activity.data["to"]) mentioned_users = Enum.map(activity.data["to"] || [], fn (ap_id) -> - User.get_cached_by_ap_id(ap_id) + if ap_id do + User.get_cached_by_ap_id(ap_id) + else + nil + end end) |> Enum.filter(&(&1)) diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 9b1c74a3f..3580e48d2 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -6,6 +6,8 @@ defmodule Pleroma.Web.TwitterAPI.Controller do alias Pleroma.Web.ActivityPub.ActivityPub alias Ecto.Changeset + require Logger + def verify_credentials(%{assigns: %{user: user}} = conn, _params) do render(conn, UserView, "show.json", %{user: user}) end @@ -188,6 +190,30 @@ defmodule Pleroma.Web.TwitterAPI.Controller do render(conn, UserView, "show.json", %{user: user, for: user}) end + def update_banner(%{assigns: %{user: user}} = conn, params) do + with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}), + new_info <- Map.put(user.info, "banner", object.data), + change <- User.info_changeset(user, %{info: new_info}), + {:ok, user} <- Repo.update(change) do + %{"url" => [ %{ "href" => href } | t ]} = object.data + response = %{ url: href } |> Poison.encode! + conn + |> json_reply(200, response) + end + end + + def update_background(%{assigns: %{user: user}} = conn, params) do + with {:ok, object} <- ActivityPub.upload(params), + new_info <- Map.put(user.info, "background", object.data), + change <- User.info_changeset(user, %{info: new_info}), + {:ok, user} <- Repo.update(change) do + %{"url" => [ %{ "href" => href } | t ]} = object.data + response = %{ url: href } |> Poison.encode! + conn + |> json_reply(200, response) + end + end + def external_profile(%{assigns: %{user: current_user}} = conn, %{"profileurl" => uri}) do with {:ok, user_map} <- TwitterAPI.get_external_profile(current_user, uri), response <- Poison.encode!(user_map) do @@ -226,6 +252,23 @@ defmodule Pleroma.Web.TwitterAPI.Controller do end end + def update_profile(%{assigns: %{user: user}} = conn, params) do + params = if bio = params["description"] do + Map.put(params, "bio", bio) + else + params + end + + with changeset <- User.update_changeset(user, params), + {:ok, user} <- Repo.update(changeset) do + render(conn, UserView, "user.json", %{user: user, for: user}) + else + error -> + Logger.debug("Can't update user: #{inspect(error)}") + bad_request_reply(conn, "Can't update user") + end + end + defp bad_request_reply(conn, error_message) do json = error_json(conn, error_message) json_reply(conn, 400, json) diff --git a/lib/pleroma/web/twitter_api/utils.ex b/lib/pleroma/web/twitter_api/utils.ex index 2c3507dfb..055588031 100644 --- a/lib/pleroma/web/twitter_api/utils.ex +++ b/lib/pleroma/web/twitter_api/utils.ex @@ -9,10 +9,19 @@ defmodule Pleroma.Web.TwitterAPI.Utils do end) end + defp shortname(name) do + if String.length(name) < 30 do + name + else + String.slice(name, 0..30) <> "…" + end + end + def add_attachments(text, attachments) do attachment_text = Enum.map(attachments, fn (%{"url" => [%{"href" => href} | _]}) -> - "<a href=\"#{URI.encode(href)}\" class='attachment'>#{Path.basename(href)}</a>" + name = URI.decode(Path.basename(href)) + "<a href=\"#{href}\" class='attachment'>#{shortname(name)}</a>" _ -> "" end) Enum.join([text | attachment_text], "<br>\n") diff --git a/lib/pleroma/web/twitter_api/views/user_view.ex b/lib/pleroma/web/twitter_api/views/user_view.ex index 24d2981fa..932c018a6 100644 --- a/lib/pleroma/web/twitter_api/views/user_view.ex +++ b/lib/pleroma/web/twitter_api/views/user_view.ex @@ -11,6 +11,9 @@ defmodule Pleroma.Web.TwitterAPI.UserView do render_many(users, Pleroma.Web.TwitterAPI.UserView, "user.json", for: user) end + defp image_url(%{"url" => [ %{ "href" => href } | t ]}), do: href + defp image_url(_), do: nil + def render("user.json", %{user: user = %User{}} = assigns) do image = User.avatar_url(user) following = if assigns[:for] do @@ -37,7 +40,9 @@ defmodule Pleroma.Web.TwitterAPI.UserView do "rights" => %{}, "screen_name" => user.nickname, "statuses_count" => user_info[:note_count], - "statusnet_profile_url" => user.ap_id + "statusnet_profile_url" => user.ap_id, + "cover_photo" => image_url(user.info["banner"]), + "background_image" => image_url(user.info["background"]) } end diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex index 7ae413c26..da38f662c 100644 --- a/lib/pleroma/web/web_finger/web_finger.ex +++ b/lib/pleroma/web/web_finger/web_finger.ex @@ -82,20 +82,34 @@ defmodule Pleroma.Web.WebFinger do {:ok, data} end - def finger(account, getter \\ &@httpoison.get/3) do + def get_template_from_xml(body) do + xpath = "//Link[@rel='lrdd' and @type='application/xrd+xml']/@template" + with doc when doc != :error <- XML.parse_document(body), + template when template != nil <- XML.string_from_xpath(xpath, doc) do + {:ok, template} + end + end + + def find_lrdd_template(domain) do + with {:ok, %{status_code: status_code, body: body}} <- @httpoison.get("http://#{domain}/.well-known/host-meta", [], follow_redirect: true) do + get_template_from_xml(body) + else + e -> {:error, "Can't find lrdd template: #{inspect(e)}"} + end + end + + def finger(account) do domain = with [_name, domain] <- String.split(account, "@") do domain else _e -> URI.parse(account).host end - address = webfinger_address(domain) - # try https first - response = with {:ok, result} <- getter.("https:" <> address, ["Accept": "application/xrd+xml"], [params: [resource: account]]) do - {:ok, result} - else _ -> - getter.("http:" <> address, ["Accept": "application/xrd+xml"], [params: [resource: account], follow_redirect: true]) - end + {:ok, template} = find_lrdd_template(domain) + + address = String.replace(template, "{uri}", URI.encode(account)) + + response = @httpoison.get(address, ["Accept": "application/xrd+xml"]) with {:ok, %{status_code: status_code, body: body}} when status_code in 200..299 <- response, doc when doc != :error<- XML.parse_document(body), |