Skip to content

Commit

Permalink
feat: api routes for data (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
pichoemr authored Apr 14, 2022
1 parent fbfb822 commit 3f7d89b
Show file tree
Hide file tree
Showing 20 changed files with 513 additions and 177 deletions.
3 changes: 2 additions & 1 deletion apps/lenra/lib/lenra/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ defmodule Lenra.Application do
Application.fetch_env!(:lenra, :faas_url) => [size: 32, count: 8],
Application.fetch_env!(:lenra, :gitlab_api_url) => [size: 10, count: 3]
}},
AppChannelMonitor
AppChannelMonitor,
{Lenra.SessionAgent, %{}}
]

# See https://hexdocs.pm/elixir/Supervisor.html
Expand Down
38 changes: 10 additions & 28 deletions apps/lenra/lib/lenra/guardian/app_guardian.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,25 @@ defmodule Lenra.AppGuardian do

use Guardian, otp_app: :lenra

alias ApplicationRunner.{SessionManager, SessionManagers}
alias Lenra.{Environment, Repo, SessionAgent, User}

def subject_for_token(session_pid, _claims) do
{:ok, to_string(session_pid)}
end

def resource_from_claims(%{"sub" => session_id}) do
case SessionManager.fetch_assigns(session_id) do
{:ok, session_assigns} -> session_assigns
err -> err
end
end

def verify_claims(claims, _option) do
with {:ok, _id} <- SessionManagers.fetch_session_manager_pid(claims["sub"]) do
{:ok, claims}
def resource_from_claims(%{"user_id" => user_id, "env_id" => env_id}) do
with env <- Repo.get(Environment, env_id),
user <- Repo.get(User, user_id) do
{:ok, %{environment: env, user: user}}
end
end

def on_verify(claims, token, _options) do
# TODO see if we can pass id in option, from verify_claims
case SessionManager.fetch_assigns(claims["sub"]) do
{:ok, session_assigns} ->
case extract_token(session_assigns) == token do
true ->
{:ok, claims}

false ->
{:error, :invalid_token}
end

err ->
err
if SessionAgent.fetch_token(claims["sub"]) ==
token do
{:ok, claims}
else
{:error, :invalid_token}
end
end

defp extract_token(%{token: token}) do
token
end
end
36 changes: 35 additions & 1 deletion apps/lenra/lib/lenra/services/data_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,41 @@ defmodule Lenra.DataServices do
import Ecto.Query, only: [from: 2]

alias Lenra.Repo
alias ApplicationRunner.{Data, DataServices, Datastore, UserData}
alias ApplicationRunner.{AST.EctoParser, AST.Parser, Data, DataServices, Datastore, UserData}

def get(ds_name, id) do
select =
from(d in Data,
join: ds in Datastore,
on: d.datastore_id == ds.id,
where: d.id == ^id and ds.name == ^ds_name,
select: d
)

select
|> Repo.one()
end

def query(env_id, user_id, query) do
select =
from(d in Data,
join: ud in UserData,
on: ud.data_id == d.id,
join: ds in Datastore,
on: d.datastore_id == ds.id,
where: ud.user_id == ^user_id and ds.environment_id == ^env_id,
select: d.id
)

user_data_id =
select
|> Repo.one()

query
|> Parser.from_json()
|> EctoParser.to_ecto(env_id, user_data_id)
|> Repo.all()
end

def create(environment_id, params) do
environment_id
Expand Down
20 changes: 11 additions & 9 deletions apps/lenra/lib/lenra/services/datastore_services.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ defmodule Lenra.DatastoreServices do
end)
end

def update(datastore_id, params) do
datastore_id
|> DatastoreServices.update(params)
|> Repo.transaction()
end
def delete(ds_name, env_id) do
Datastore
|> Repo.get_by(environment_id: env_id, name: ds_name)
|> case do
nil ->
{:error, :datastore_not_found}

