Our client /project/messages and /user/messages routes will be in fact fetching conversations.
That means the current :index endpoint being implemented in #1278 is over-implemented and par of the behavior will have to be moved into the new endpoint.
That being said, all of the work being done there will be transferable to the solution for this issue.
The ConversationController needs potentially just one, but likely two endpoints.
This issue is for the :index endpoint.
Subtasks
[ ] Implement Policy.Conversation.scope, with tests
This is a custom query involving the message scope, in that, the user has access to all conversations belonging to messages they initiated, as well as all conversations belonging to them directly (meaning they were the target of a message sent by a project admin).
def scope(query, %User{id: id} = current_user) do
scoped_message_ids =
Message
|> Policy.Message.scope(current_user)
|> select([m], m.id)
|> Repo.all
query
|> where(user_id: ^id)
|> or_where([c], c.message_id in scoped_message_ids)
end
[ ] tests for Policy.Conversation.scope
[ ] Implement :index endpoint with tests
needs to scope correctly
needs to apply correct status filter
needs to apply project_id filter for the purposes of /:project/messages
no need to apply a user_id filter yet, the scope will be enough for /:user/messages
no need for coalesced id support - the client should fetch conversations directly, not through message.conversations. If there's a need later, we can plug it in
the messages/conversations index page should, by default query conversations initiated by users with any amount of parts, as well as convs. initiated by projects with at least one part (so we don't render unreplied to messages sent out to multiple users)
This is a weird route/endpoint which in a way is indexing two schemas at once.
We'd have to scope the conversations using the message scope, apply project_id filter to that scope, then fetch conversations from those messages, which fulfil the "status" rule and potentially any additional filter.
# in CodeCorpsWeb.ConversationController
def index(conn, params) do
Message
|> Policy.Conversation.scope(current_user)
|> Messages.list_conversations(params)
end
# in CodeCorps.Messages
def list_conversations(scope, %{} = params) do
scope
|> ConversationQuery.project_filter(params)
|> ConversationQuery.status_filter(params)
end
# in CodeCorps.Messages.ConversationQuery
def project_filter(query, %{"project_id" => project_id}) do
query
|> join(:left, [c], m in Message, c.messsage_id == m.id)
|> where([_c, _m], m.project_id == ^project_id)
end
def status_filter(query, %{}), do: query
# "status" => "active" is what the client is querying for by default,
# and is the default query parameter for the route, so it isn't rendered in the URL
def status_filter(query, %{"status" => "active"}) do
query
|> where([initiated_by: "user"])
|> or_where([initiated_by: "admin, part_count > 0])
end
def status_filter(query, %{}), do: query
Problem
Our client
/project/messages
and/user/messages
routes will be in fact fetching conversations.That means the current
:index
endpoint being implemented in #1278 is over-implemented and par of the behavior will have to be moved into the new endpoint.That being said, all of the work being done there will be transferable to the solution for this issue.
The
ConversationController
needs potentially just one, but likely two endpoints.This issue is for the
:index
endpoint.Subtasks
Policy.Conversation.scope
, with testsThis is a custom query involving the message scope, in that, the user has access to all conversations belonging to messages they initiated, as well as all conversations belonging to them directly (meaning they were the target of a message sent by a project admin).
Policy.Conversation.scope
:index
endpoint with testsproject_id
filter for the purposes of /:project/messagesuser_id
filter yet, the scope will be enough for/:user/messages
message.conversations
. If there's a need later, we can plug it inFrom https://github.com/code-corps/code-corps-api/issues/1234#issuecomment-350776870
This is a weird route/endpoint which in a way is indexing two schemas at once.
We'd have to scope the conversations using the message scope, apply
project_id
filter to that scope, then fetch conversations from those messages, which fulfil the "status" rule and potentially any additional filter.Messages.list_conversations/2
References