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

Commit

Permalink
Merge 7d16db0 into 249d1f2
Browse files Browse the repository at this point in the history
  • Loading branch information
renatomassaro committed Sep 13, 2017
2 parents 249d1f2 + 7d16db0 commit 823d877
Show file tree
Hide file tree
Showing 165 changed files with 7,136 additions and 2,296 deletions.
1 change: 0 additions & 1 deletion lib/account/action/flow/account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ defmodule Helix.Account.Action.Flow.Account do
@spec setup_account(Account.id | Account.t) ::
{:ok, %{entity: Entity.t, server: Server.t}}
| :error
# TODO: improve documentation
@doc """
Setups the input account
"""
Expand Down
44 changes: 44 additions & 0 deletions lib/account/public/account.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
defmodule Helix.Account.Public.Account do

alias Helix.Entity.Model.Entity
alias Helix.Server.Public.Index, as: ServerIndex
alias Helix.Account.Public.Index, as: AccountIndex

@type bootstrap ::
%{
account: AccountIndex.index,
servers: ServerIndex.index
}

@doc """
Returns all data related to the player. Used by the client upon login (or sync
request).
The final result is a fractal-like format created by the indexes being used.
"""
@spec bootstrap(Entity.id) ::
bootstrap
def bootstrap(entity_id) do
%{
account: AccountIndex.index(),
servers: ServerIndex.index(entity_id)
}
end

@doc """
Renders the bootstrap result by calling each index renderer.
Similar in purpose to `ProcessViewable`.
"""
@spec render_bootstrap(bootstrap) ::
%{
account: AccountIndex.rendered_index,
servers: ServerIndex.rendered_index
}
def render_bootstrap(bootstrap) do
%{
account: AccountIndex.render_index(bootstrap.account),
servers: ServerIndex.render_index(bootstrap.servers),
}
end
end
18 changes: 18 additions & 0 deletions lib/account/public/index.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule Helix.Account.Public.Index do

@type index :: term

@type rendered_index :: term

@spec index() ::
index
def index do
%{}
end

@spec render_index(index) ::
rendered_index
def render_index(index) do
index
end
end
105 changes: 13 additions & 92 deletions lib/account/websocket/channel/account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,103 +5,24 @@ defmodule Helix.Account.Websocket.Channel.Account do

use Phoenix.Channel

alias Helix.Hardware.Query.Component, as: ComponentQuery
alias Helix.Hardware.Query.Motherboard, as: MotherboardQuery
alias Helix.Server.Query.Server, as: ServerQuery
alias Helix.Entity.Query.Database, as: DatabaseQuery
alias Helix.Entity.Query.Entity, as: EntityQuery
alias Helix.Websocket.Socket, as: Websocket

def join("account:" <> account_id, _message, socket) do
# TODO: Provide a cleaner way to check this
player_account_id = to_string(socket.assigns.account.account_id)
alias Helix.Account.Websocket.Channel.Account.Join, as: AccountJoin
alias Helix.Account.Websocket.Channel.Account.Requests.Bootstrap,
as: BootstrapRequest

if account_id == player_account_id do
{:ok, socket}
else
{:error, %{reason: "can't join another user's notification channel"}}
end
def join(topic, _params, socket) do
request = AccountJoin.new(topic)
Websocket.handle_join(request, socket, &assign/3)
end

def handle_in("database.index", _message, socket) do
database =
socket.assigns.account.account_id
|> EntityQuery.get_entity_id()
|> EntityQuery.fetch()
|> DatabaseQuery.get_database()

{:reply, {:ok, %{data: %{entries: database}}}, socket}
end

# TODO: Fetch server's IPs
def handle_in("server.index", _message, socket) do
servers =
socket.assigns.account
|> EntityQuery.get_entity_id()
|> EntityQuery.fetch()
|> EntityQuery.get_servers()
|> Enum.map(&ServerQuery.fetch/1)
|> Enum.map(fn
server = %{motherboard_id: motherboard} when not is_nil(motherboard) ->
motherboard =
server.motherboard_id
|> ComponentQuery.fetch()
|> MotherboardQuery.fetch()
|> MotherboardQuery.preload_components()

{server, motherboard}
server ->
{server, nil}
end)
|> Enum.map(&render_server/1)

{:reply, {:ok, %{data: %{servers: servers}}}, socket}
end