def delete(datastore_id) do
datastore_id
|> DatastoreServices.delete()
|> Repo.transaction()
datastore ->
datastore.id
|> DatastoreServices.delete()
|> Repo.transaction()
end
end
end
6 changes: 2 additions & 4 deletions apps/lenra/lib/lenra/services/openfaas_services.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Lenra.OpenfaasServices do
The service that manage calls to an Openfaas action with `run_action/3`
"""

alias Lenra.{DeploymentServices, Environment, LenraApplication, SessionStateServices}
alias Lenra.{DeploymentServices, Environment, LenraApplication, SessionAgent}
require Logger

defp get_http_context do
Expand Down Expand Up @@ -45,12 +45,10 @@ defmodule Lenra.OpenfaasServices do
event,
session_id
) do
{:ok, token} = SessionStateServices.create_and_assign_token(session_id)
token = SessionAgent.fetch_token(session_id)

finch_response = run_listener(application, environment, action, props, event, token)

SessionStateServices.revoke_token(session_id, token)

finch_response
|> case do
{:ok, %{"data" => data}} ->
Expand Down
22 changes: 22 additions & 0 deletions apps/lenra/lib/lenra/services/session_agent.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
defmodule Lenra.SessionAgent do
@moduledoc """
Lenra.SessionAgent manage token for session api request
"""
use Agent

def start_link(initial_value) do
Agent.start_link(fn -> initial_value end, name: {:global, __MODULE__})
end

def add_token(session_id, token) do
Agent.update({:global, __MODULE__}, &Map.merge(&1, %{session_id => token}))
end

def revoke_token(session_id) do
Agent.update({:global, __MODULE__}, &Map.delete(&1, session_id))
end

def fetch_token(session_id) do
Agent.get({:global, __MODULE__}, &Map.get(&1, session_id))
end
end
17 changes: 7 additions & 10 deletions apps/lenra/lib/lenra/services/session_state_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@ defmodule Lenra.SessionStateServices do
Lenra.Sessionstate handle all operation for session state.
"""

alias ApplicationRunner.SessionManager
alias Lenra.AppGuardian
alias Lenra.SessionAgent

def create_and_assign_token(session_id) do
with {:ok, session_assigns} <- SessionManager.fetch_assigns(session_id),
{:ok, token, _claims} <- AppGuardian.encode_and_sign(session_id, %{type: "session"}),
:ok <- SessionManager.set_assigns(session_id, Map.merge(session_assigns, %{token: token})) do
def create_and_assign_token(session_id, user_id, env_id) do
with {:ok, token, _claims} <-
AppGuardian.encode_and_sign(session_id, %{type: "session", user_id: user_id, env_id: env_id}),
:ok <- SessionAgent.add_token(session_id, token) do
{:ok, token}
end
end

def revoke_token(session_id, token) do
with {:ok, session_assigns} <- SessionManager.fetch_assigns(session_id),
{:ok, revoked_token} <- AppGuardian.revoke(token) do
SessionManager.set_assigns(session_id, Map.merge(session_assigns, %{token: revoked_token}))
end
def revoke_token(session_id) do
SessionAgent.revoke_token(session_id)
end
end
34 changes: 17 additions & 17 deletions apps/lenra/test/lenra/services/datastore_services_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,16 @@ defmodule Lenra.DatastoreServicesTest do

datastore = Repo.get(Datastore, inserted_datastore.id)

DatastoreServices.delete(datastore.id)
DatastoreServices.delete("users", env_id)

deleted_data = Repo.get(Datastore, inserted_datastore.id)

assert datastore.id == inserted_datastore.id
assert deleted_data == nil
end

test "should return error id invalid", %{env_id: _env_id} do
assert {:error, :datastore, :datastore_not_found, _changes_so_far} = DatastoreServices.delete(-1)
test "should return error id invalid", %{env_id: env_id} do
assert {:error, :datastore_not_found} = DatastoreServices.delete("null", env_id)
end

test "should also delete data", %{env_id: env_id, user_id: _user_id} do
Expand All @@ -112,7 +112,7 @@ defmodule Lenra.DatastoreServicesTest do

assert length(datas) == 3

DatastoreServices.delete(datastore.id)
DatastoreServices.delete("users", env_id)

deleted_datastore = Repo.get(Datastore, inserted_datastore.id)

Expand All @@ -130,22 +130,22 @@ defmodule Lenra.DatastoreServicesTest do
end
end

describe "DatastoreServices.update_1/1" do
test "should update datastore if params valid", %{env_id: env_id, user_id: _user_id} do
{:ok, %{inserted_datastore: inserted_datastore}} = DatastoreServices.create(env_id, %{"name" => "users"})
# describe "DatastoreServices.update_1/1" do
# test "should update datastore if params valid", %{env_id: env_id, user_id: _user_id} do
# {:ok, %{inserted_datastore: inserted_datastore}} = DatastoreServices.create(env_id, %{"name" => "users"})

datastore = Repo.get(Datastore, inserted_datastore.id)
# datastore = Repo.get(Datastore, inserted_datastore.id)

DatastoreServices.update(datastore.id, %{"name" => "test"})
# DatastoreServices.update(datastore.id, %{"name" => "test"})

updated_data = Repo.get(Datastore, inserted_datastore.id)
# updated_data = Repo.get(Datastore, inserted_datastore.id)

assert updated_data.name == "test"
end
# assert updated_data.name == "test"
# end

