Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add disconnectTelegramBot mutation #4496

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions lib/sanbase/accounts/accounts_event_emitter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ defmodule Sanbase.Accounts.EventEmitter do
|> notify()
end

def handle_event(
{:ok, user},
:disconnect_telegram_bot,
%{telegram_chat_id: telegram_chat_id} = args
) do
Map.merge(
%{
event_type: :disconnect_telegram_bot,
user_id: user.id,
telegram_chat_id: telegram_chat_id
},
args
)
|> notify()
end

def handle_event({:ok, user}, :update_email_candidate, %{email_candidate: _} = args) do
Map.merge(%{event_type: :update_email_candidate, user_id: user.id}, args)
|> notify()
Expand Down
27 changes: 26 additions & 1 deletion lib/sanbase/accounts/user_settings.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ defmodule Sanbase.Accounts.UserSettings do
higher plan. Both things might take some to fix/upgrade, so having the option to unblock yourself
until the issues are resolved is required.k
"""

def can_self_reset_api_rate_limits?(user) do
%{self_api_rate_limits_reset_at: last_self_reset_at} = settings_for(user)

Expand All @@ -56,6 +55,32 @@ defmodule Sanbase.Accounts.UserSettings do
end
end

def disconnect_telegram_bot(user) do
# First get the existing chat id so we can send it with the event
# so the user events subscriber can send a message to that chat id
# informing that the bot is disconnected.
user_settings =
%{settings: %{telegram_chat_id: telegram_chat_id}} =
user_settings_for(user, force: true)

user_settings
|> changeset(%{settings: %{telegram_chat_id: nil}})
|> Sanbase.Repo.update()
|> case do
{:ok, user_settings} ->
Sanbase.Accounts.EventEmitter.emit_event(
{:ok, user},
:disconnect_telegram_bot,
%{telegram_chat_id: telegram_chat_id}
)

{:ok, user_settings}

{:error, error} ->
{:error, error}
end
end

def update_self_reset_api_rate_limits_datetime(user, dt) do
user_settings_for(user, force: true)
|> changeset(%{user_id: user.id, settings: %{self_api_rate_limits_reset_at: dt}})
Expand Down
7 changes: 7 additions & 0 deletions lib/sanbase/event_bus/event_validation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ defmodule Sanbase.EventBus.EventValidation do
def valid?(%{event_type: :update_email_candidate, user_id: id, email_candidate: email}),
do: valid_integer_id?(id) and is_binary(email)

def valid?(%{
event_type: :disconnect_telegram_bot,
user_id: id,
telegram_chat_id: telegram_chat_id
}),
do: valid_integer_id?(id) and is_integer(telegram_chat_id)

def valid?(%{event_type: :register_user, user_id: id, login_origin: login_origin}),
do: valid_integer_id?(id) and (is_atom(login_origin) or is_binary(login_origin))

Expand Down
20 changes: 20 additions & 0 deletions lib/sanbase/event_bus/user_events_subscriber.ex
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,26 @@ defmodule Sanbase.EventBus.UserEventsSubscriber do
state
end

defp handle_event(
%{
data: %{
event_type: :disconnect_telegram_bot,
user_id: _,
telegram_chat_id: chat_id
}
},
event_shadow,
state
) do
Sanbase.Telegram.send_message_to_chat_id(
chat_id,
"You have successfully disconnected your Telegram bot from your Sanbase profile."
)

EventBus.mark_as_completed({__MODULE__, event_shadow})
state
end

defp handle_event(_event, event_shadow, state) do
# The unhandled events are marked as completed
EventBus.mark_as_completed({__MODULE__, event_shadow})
Expand Down
15 changes: 15 additions & 0 deletions lib/sanbase_web/graphql/resolvers/user/user_resolver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,21 @@ defmodule SanbaseWeb.Graphql.Resolvers.UserResolver do
end
end

def disconnect_telegram_bot(_root, _args, %{context: %{auth: %{current_user: user}}}) do
case UserSettings.disconnect_telegram_bot(user) do
{:ok, _user_settings} ->
# Refresh the data in the user
Sanbase.Accounts.get_user(user.id)

{:error, changeset} ->
{
:error,
message: "Cannot disconnect current user's telegram bot",
details: changeset_errors(changeset)
}
end
end

def change_name(_root, %{name: new_name}, %{context: %{auth: %{current_user: user}}}) do
case User.change_name(user, new_name) do
{:ok, user} ->
Expand Down
6 changes: 6 additions & 0 deletions lib/sanbase_web/graphql/schema/queries/user_queries.ex
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ defmodule SanbaseWeb.Graphql.Schema.UserQueries do
end

object :user_mutations do
field :disconnect_telegram_bot, :user do
middleware(JWTAuth)

resolve(&UserResolver.disconnect_telegram_bot/3)
end

field :change_username, :user do
arg(:username, non_null(:string))

Expand Down
48 changes: 48 additions & 0 deletions test/sanbase/telegram/telegram_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,36 @@ defmodule Sanbase.TelegramTest do
assert chat_id == @telegram_chat_id
end

test "disconnect telegram bot after it is connected", context do
get_telegram_deep_link(context)

%Telegram.UserToken{token: user_token} = Telegram.UserToken.by_user_id(context.user.id)

simulate_telegram_deep_link_follow(context, user_token)
%Settings{telegram_chat_id: chat_id} = UserSettings.settings_for(context.user, force: true)
assert chat_id == @telegram_chat_id

self_pid = self()

Sanbase.Mock.prepare_mock(Sanbase.Telegram, :send_message_to_chat_id, fn _chat_id, text ->
send(self_pid, {:telegram_to_self, text})
{:ok, text}
end)
|> Sanbase.Mock.run_with_mocks(fn ->
assert %{"settings" => %{"hasTelegramConnected" => false}} =
disconnect_telegram_bot(context)

%Settings{telegram_chat_id: chat_id} = UserSettings.settings_for(context.user, force: true)
assert chat_id == nil

assert_receive(
{:telegram_to_self,
"You have successfully disconnected your Telegram bot from your Sanbase profile."},
200
)
end)
end

test "revoke telegram deep link removes the token", context do
get_telegram_deep_link(context)

Expand Down Expand Up @@ -113,6 +143,24 @@ defmodule Sanbase.TelegramTest do
json_response(result, 200)["data"]["revokeTelegramDeepLink"]
end

defp disconnect_telegram_bot(context) do
mutation = """
mutation{
disconnectTelegramBot{
settings{
hasTelegramConnected
}
}
}
"""

result =
context.conn
|> post("/graphql", mutation_skeleton(mutation))

json_response(result, 200)["data"]["disconnectTelegramBot"]
end

defp simulate_telegram_deep_link_follow(context, user_token) do
response = %{
"message" => %{
Expand Down
Loading