Skip to content
This repository has been archived by the owner on Jun 11, 2023. It is now read-only.

Public FTP #301

Merged
merged 18 commits into from
Oct 16, 2017
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
8 changes: 4 additions & 4 deletions graphs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ mix xref graph \
--exclude lib/hell/mix/tasks/seeds.ex \
--exclude lib/hell/mix/tasks/test.ex \
--exclude lib/release.ex \
--exclude lib/event.ex \
--exclude lib/event_dispatcher.ex >> /dev/null
--exclude lib/event/event.ex \
--exclude lib/event/dispatcher.ex >> /dev/null
dot -Tpng xref_graph.dot -o graphs/overview.png

mix xref graph --format dot --source lib/event_dispatcher.ex >> /dev/null
mix xref graph --format dot --source lib/event/dispatcher.ex >> /dev/null
dot -Tpng xref_graph.dot -o graphs/event_consumers.png

mix xref graph --format dot --exclude lib/event_dispatcher.ex --sink lib/event.ex >> /dev/null
mix xref graph --format dot --exclude lib/event/dispatcher.ex --sink lib/event/event.ex >> /dev/null
dot -Tpng xref_graph.dot -o graphs/event_publishers.png

mix xref graph --format dot
Expand Down
31 changes: 10 additions & 21 deletions lib/account/websocket/channel/account.ex
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
defmodule Helix.Account.Websocket.Channel.Account do
import Helix.Websocket.Channel

channel Helix.Account.Websocket.Channel.Account do
@moduledoc """
Channel to notify an user of an action that affects them.
"""

use Phoenix.Channel

alias Helix.Websocket.Socket, as: Websocket

alias Helix.Account.Websocket.Channel.Account.Join, as: AccountJoin
alias Helix.Account.Websocket.Channel.Account.Requests.Bootstrap,
as: BootstrapRequest
alias Helix.Account.Websocket.Channel.Account.Requests.EmailReply,
as: EmailReplyRequest

def join(topic, _params, socket) do
request = AccountJoin.new(topic)
Websocket.handle_join(request, socket, &assign/3)
end
join _, AccountJoin

def handle_in("bootstrap", _params, socket) do
request = BootstrapRequest.new()
Websocket.handle_request(request, socket)
end
topic "bootstrap", BootstrapRequest

@doc """
Replies to a Storyline email.
Expand All @@ -37,13 +29,10 @@ defmodule Helix.Account.Websocket.Channel.Account do
- "reply_not_found" - The given reply ID is not valid, may be locked or not
exist within the current step email.
"""
def handle_in("email.reply", params, socket) do
request = EmailReplyRequest.new(params)
Websocket.handle_request(request, socket)
end
topic "email.reply", EmailReplyRequest

intercept ["event"]

def handle_out("event", event, socket),
do: Websocket.handle_event(event, socket, &push/3)
@doc """
Intercepts and handles outgoing events.
"""
event_handler "event"
end
38 changes: 17 additions & 21 deletions lib/account/websocket/channel/account/requests/bootstrap.ex
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
defmodule Helix.Account.Websocket.Channel.Account.Requests.Bootstrap do
import Helix.Websocket.Request

require Helix.Websocket.Request
request Helix.Account.Websocket.Channel.Account.Requests.Bootstrap do

Helix.Websocket.Request.register()
alias Helix.Account.Public.Account, as: AccountPublic

defimpl Helix.Websocket.Requestable do
def check_params(request, _socket),
do: reply_ok(request)

alias Helix.Websocket.Utils, as: WebsocketUtils
alias Helix.Account.Public.Account, as: AccountPublic
def check_permissions(request, _socket),
do: reply_ok(request)

def check_params(request, _socket),
do: {:ok, request}
def handle_request(request, socket) do
entity_id = socket.assigns.entity_id

def check_permissions(request, _socket),
do: {:ok, request}
meta = %{
bootstrap: AccountPublic.bootstrap(entity_id)
}

def handle_request(request, socket) do
entity_id = socket.assigns.entity_id

meta = %{bootstrap: AccountPublic.bootstrap(entity_id)}

{:ok, %{request| meta: meta}}
end
update_meta(request, meta, reply: true)
end

def reply(request, socket) do
data = AccountPublic.render_bootstrap(request.meta.bootstrap)
WebsocketUtils.reply_ok(data, socket)
end
render(request, _socket) do
data = AccountPublic.render_bootstrap(request.meta.bootstrap)
{:ok, data}
end
end
75 changes: 34 additions & 41 deletions lib/account/websocket/channel/account/requests/email_reply.ex
Original file line number Diff line number Diff line change
@@ -1,53 +1,46 @@
defmodule Helix.Account.Websocket.Channel.Account.Requests.EmailReply do
import Helix.Websocket.Request

request Helix.Account.Websocket.Channel.Account.Requests.EmailReply do
@moduledoc """
Implementation of the `EmailReply` request, which allows the player to send
an (storyline) email reply to the Contact (story character)
"""

