diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 6772cf6b06..eed65cf954 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -157,6 +157,7 @@ defmodule Pleroma.User do field(:last_status_at, :naive_datetime) field(:birthday, :date) field(:show_birthday, :boolean, default: false) + field(:location, :string) embeds_one( :notification_settings, @@ -475,7 +476,8 @@ def remote_user_changeset(struct \\ %User{local: false}, params) do :accepts_chat_messages, :pinned_objects, :birthday, - :show_birthday + :show_birthday, + :location ] ) |> cast(params, [:name], empty_values: []) @@ -539,7 +541,8 @@ def update_changeset(struct, params \\ %{}) do :disclose_client, :accepts_email_list, :birthday, - :show_birthday + :show_birthday, + :location ] ) |> validate_min_age() diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index c54311f549..c021789b37 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1549,7 +1549,8 @@ defp object_to_user_data(data) do accepts_chat_messages: accepts_chat_messages, pinned_objects: pinned_objects, birthday: birthday, - show_birthday: show_birthday + show_birthday: show_birthday, + location: data["vcard:Address"] || "" } # nickname can be nil because of virtual actors diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index d20d4591a4..71e7744328 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -122,7 +122,8 @@ def render("user.json", %{user: user}) do "discoverable" => user.is_discoverable, "capabilities" => capabilities, "alsoKnownAs" => user.also_known_as, - "vcard:bday" => birthday + "vcard:bday" => birthday, + "vcard:Address" => user.location } |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user)) |> Map.merge(maybe_make_image(&User.banner_url/2, "image", user)) diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index 044207958f..b0680ee000 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -747,6 +747,11 @@ defp update_credentials_request do allOf: [BooleanLike], nullable: true, description: "User's birthday will be visible" + }, + location: %Schema{ + type: :string, + nullable: true, + description: "User location" } }, example: %{ diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex index 029c6f6cf1..cf4852d2ed 100644 --- a/lib/pleroma/web/api_spec/schemas/account.ex +++ b/lib/pleroma/web/api_spec/schemas/account.ex @@ -55,6 +55,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do "whether the user account is waiting on email confirmation to be activated" }, show_birthday: %Schema{type: :boolean, nullable: true}, + location: %Schema{type: :string, nullable: true}, hide_favorites: %Schema{type: :boolean}, hide_followers_count: %Schema{ type: :boolean, diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 93b2c43fff..09e182985e 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -222,6 +222,7 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p # Note: param name is indeed :discoverable (not an error) |> Maps.put_if_present(:is_discoverable, params[:discoverable]) |> Maps.put_if_present(:birthday, params[:birthday]) + |> Maps.put_if_present(:location, params[:location]) # What happens here: # diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 1f0577f739..96f9d5ad8a 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -297,7 +297,8 @@ defp do_render("show.json", %{user: user} = opts) do skip_thread_containment: user.skip_thread_containment, background_image: image_url(user.background) |> MediaProxy.url(), accepts_chat_messages: user.accepts_chat_messages, - favicon: favicon + favicon: favicon, + location: user.location } } |> maybe_put_role(user, opts[:for]) diff --git a/priv/repo/migrations/20220314220000_add_location_to_users.exs b/priv/repo/migrations/20220314220000_add_location_to_users.exs new file mode 100644 index 0000000000..7e548166ea --- /dev/null +++ b/priv/repo/migrations/20220314220000_add_location_to_users.exs @@ -0,0 +1,9 @@ +defmodule Pleroma.Repo.Migrations.AddLocationToUsers do + use Ecto.Migration + + def change do + alter table(:users) do + add_if_not_exists(:location, :string) + end + end +end diff --git a/test/fixtures/birthdays/misskey-user.json b/test/fixtures/birthdays/misskey-user.json index 4ffee3910d..9a5642f8cc 100644 --- a/test/fixtures/birthdays/misskey-user.json +++ b/test/fixtures/birthdays/misskey-user.json @@ -1 +1 @@ -{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","sensitive":"as:sensitive","Hashtag":"as:Hashtag","quoteUrl":"as:quoteUrl","toot":"http://joinmastodon.org/ns#","Emoji":"toot:Emoji","featured":"toot:featured","discoverable":"toot:discoverable","schema":"http://schema.org#","PropertyValue":"schema:PropertyValue","value":"schema:value","misskey":"https://misskey.io/ns#","_misskey_content":"misskey:_misskey_content","_misskey_quote":"misskey:_misskey_quote","_misskey_reaction":"misskey:_misskey_reaction","_misskey_votes":"misskey:_misskey_votes","_misskey_talk":"misskey:_misskey_talk","isCat":"misskey:isCat","vcard":"http://www.w3.org/2006/vcard/ns#"}],"type":"Person","id":"https://misskey.io/users/8dhi2ne167","inbox":"https://misskey.io/users/8dhi2ne167/inbox","outbox":"https://misskey.io/users/8dhi2ne167/outbox","followers":"https://misskey.io/users/8dhi2ne167/followers","following":"https://misskey.io/users/8dhi2ne167/following","sharedInbox":"https://misskey.io/inbox","endpoints":{"sharedInbox":"https://misskey.io/inbox"},"url":"https://misskey.io/@mkljczk","preferredUsername":"mkljczk","name":null,"summary":null,"icon":null,"image":null,"tag":[],"manuallyApprovesFollowers":false,"discoverable":true,"publicKey":{"id":"https://misskey.io/users/8dhi2ne167#main-key","type":"Key","owner":"https://misskey.io/users/8dhi2ne167","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7CI3Ol1M0TDdLL+E8Uhd\nJ8l/RTEtxl39MKxsqSCZr9itf/EBn4dGTifK9LN3XZD2fjmX4hdwaxndp2HYVDqn\ndc6O57u8dHxFv9wTwXQrLzEonOzbrBec6WB42ZpkFHi4XEyqg8iYGu5Yy7ttXJ21\nOfWqi+eytttcTErKuu4z8MX1L1IlmpfSmH1trMyDZLFMRqVJ0416/qI0K3l3cmIf\n8cuWbJ57UxVbYxp9242der/3vrNIU24rAouYQYe1atUgFPKil3w8dCY7magy36Wg\nOXC1hdRsFcsVW54/3cSQ9fc/+1HIg16/zlS+AWb4dVDhrAUJLYIBrkMPRnu/cDuI\ndvyL+KtZUxhDBoSO0JLrd1+GZGt0WD+mfutCugJS8IGlWQmGq8WRmM2vYfZgEYkq\nCv4392VSsWvg4iluKz0eX+8l7QKHseJwGBvk89Txlz6f7QkooBXYuuyHZS1ZLZBW\nfooK+RNAquDU+cVUu1gVt1V5yt3IxF1qvMRtlElNJKN5NUJT9/K2YcVX6UoMXhDd\noSOpARqPm9E2pdjI62pAOBbCplMSoBprhoCYm0iozf9QhNyUBGWDcTsFDDgqOwy4\nYjGQ5jsnCrkhSzRkTViWD+Pgw+Ar4fxcjySGUf0x7HkNfteDPSdLMD8J2vTJXfoB\nGAQQmGMZmFgONC62FrDphlsCAwEAAQ==\n-----END PUBLIC KEY-----\n"},"isCat":true,"vcard:bday":"2001-02-12"} \ No newline at end of file +{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","sensitive":"as:sensitive","Hashtag":"as:Hashtag","quoteUrl":"as:quoteUrl","toot":"http://joinmastodon.org/ns#","Emoji":"toot:Emoji","featured":"toot:featured","discoverable":"toot:discoverable","schema":"http://schema.org#","PropertyValue":"schema:PropertyValue","value":"schema:value","misskey":"https://misskey.io/ns#","_misskey_content":"misskey:_misskey_content","_misskey_quote":"misskey:_misskey_quote","_misskey_reaction":"misskey:_misskey_reaction","_misskey_votes":"misskey:_misskey_votes","_misskey_talk":"misskey:_misskey_talk","isCat":"misskey:isCat","vcard":"http://www.w3.org/2006/vcard/ns#"}],"type":"Person","id":"https://misskey.io/users/8dhi2ne167","inbox":"https://misskey.io/users/8dhi2ne167/inbox","outbox":"https://misskey.io/users/8dhi2ne167/outbox","followers":"https://misskey.io/users/8dhi2ne167/followers","following":"https://misskey.io/users/8dhi2ne167/following","sharedInbox":"https://misskey.io/inbox","endpoints":{"sharedInbox":"https://misskey.io/inbox"},"url":"https://misskey.io/@mkljczk","preferredUsername":"mkljczk","name":null,"summary":null,"icon":null,"image":null,"tag":[],"manuallyApprovesFollowers":false,"discoverable":true,"publicKey":{"id":"https://misskey.io/users/8dhi2ne167#main-key","type":"Key","owner":"https://misskey.io/users/8dhi2ne167","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7CI3Ol1M0TDdLL+E8Uhd\nJ8l/RTEtxl39MKxsqSCZr9itf/EBn4dGTifK9LN3XZD2fjmX4hdwaxndp2HYVDqn\ndc6O57u8dHxFv9wTwXQrLzEonOzbrBec6WB42ZpkFHi4XEyqg8iYGu5Yy7ttXJ21\nOfWqi+eytttcTErKuu4z8MX1L1IlmpfSmH1trMyDZLFMRqVJ0416/qI0K3l3cmIf\n8cuWbJ57UxVbYxp9242der/3vrNIU24rAouYQYe1atUgFPKil3w8dCY7magy36Wg\nOXC1hdRsFcsVW54/3cSQ9fc/+1HIg16/zlS+AWb4dVDhrAUJLYIBrkMPRnu/cDuI\ndvyL+KtZUxhDBoSO0JLrd1+GZGt0WD+mfutCugJS8IGlWQmGq8WRmM2vYfZgEYkq\nCv4392VSsWvg4iluKz0eX+8l7QKHseJwGBvk89Txlz6f7QkooBXYuuyHZS1ZLZBW\nfooK+RNAquDU+cVUu1gVt1V5yt3IxF1qvMRtlElNJKN5NUJT9/K2YcVX6UoMXhDd\noSOpARqPm9E2pdjI62pAOBbCplMSoBprhoCYm0iozf9QhNyUBGWDcTsFDDgqOwy4\nYjGQ5jsnCrkhSzRkTViWD+Pgw+Ar4fxcjySGUf0x7HkNfteDPSdLMD8J2vTJXfoB\nGAQQmGMZmFgONC62FrDphlsCAwEAAQ==\n-----END PUBLIC KEY-----\n"},"isCat":true,"vcard:bday":"2001-02-12","vcard:Address":"Poland"} \ No newline at end of file diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs index b0c8d4e0c4..38ac5cac8a 100644 --- a/test/pleroma/web/activity_pub/activity_pub_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -409,6 +409,26 @@ test "fetches user birthday information from misskey" do assert user.birthday == ~D[2001-02-12] end + + test "fetches user location information from misskey" do + user_id = "https://misskey.io/@mkljczk" + + Tesla.Mock.mock(fn + %{ + method: :get, + url: ^user_id + } -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/birthdays/misskey-user.json"), + headers: [{"content-type", "application/activity+json"}] + } + end) + + {:ok, user} = ActivityPub.make_user_from_ap_id(user_id) + + assert user.location == "Poland" + end end test "it fetches the appropriate tag-restricted posts" do diff --git a/test/pleroma/web/mastodon_api/update_credentials_test.exs b/test/pleroma/web/mastodon_api/update_credentials_test.exs index 9f0c6bf533..cf828dce9e 100644 --- a/test/pleroma/web/mastodon_api/update_credentials_test.exs +++ b/test/pleroma/web/mastodon_api/update_credentials_test.exs @@ -397,6 +397,16 @@ test "updates the user's show_birthday status", %{conn: conn} do assert user_data["source"]["pleroma"]["show_birthday"] == true end + test "updates location", %{conn: conn} do + res = + patch(conn, "/api/v1/accounts/update_credentials", %{ + "location" => "Pleroma, Fediverse" + }) + + assert user_data = json_response_and_validate_schema(res, 200) + assert user_data["pleroma"]["location"] == "Pleroma, Fediverse" + end + test "emojis in fields labels", %{conn: conn} do fields = [ %{"name" => ":firefox:", "value" => "is best 2hu"}, diff --git a/test/pleroma/web/mastodon_api/views/account_view_test.exs b/test/pleroma/web/mastodon_api/views/account_view_test.exs index 4c5dddec7e..363fdcf420 100644 --- a/test/pleroma/web/mastodon_api/views/account_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/account_view_test.exs @@ -92,7 +92,8 @@ test "Represent a user account" do hide_follows_count: false, relationship: %{}, skip_thread_containment: false, - accepts_chat_messages: nil + accepts_chat_messages: nil, + location: nil } } @@ -194,7 +195,8 @@ test "Represent a Service(bot) account" do hide_follows_count: false, relationship: %{}, skip_thread_containment: false, - accepts_chat_messages: nil + accepts_chat_messages: nil, + location: nil } }