test "should return error id invalid", %{env_id: _env_id} do
assert {:error, :datastore, :datastore_not_found, _changes_so_far} =
DatastoreServices.update(-1, %{"name" => "test"})
end
end
# test "should return error id invalid", %{env_id: _env_id} do
# assert {:error, :datastore, :datastore_not_found, _changes_so_far} =
# DatastoreServices.update(-1, %{"name" => "test"})
# end
# end
end
5 changes: 4 additions & 1 deletion apps/lenra_web/lib/lenra_web/channels/app_channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ defmodule LenraWeb.AppChannel do
Environment,
LenraApplication,
LenraApplicationServices,
Repo
Repo,
SessionStateServices
}

alias LenraWeb.ErrorHelpers
Expand All @@ -32,6 +33,8 @@ defmodule LenraWeb.AppChannel do
:ok <- Bouncer.allow(LenraWeb.AppChannel.Policy, :join_app, user, application) do
%Environment{} = environment = select_env(application)

SessionStateServices.create_and_assign_token(session_id, user.id, environment.id)

Logger.debug("Environment selected is #{environment.name}")

# Assign the session_id to the socket for future usage
Expand Down
27 changes: 23 additions & 4 deletions apps/lenra_web/lib/lenra_web/controllers/data_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,47 @@ defmodule LenraWeb.DataController do
alias Lenra.AppGuardian.Plug
alias Lenra.DataServices

def get(conn, params) do
with data <- DataServices.get(params["datastore"], params["id"]) do
conn
|> assign_data(:data, data)
|> reply
end
end

def create(conn, params) do
with {:ok, inserted_data: data} <-
DataServices.create(Plug.current_resource(conn).environment.id, params) do
with session_assings <- Plug.current_resource(conn),
{:ok, %{inserted_data: data}} <-
DataServices.create(session_assings.environment.id, params) do
conn
|> assign_data(:inserted_data, data)
|> reply
end
end

def update(conn, params) do
with {:ok, updated_data: data} <- DataServices.update(params["data_id"], params) do
with {:ok, %{updated_data: data}} <- DataServices.update(params["id"], params) do
conn
|> assign_data(:updated_data, data)
|> reply
end
end

def delete(conn, params) do
with {:ok, deleted_data: data} <- DataServices.delete(params["data_id"]) do
with {:ok, %{deleted_data: data}} <- DataServices.delete(params["id"]) do
conn
|> assign_data(:deleted_data, data)
|> reply
end
end

def query(conn, params) do
with session_assings <- Plug.current_resource(conn),
requested <-
DataServices.query(session_assings.environment.id, session_assings.user.id, params["query"]) do
conn
|> assign_data(:requested, requested)
|> reply
end
end
end
16 changes: 6 additions & 10 deletions apps/lenra_web/lib/lenra_web/controllers/datastore_controller.ex
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
defmodule LenraWeb.DatastoreController do
use LenraWeb, :controller

alias Lenra.AppGuardian.Plug
alias Lenra.DatastoreServices

def create(conn, params) do
with {:ok, inserted_datastore: datastore} <- DatastoreServices.create(params["env_id"], params) do
with session_assings <- Plug.current_resource(conn),
{:ok, %{inserted_datastore: datastore}} <- DatastoreServices.create(session_assings.environment.id, params) do
conn
|> assign_data(:inserted_datastore, datastore)
|> reply
end
end

def update(conn, params) do
with {:ok, updated_datastore: datastore} <- DatastoreServices.update(params["datastore_id"], params) do
conn
|> assign_data(:updated_datastore, datastore)
|> reply
end
end

def delete(conn, params) do
with {:ok, deleted_datastore: datastore} <- DatastoreServices.delete(params["datastore_id"]) do
with session_assings <- Plug.current_resource(conn),
{:ok, %{deleted_datastore: datastore}} <-
DatastoreServices.delete(params["datastore"], session_assings.environment.id) do
conn
|> assign_data(:deleted_datastore, datastore)
|> reply
Expand Down
15 changes: 11 additions & 4 deletions apps/lenra_web/lib/lenra_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,17 @@ defmodule LenraWeb.Router do

scope "/app", LenraWeb do
pipe_through([:api, :ensure_auth_app])
# TODO define datastore/data/datareference route
resources("/data/:ds_name", DataController, only: [:create, :update, :delete])
resources("/datastore/:ds_name", DatastoreController, only: [:create, :update, :delete])
resources("/data_reference/:ds_name", DataReferenceController, only: [:create, :update, :delete])

post("/datastore", DatastoreController, :create)
delete("/datastore/:datastore", DatastoreController, :delete)

get("/datastore/:datastore/data/:id", DataController, :get)
post("/datastore/:datastore/data", DataController, :create)
delete("/datastore/:datastore/data/:id", DataController, :delete)
put("/datastore/:datastore/data/:id", DataController, :update)
# patch("/:ds_name/data/:id", DataController, :update)

post("/data/query", DataController, :query)
end

scope "/", LenraWeb do
Expand Down
Loading

0 comments on commit 3f7d89b

Please sign in to comment.