feat(chat): add auth logic for room memberships

This commit is contained in:
João Paulo Dubas 2024-11-17 21:16:52 +00:00
parent d3253bd900
commit 9755dc2b9e
Signed by: joao.dubas
SSH Key Fingerprint: SHA256:V1mixgOGRc/YMhGx/DNkOSmJxgA2vHNrDZEk3wt/kOA
3 changed files with 80 additions and 12 deletions

View File

@ -29,6 +29,12 @@ defmodule Slax.Chat do
Repo.insert!(%RoomMembership{room: room, user: user})
end
def joined?(%Room{} = room, %User{} = user) do
Repo.exists?(
from rm in RoomMembership, where: rm.room_id == ^room.id and rm.user_id == ^user.id
)
end
def change_room(room, attrs \\ %{}) do
Room.changeset(room, attrs)
end
@ -47,6 +53,13 @@ defmodule Slax.Chat do
Repo.all(query)
end
def list_joined_rooms(%User{} = user) do
user
|> Repo.preload(:rooms)
|> Map.fetch!(:rooms)
|> Enum.sort_by(& &1.name)
end
def list_messages_in_room(%Room{id: room_id}) do
query =
from(m in Message,

View File

@ -65,6 +65,7 @@ defmodule SlaxWeb.ChatRoomLive do
<h1 class="text-sm font-bold leading-none">
#<%= @room.name %>
<.link
:if={@joined?}
class="font-normal text-xs text-blue-600 hover:text-blue-700"
navigate={~p"/rooms/#{@room}/edit"}
>
@ -135,7 +136,7 @@ defmodule SlaxWeb.ChatRoomLive do
timezone={@timezone}
/>
</div>
<div class="h-12 bg-white px-4 pb-4">
<div :if={@joined?} class="h-12 bg-white px-4 pb-4">
<.form
id="new-message-form"
for={@new_message_form}
@ -158,13 +159,41 @@ defmodule SlaxWeb.ChatRoomLive do
</button>
</.form>
</div>
<div
:if={!@joined?}
class="flex justify-around mx-5 mb-5 p-6 bg-slate-100 border-slate-300 border rounded-lg"
>
<div class="max-w-3-xl text-center">
<div class="mb-4">
<h1 class="text-xl font-semibold"><%= @room.name %></h1>
<p :if={@room.topic} class="text-sm mt-1 text-gray-600"><%= @room.topic %></p>
</div>
<div class="flex items-center justify-around">
<buttom
phx-click="join-room"
class="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500"
>
Join Room
</buttom>
</div>
<div class="mt-4">
<.link
navigate={~p"/rooms"}
href="#"
class="text-sm text-slate-500 underline hover:text-slate-600"
>
Back to All Rooms
</.link>
</div>
</div>
</div>
</div>
"""
end
@impl Phoenix.LiveView
def mount(_params, _session, socket) do
rooms = Chat.list_rooms()
rooms = Chat.list_joined_rooms(socket.assigns.current_user)
users = Accounts.list_users()
timezone = get_connect_params(socket)["timezone"]
@ -206,7 +235,12 @@ defmodule SlaxWeb.ChatRoomLive do
{:noreply,
socket
|> assign(hide_topic?: false, page_title: "# #{room.name}", room: room)
|> assign(
hide_topic?: false,
joined?: Chat.joined?(room, socket.assigns.current_user),
page_title: "# #{room.name}",
room: room
)
|> stream(:messages, messages, reset: true)
|> assign_message_form(Chat.change_message(%Message{}))
|> push_event("scroll_messages_to_bottom", %{})}
@ -228,12 +262,16 @@ defmodule SlaxWeb.ChatRoomLive do
%{current_user: user, room: room} = socket.assigns
socket =
case Chat.create_message(room, user, message_params) do
{:ok, _message} ->
assign_message_form(socket, Chat.change_message(%Message{}))
if Chat.joined?(room, user) do
case Chat.create_message(room, user, message_params) do
{:ok, _message} ->
assign_message_form(socket, Chat.change_message(%Message{}))
{:error, changeset} ->
assign_message_form(socket, changeset)
{:error, changeset} ->
assign_message_form(socket, changeset)
end
else
socket
end
{:noreply, socket}
@ -246,6 +284,16 @@ defmodule SlaxWeb.ChatRoomLive do
{:noreply, socket}
end
@impl Phoenix.LiveView
def handle_event("join-room", _, socket) do
current_user = socket.assigns.current_user
room = socket.assigns.room
Chat.join_room!(room, current_user)
Chat.subscribe_to_room(room)
socket = assign(socket, joined?: true, rooms: Chat.list_joined_rooms(current_user))
{:noreply, socket}
end
@impl Phoenix.LiveView
def handle_info({:new_message, message}, socket) do
socket =

View File

@ -33,12 +33,19 @@ defmodule SlaxWeb.ChatRoomLive.Edit do
@impl Phoenix.LiveView
def mount(%{"id" => id}, _session, socket) do
room = Chat.get_room!(id)
changeset = Chat.change_room(room)
socket =
socket
|> assign(page_title: "Edit chat room", room: room)
|> assign_form(changeset)
if Chat.joined?(room, socket.assigns.current_user) do
changeset = Chat.change_room(room)
socket
|> assign(page_title: "Edit chat room", room: room)
|> assign_form(changeset)
else
socket
|> put_flash(:error, "Permission denied")
|> push_navigate(to: ~p"/")
end
{:ok, socket}
end