Browse Source

Add idempotency_key to the chat_message entity.

2298-weird-follow-issue
eugenijm 3 years ago
parent
commit
8e41baff40
10 changed files with 50 additions and 6 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +4
    -1
      docs/API/chats.md
  3. +8
    -1
      lib/pleroma/application.ex
  4. +6
    -0
      lib/pleroma/web/activity_pub/side_effects.ex
  5. +2
    -1
      lib/pleroma/web/common_api.ex
  6. +9
    -1
      lib/pleroma/web/pleroma_api/controllers/chat_controller.ex
  7. +11
    -0
      lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex
  8. +2
    -0
      test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs
  9. +4
    -1
      test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs
  10. +3
    -1
      test/pleroma/web/streamer_test.exs

+ 1
- 0
CHANGELOG.md View File

@@ -38,6 +38,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Pleroma API: Pagination for remote/local packs and emoji.
- Admin API: (`GET /api/pleroma/admin/users`) added filters user by `unconfirmed` status
- Admin API: (`GET /api/pleroma/admin/users`) added filters user by `actor_type`
- Pleroma API: Add `idempotency_key` to the chat message entity that can be used for optimistic message sending.

</details>



+ 4
- 1
docs/API/chats.md View File

@@ -173,11 +173,14 @@ Returned data:
"created_at": "2020-04-21T15:06:45.000Z",
"emojis": [],
"id": "12",
"unread": false
"unread": false,
"idempotency_key": "75442486-0874-440c-9db1-a7006c25a31f"
}
]
```

- idempotency_key: The copy of the `idempotency-key` HTTP request header that can be used for optimistic message sending. Included only during the first few minutes after the message creation.

### Posting a chat message

Posting a chat message for given Chat id works like this:


+ 8
- 1
lib/pleroma/application.ex View File

@@ -168,7 +168,11 @@ defmodule Pleroma.Application do
build_cachex("web_resp", limit: 2500),
build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10),
build_cachex("failed_proxy_url", limit: 2500),
build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000)
build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000),
build_cachex("chat_message_id_idempotency_key",
expiration: chat_message_id_idempotency_key_expiration(),
limit: 500_000
)
]
end

@@ -178,6 +182,9 @@ defmodule Pleroma.Application do
defp idempotency_expiration,
do: expiration(default: :timer.seconds(6 * 60 * 60), interval: :timer.seconds(60))

defp chat_message_id_idempotency_key_expiration,
do: expiration(default: :timer.minutes(2), interval: :timer.seconds(60))

defp seconds_valid_interval,
do: :timer.seconds(Config.get!([Pleroma.Captcha, :seconds_valid]))



+ 6
- 0
lib/pleroma/web/activity_pub/side_effects.ex View File

@@ -312,6 +312,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
{:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
{:ok, cm_ref} = MessageReference.create(chat, object, user.ap_id != actor.ap_id)

Cachex.put(
:chat_message_id_idempotency_key_cache,
cm_ref.id,
meta[:idempotency_key]
)

{
["user", "user:pleroma_chat"],
{user, %{cm_ref | chat: chat, object: object}}


+ 2
- 1
lib/pleroma/web/common_api.ex View File

@@ -45,7 +45,8 @@ defmodule Pleroma.Web.CommonAPI do
{_, {:ok, %Activity{} = activity, _meta}} <-
{:common_pipeline,
Pipeline.common_pipeline(create_activity_data,
local: true
local: true,
idempotency_key: opts[:idempotency_key]
)} do
{:ok, activity}
else


+ 9
- 1
lib/pleroma/web/pleroma_api/controllers/chat_controller.ex View File

@@ -80,7 +80,8 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
%User{} = recipient <- User.get_cached_by_ap_id(chat.recipient),
{:ok, activity} <-
CommonAPI.post_chat_message(user, recipient, params[:content],
media_id: params[:media_id]
media_id: params[:media_id],
idempotency_key: idempotency_key(conn)
),
message <- Object.normalize(activity, false),
cm_ref <- MessageReference.for_chat_and_object(chat, message) do
@@ -169,4 +170,11 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|> render("show.json", chat: chat)
end
end

defp idempotency_key(conn) do
case get_req_header(conn, "idempotency-key") do
[key] -> key
_ -> nil
end
end
end

+ 11
- 0
lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex View File

@@ -5,6 +5,7 @@
defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
use Pleroma.Web, :view

alias Pleroma.Maps
alias Pleroma.User
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.StatusView
@@ -37,6 +38,7 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
Pleroma.Web.RichMedia.Helpers.fetch_data_for_object(object)
)
}
|> put_idempotency_key()
end

def render("index.json", opts) do
@@ -47,4 +49,13 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
Map.put(opts, :as, :chat_message_reference)
)
end

defp put_idempotency_key(data) do
with {:ok, idempotency_key} <- Cachex.get(:chat_message_id_idempotency_key_cache, data.id) do
data
|> Maps.put_if_present(:idempotency_key, idempotency_key)
else
_ -> data
end
end
end

+ 2
- 0
test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs View File

@@ -82,11 +82,13 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
result =
conn
|> put_req_header("content-type", "application/json")
|> put_req_header("idempotency-key", "123")
|> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{"content" => "Hallo!!"})
|> json_response_and_validate_schema(200)

assert result["content"] == "Hallo!!"
assert result["chat_id"] == chat.id |> to_string()
assert result["idempotency_key"] == "123"
end

test "it fails if there is no content", %{conn: conn, user: user} do


+ 4
- 1
test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs View File

@@ -25,7 +25,9 @@ defmodule Pleroma.Web.PleromaAPI.ChatMessageReferenceViewTest do
}

{:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
{:ok, activity} = CommonAPI.post_chat_message(user, recipient, "kippis :firefox:")

{:ok, activity} =
CommonAPI.post_chat_message(user, recipient, "kippis :firefox:", idempotency_key: "123")

chat = Chat.get(user.id, recipient.ap_id)

@@ -42,6 +44,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatMessageReferenceViewTest do
assert chat_message[:created_at]
assert chat_message[:unread] == false
assert match?([%{shortcode: "firefox"}], chat_message[:emojis])
assert chat_message[:idempotency_key] == "123"

clear_config([:rich_media, :enabled], true)



+ 3
- 1
test/pleroma/web/streamer_test.exs View File

@@ -255,7 +255,9 @@ defmodule Pleroma.Web.StreamerTest do
} do
other_user = insert(:user)

{:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno")
{:ok, create_activity} =
CommonAPI.post_chat_message(other_user, user, "hey cirno", idempotency_key: "123")

object = Object.normalize(create_activity, false)
chat = Chat.get(user.id, other_user.ap_id)
cm_ref = MessageReference.for_chat_and_object(chat, object)


Loading…
Cancel
Save