require Helix.Websocket.Request

Helix.Websocket.Request.register()

defimpl Helix.Websocket.Requestable do

alias Helix.Websocket.Utils, as: WebsocketUtils
alias Helix.Story.Public.Story, as: StoryPublic
alias Helix.Story.Public.Story, as: StoryPublic

def check_params(request, _socket) do
with \
true <- is_binary(request.unsafe["reply_id"])
do
params = %{
reply_id: request.unsafe["reply_id"]
}
def check_params(request, _socket) do
with \
true <- is_binary(request.unsafe["reply_id"])
do
params = %{
reply_id: request.unsafe["reply_id"]
}

{:ok, %{request| params: params}}
else
_ ->
{:error, %{message: "bad_request"}}
end
update_params(request, params, reply: true)
else
_ ->
bad_request()
end
end

@doc """
Permissions whether that reply is valid within the player's current context
are checked at StoryPublic- and StoryAction-level
"""
def check_permissions(request, _socket),
do: {:ok, request}

def handle_request(request, socket) do
entity_id = socket.assigns.entity_id
reply_id = request.params.reply_id

case StoryPublic.send_reply(entity_id, reply_id) do
:ok ->
{:ok, request}
error ->
error
end
@doc """
Permissions whether that reply is valid within the player's current context
are checked at StoryPublic- and StoryAction-level
"""
def check_permissions(request, _socket),
do: reply_ok(request)

def handle_request(request, socket) do
entity_id = socket.assigns.entity_id
reply_id = request.params.reply_id

case StoryPublic.send_reply(entity_id, reply_id) do
:ok ->
reply_ok(request)
{:error, %{message: msg}} ->
reply_error(msg)
end

def reply(_request, socket),
do: WebsocketUtils.reply_ok(%{}, socket)
end

render_empty()
end
4 changes: 2 additions & 2 deletions lib/account/websocket/routes.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule Helix.Account.Websocket.Routes do

alias Helix.Websocket.Socket
alias Helix.Websocket
alias Helix.Account.Websocket.Controller.Account, as: AccountController

# Note that this is somewhat a hack to allow us to break our request-response
Expand All @@ -12,7 +12,7 @@ defmodule Helix.Account.Websocket.Routes do
def account_logout(socket) do
AccountController.logout(socket.assigns, %{})

socket_id = Socket.id(socket)
socket_id = Websocket.id(socket)
Helix.Endpoint.broadcast(socket_id, "disconnect", %{})

# Logout will blacklist the token and stop the socket, so, this only makes
Expand Down
2 changes: 1 addition & 1 deletion lib/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Helix.Endpoint do

require Helix.Appsignal

socket "/", Helix.Websocket.Socket
socket "/", Helix.Websocket

plug Corsica,
origins: Application.get_env(:helix, Helix.Endpoint)[:allowed_cors],
Expand Down
66 changes: 66 additions & 0 deletions lib/entity/henforcer/entity.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
defmodule Helix.Entity.Henforcer.Entity do

import Helix.Henforcer

alias Helix.Server.Model.Server
alias Helix.Server.Henforcer.Server, as: ServerHenforcer
alias Helix.Entity.Model.Entity
alias Helix.Entity.Query.Entity, as: EntityQuery

@type entity_exists_relay :: %{entity: Entity.t}
@type entity_exists_error ::
{false, {:entity, :not_found}, entity_exists_relay}

@spec entity_exists?(Entity.id) ::
{true, entity_exists_relay}
| entity_exists_error
@doc """
Henforces the given Entity exists.
"""
def entity_exists?(entity_id = %Entity.ID{}) do
with entity = %Entity{} <- EntityQuery.fetch(entity_id) do
reply_ok(relay(%{entity: entity}))
else
_ ->
reply_error({:entity, :not_found})
end
end

@type owns_server_relay :: %{entity: Entity.t, server: Server.t}
@type owns_server_relay_partial :: owns_server_relay
@type owns_server_error ::
{false, {:server, :not_belongs}, owns_server_relay_partial}
| entity_exists_error
| ServerHenforcer.server_exists_error

@spec owns_server?(Entity.idt, Server.idt) ::
{true, owns_server_relay}
| owns_server_error
@doc """
Henforces the Entity is the owner of the given server.
"""
def owns_server?(entity_id = %Entity.ID{}, server) do
henforce entity_exists?(entity_id) do
owns_server?(relay.entity, server)
end
end

def owns_server?(entity, server_id = %Server.ID{}) do
henforce(ServerHenforcer.server_exists?(server_id)) do
owns_server?(entity, relay.server)
end
end

def owns_server?(entity = %Entity{}, server = %Server{}) do
with \
owner = %Entity{} <- EntityQuery.fetch_by_server(server),
true <- owner == entity
do
reply_ok()
else
_ ->
reply_error({:server, :not_belongs})
end
|> wrap_relay(%{entity: entity, server: server})
end
end
Loading