# TODO: Move this to a viewer
def render_server({server, nil}) do
%{
server_id: to_string(server.server_id),
server_type: server.server_type,
password: server.password,
hardware: nil,
ips: []
}
end
def render_server({server, motherboard}) do
%{
server_id: to_string(server.server_id),
server_type: server.server_type,
password: server.password,
hardware: %{
# FIXME: This is querying the db again for the components
resources: MotherboardQuery.resources(motherboard),
components: render_components(motherboard)
},
ips: []
}
def handle_in("bootstrap", _params, socket) do
request = BootstrapRequest.new()
Websocket.handle_request(request, socket)
end

defp render_components(%{slots: slots}) do
slots
|> Enum.map(fn slot = %{component: component = %{}} ->
internal_id = slot.slot_internal_id

data = %{
component_id: to_string(component.component_id),
component_type: component.component_type,
# TODO: Return data about component specialization
meta: %{}
}
intercept ["event"]

{internal_id, data}
end)
|> :maps.from_list()
end

def notify(account_id, notification) do
Helix.Endpoint.broadcast(
"account:" <> to_string(account_id),
"event",
notification)
end
def handle_out("event", event, socket),
do: Websocket.handle_event(event, socket, &push/3)
end
55 changes: 55 additions & 0 deletions lib/account/websocket/channel/account/join.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
defmodule Helix.Account.Websocket.Channel.Account.Join do
@moduledoc """
Joinable implementation for the Account channel.
There's only one way to subscribe to an account's channel, and only the owner
of the account (authenticated on the Socket) can join this channel.
Therefore, the requested account_id (specified on the Channel's topic) must
belong to the authenticated user on the socket.
"""

require Helix.Websocket.Join

Helix.Websocket.Join.register()

defimpl Helix.Websocket.Joinable do

alias Helix.Account.Model.Account

def check_params(request, _socket) do
account_id = get_id_from_topic(request.topic)

with {:ok, account_id} <- Account.ID.cast(account_id) do
params = %{
account_id: account_id
}

{:ok, %{request| params: params}}
else
_ ->
{:error, %{message: "bad_request"}}
end
end

@doc """
This is where we check the requested account is the same one currently
authenticated.
"""
def check_permissions(request, socket) do
account_id = socket.assigns.account.account_id

if account_id == request.params.account_id do
{:ok, request}
else
{:error, %{message: "access_denied"}}
end
end

def join(_request, socket, _assign),
do: {:ok, socket}

defp get_id_from_topic(topic),
do: List.last(String.split(topic, "account:"))
end
end
31 changes: 31 additions & 0 deletions lib/account/websocket/channel/account/requests/bootstrap.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Helix.Account.Websocket.Channel.Account.Requests.Bootstrap do

require Helix.Websocket.Request

Helix.Websocket.Request.register()

defimpl Helix.Websocket.Requestable do

alias Helix.Websocket.Utils, as: WebsocketUtils
alias Helix.Account.Public.Account, as: AccountPublic

def check_params(request, _socket),
do: {:ok, request}

def check_permissions(request, _socket),
do: {:ok, request}

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

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

{:ok, %{request| meta: meta}}
end

def reply(request, socket) do
data = AccountPublic.render_bootstrap(request.meta.bootstrap)
WebsocketUtils.reply_ok(data, socket)
end
end
end
4 changes: 2 additions & 2 deletions lib/cache/internal/builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ defmodule Helix.Cache.Internal.Builder do
NPC.ID.cast!(to_string(entity.entity_id))
|> NPCInternal.fetch()
|> NPCWebInternal.generate_content(network_id, ip)
_ ->
%{to: "do"}
:account ->
%{}
end
end

Expand Down
32 changes: 0 additions & 32 deletions lib/cache/model/cacheable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -140,35 +140,3 @@ defmodule Helix.Cache.Model.Cacheable.Utils do
end
end
end

###########################################
# IGNORE THE FOLLOWING LINES.
# Dialyzer is not particularly a fan of protocols, so it will emit a lot of
# "unknown functions" for non-implemented types on a protocol. This hack will
# implement any possible type to avoid those warnings (albeit it might increase
# the compilation time in a second)
###########################################

impls = [
Atom,
BitString,
Float,
Function,
Integer,
List,
Map,
PID,
Port,
Reference,
Tuple
]

for impl <- impls do
defimpl Helix.Cache.Model.Cacheable, for: impl do
def format_input(input),
do: raise "#{inspect input} is not a valid value for Cacheable"

def format_output(input),
do: raise "#{inspect input} is not a valid value for Cacheable"
end
end
Loading

0 comments on commit 823d877

Please sign in to comment.