From 1cc13b1b8ab1f597e924d09c2ef3cedade571689 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Thu, 30 May 2024 17:56:33 +0200 Subject: [PATCH 01/15] feat: bulk operations --- .../controllers/arke_controller.ex | 65 ++++++++ .../controllers/auth_controller.ex | 153 +++++++++++------- lib/arke_server/router.ex | 1 + 3 files changed, 157 insertions(+), 62 deletions(-) diff --git a/lib/arke_server/controllers/arke_controller.ex b/lib/arke_server/controllers/arke_controller.ex index ee7cd9d..74fea2f 100644 --- a/lib/arke_server/controllers/arke_controller.ex +++ b/lib/arke_server/controllers/arke_controller.ex @@ -88,6 +88,71 @@ defmodule ArkeServer.ArkeController do end end + @doc """ + Bulk Creates units + """ + def create_bulk(%Plug.Conn{body_params: params} = conn, %{"arke_id" => id}) do + # all arkes struct and gen server are on :arke_system so it won't be changed to project + project = conn.assigns[:arke_project] + + arke = ArkeManager.get(String.to_atom(id), project) + + # TODO handle query parameter with plugs + load_links = Map.get(conn.query_params, "load_links", "false") == "true" + load_values = Map.get(conn.query_params, "load_values", "false") == "true" + load_files = Map.get(conn.query_params, "load_files", "false") == "true" + + case is_bulk_body_valid?(params) do + false -> + ResponseManager.send_resp(conn, 400, nil, "Invalid bulk body") + + true -> + QueryManager.create_bulk( + project, + arke, + params["data"], + runtime_data: %{conn: conn} + ) + |> case do + {:ok, valid, errors} -> + parsed_errors = + Enum.map(errors, fn {unit, msg} -> + %{ + data: + StructManager.encode(unit, + load_links: load_links, + load_values: load_values, + load_files: load_files, + type: :json + ), + error: msg + } + end) + + ResponseManager.send_resp(conn, 200, %{ + content: %{ + items: + StructManager.encode(valid, + load_links: load_links, + load_values: load_values, + load_files: load_files, + type: :json + ), + errors: parsed_errors + } + }) + + {:error, error} -> + ResponseManager.send_resp(conn, 400, nil, error) + end + end + end + + defp is_bulk_body_valid?(%{"data" => data} = _params) when is_list(data), + do: Enum.all?(data, fn item -> is_map(item) end) + + defp is_bulk_body_valid?(params), do: false + # delete @doc """ Delete a unit diff --git a/lib/arke_server/controllers/auth_controller.ex b/lib/arke_server/controllers/auth_controller.ex index e45d58d..09692f8 100644 --- a/lib/arke_server/controllers/auth_controller.ex +++ b/lib/arke_server/controllers/auth_controller.ex @@ -14,8 +14,8 @@ defmodule ArkeServer.AuthController do @moduledoc """ - Documentation for `ArkeServer.AuthController`. Used from the controller and via API not from CLI - """ + Documentation for `ArkeServer.AuthController`. Used from the controller and via API not from CLI + """ use ArkeServer, :controller @@ -86,8 +86,9 @@ defmodule ArkeServer.AuthController do when is_nil(otp) do case Otp.generate(project, username, "signup") do {:ok, otp} -> - mailer_module().signup(conn,params,mode: "otp", unit: otp,code: otp.data.code) + mailer_module().signup(conn, params, mode: "otp", unit: otp, code: otp.data.code) ResponseManager.send_resp(conn, 200, %{content: "OTP send successfully"}) + {:error, errors} -> ResponseManager.send_resp(conn, 401, nil, errors) end @@ -128,7 +129,8 @@ defmodule ArkeServer.AuthController do end end - defp handle_signup_mode(conn, _, _, _project, "otp_mail"), do: params_required(conn, ["username","password","otp"]) + defp handle_signup_mode(conn, _, _, _project, "otp_mail"), + do: params_required(conn, ["username", "password", "otp"]) defp handle_signup_mode(conn, _, _, _project, _), do: auth_not_active(conn) @@ -138,43 +140,50 @@ defmodule ArkeServer.AuthController do req_params, project ) do - {_, params} = Map.pop(req_params, "otp") - with {:ok, params, arke_system_user} <- check_user_on_signup(params, Map.get(params, "arke_system_user", nil)), - {:ok, _member} <- QueryManager.create(project, arke, data_as_klist(params)) - do - username = Map.get(arke_system_user, "username", nil) - password = Map.get(arke_system_user, "password", nil) - Auth.validate_credentials(username, password, project) - |> case do - {:ok, member, access_token, refresh_token} -> - content = - Map.merge(Arke.StructManager.encode(member, type: :json), %{ - access_token: access_token, - refresh_token: refresh_token - }) - mailer_module().signup(conn,params, member: member,response_body: content) - ResponseManager.send_resp(conn, 200, %{content: content}) - - {:error, error} -> - ResponseManager.send_resp(conn, 401, nil, error) - end - else - ({:error, errors} -> ResponseManager.send_resp(conn, 400, errors)) - end + with {:ok, params, arke_system_user} <- + check_user_on_signup(params, Map.get(params, "arke_system_user", nil)), + {:ok, _member} <- QueryManager.create(project, arke, data_as_klist(params)) do + username = Map.get(arke_system_user, "username", nil) + password = Map.get(arke_system_user, "password", nil) + + Auth.validate_credentials(username, password, project) + |> case do + {:ok, member, access_token, refresh_token} -> + content = + Map.merge(Arke.StructManager.encode(member, type: :json), %{ + access_token: access_token, + refresh_token: refresh_token + }) + + mailer_module().signup(conn, params, member: member, response_body: content) + ResponseManager.send_resp(conn, 200, %{content: content}) + + {:error, error} -> + ResponseManager.send_resp(conn, 401, nil, error) + end + else + {:error, errors} -> ResponseManager.send_resp(conn, 400, errors) end + end - defp check_user_on_signup(_params, arke_system_user) when is_nil(arke_system_user) or arke_system_user == "" or arke_system_user == %{}, do: {:error, "arke_system_user is required"} - defp check_user_on_signup(params, arke_system_user) when is_binary(arke_system_user) do + defp check_user_on_signup(_params, arke_system_user) + when is_nil(arke_system_user) or arke_system_user == "" or arke_system_user == %{}, + do: {:error, "arke_system_user is required"} + + defp check_user_on_signup(params, arke_system_user) when is_binary(arke_system_user) do case Jason.decode(arke_system_user) do {:ok, u} -> params = Map.merge(params, %{"arke_system_user" => u}) {:ok, params, u} - {:error, _} -> {:error, "arke_system_user is not a valid json"} - end + + {:error, _} -> + {:error, "arke_system_user is not a valid json"} end - defp check_user_on_signup(params, arke_system_user), do: {:ok, params, arke_system_user} + end + + defp check_user_on_signup(params, arke_system_user), do: {:ok, params, arke_system_user} @doc """ Signin a user @@ -187,22 +196,25 @@ defmodule ArkeServer.AuthController do project = get_project(conn.assigns[:arke_project]) case QueryManager.get_by(project: project, group: :arke_auth_member, auth_token: token) do - nil -> ResponseManager.send_resp(conn, 401, "Unauthorized") + nil -> + ResponseManager.send_resp(conn, 401, "Unauthorized") + member -> with {:ok, access_token, _claims} <- ArkeAuth.Guardian.encode_and_sign(member, %{}), - {:ok, refresh_token, _claims} <- ArkeAuth.Guardian.encode_and_sign(member, %{}, token_type: "refresh") - do + {:ok, refresh_token, _claims} <- + ArkeAuth.Guardian.encode_and_sign(member, %{}, token_type: "refresh") do content = Map.merge(Arke.StructManager.encode(member, type: :json), %{ access_token: access_token, refresh_token: refresh_token }) + update_member_access_time(member, auth_token: nil) ResponseManager.send_resp(conn, 200, %{content: content}) - else {:error, type} -> - ResponseManager.send_resp(conn, 401, "Unauthorized") + else + {:error, type} -> + ResponseManager.send_resp(conn, 401, "Unauthorized") end - end end @@ -210,6 +222,7 @@ defmodule ArkeServer.AuthController do def signin(conn, %{"username" => username, "password" => password} = params) do project = get_project(conn.assigns[:arke_project]) auth_mode = System.get_env("AUTH_MODE", "default") + Auth.validate_credentials(username, password, project) |> case do {:ok, member, _access_token, _refresh_token} -> @@ -225,6 +238,7 @@ defmodule ArkeServer.AuthController do ResponseManager.send_resp(conn, 401, messages) end end + def signin(conn, _params), do: ResponseManager.send_resp(conn, 404, nil) defp handle_signin_mode( @@ -235,7 +249,9 @@ defmodule ArkeServer.AuthController do ), do: handle_signin(conn, username, password, project) - defp handle_signin_mode(conn, _, _project, "default"), do: params_required(conn, ["username","password"]) + defp handle_signin_mode(conn, _, _project, "default"), + do: params_required(conn, ["username", "password"]) + defp handle_signin_mode( conn, %{"username" => username, "password" => password, "otp" => otp}, @@ -246,7 +262,6 @@ defmodule ArkeServer.AuthController do Auth.validate_credentials(username, password, project) |> case do {:ok, member, _access_token, _refresh_token} -> - data = %{ arke_id: member.arke_id, id: member.id, @@ -259,12 +274,12 @@ defmodule ArkeServer.AuthController do if username in reviewer do review_code = get_review_code() - mailer_module().signin(conn,member, mode: "otp", code: review_code) + mailer_module().signin(conn, member, mode: "otp", code: review_code) ResponseManager.send_resp(conn, 200, data, "OTP send successfully") else case Otp.generate(project, member.id, "signin") do {:ok, otp} -> - mailer_module().signin(conn,member,mode: "otp", unit: otp,code: otp.data.code) + mailer_module().signin(conn, member, mode: "otp", unit: otp, code: otp.data.code) ResponseManager.send_resp(conn, 200, data, "OTP send successfully") {:error, errors} -> @@ -277,7 +292,6 @@ defmodule ArkeServer.AuthController do end end - defp handle_signin_mode( conn, %{"username" => username, "password" => password, "otp" => otp}, @@ -288,6 +302,7 @@ defmodule ArkeServer.AuthController do |> case do {:ok, member, _access_token, _refresh_token} -> reviewer = get_review_email() + if username in reviewer do if otp == get_review_code() do handle_signin(conn, username, password, project) @@ -331,7 +346,8 @@ defmodule ArkeServer.AuthController do end end - defp handle_signin_mode(conn, _, _project, "otp_mail"), do: params_required(conn, ["username","password","otp"]) + defp handle_signin_mode(conn, _, _project, "otp_mail"), + do: params_required(conn, ["username", "password", "otp"]) defp handle_signin_mode(conn, _, _project, _), do: auth_not_active(conn) @@ -357,7 +373,12 @@ defmodule ArkeServer.AuthController do defp update_member_access_time(member, args \\ []) do datetime_now = NaiveDateTime.utc_now() update_data = [last_access_time: datetime_now] - update_data = if Map.get(member.data, :first_access_time, nil) == nil, do: Keyword.put(update_data, :first_access_time, datetime_now), else: update_data + + update_data = + if Map.get(member.data, :first_access_time, nil) == nil, + do: Keyword.put(update_data, :first_access_time, datetime_now), + else: update_data + update_data = Keyword.merge(update_data, args) QueryManager.update(member, update_data) end @@ -405,6 +426,7 @@ defmodule ArkeServer.AuthController do handle_change_password_mode(conn, params, member, auth_mode) end end + def change_password(conn, _), do: ResponseManager.send_resp(conn, 400, nil) defp handle_change_password_mode( @@ -415,7 +437,8 @@ defmodule ArkeServer.AuthController do ), do: handle_change_password(conn, member, old_pwd, new_pwd) - defp handle_change_password_mode(conn, _, _, _mode), do: params_required(conn, ["old_password","password"]) + defp handle_change_password_mode(conn, _, _, _mode), + do: params_required(conn, ["old_password", "password"]) defp handle_change_password_mode(conn, _, _, _), do: auth_not_active(conn) @@ -435,7 +458,6 @@ defmodule ArkeServer.AuthController do end end - @doc """ Reset user password """ @@ -446,20 +468,21 @@ defmodule ArkeServer.AuthController do case QueryManager.get_by(project: project, group_id: :arke_auth_member, email: email) do nil -> - {:error,msg} = Error.create(:auth, "member not found with given email") + {:error, msg} = Error.create(:auth, "member not found with given email") ResponseManager.send_resp(conn, 404, msg) member -> case member.arke_id do :super_admin -> handle_recover_password(conn, member, params) + _ -> handle_recover_password_mode(conn, params, member, auth_mode) end end end - def recover_password(conn, _), do: ResponseManager.send_resp(conn, 400, nil) + def recover_password(conn, _), do: ResponseManager.send_resp(conn, 400, nil) defp handle_recover_password_mode( conn, @@ -470,6 +493,7 @@ defmodule ArkeServer.AuthController do do: handle_recover_password(conn, email, "default") defp handle_recover_password_mode(conn, _, _, "default"), do: params_required(conn, ["email"]) + defp handle_recover_password_mode( conn, %{"email" => _email, "otp" => otp}, @@ -477,10 +501,9 @@ defmodule ArkeServer.AuthController do "otp_mail" ) when is_nil(otp) do - case Otp.generate(project, member.id, "reset_password") do {:ok, otp} -> - mailer_module().reset_password(conn,member,mode: "otp",unit: otp,code: otp.data.code) + mailer_module().reset_password(conn, member, mode: "otp", unit: otp, code: otp.data.code) ResponseManager.send_resp(conn, 200, %{content: "OTP send successfully"}) @@ -489,16 +512,17 @@ defmodule ArkeServer.AuthController do end end - defp handle_recover_password_mode(conn, _, _, "otp_mail"), do: params_required(conn, ["email","otp"]) - defp handle_recover_password_mode(conn, _, _, _), do: auth_not_active(conn) - + defp handle_recover_password_mode(conn, _, _, "otp_mail"), + do: params_required(conn, ["email", "otp"]) + defp handle_recover_password_mode(conn, _, _, _), do: auth_not_active(conn) defp handle_recover_password(conn, email, "default") do default_msg = "An email has been sent to the given email" + case QueryManager.get_by(email: email, arke_id: :user, project: :arke_system) do nil -> - ResponseManager.send_resp(conn, 200,default_msg ) + ResponseManager.send_resp(conn, 200, default_msg) user -> old_token_list = @@ -518,13 +542,18 @@ defmodule ArkeServer.AuthController do {:ok, unit} -> url_token = unit.data.token endpoint = "#{System.get_env("RESET_PASSWORD_ENDPOINT", "")}/#{url_token}" - mailer_module().reset_password(conn,user,mode: "email", unit: unit, endpoint: endpoint) + + mailer_module().reset_password(conn, user, + mode: "email", + unit: unit, + endpoint: endpoint + ) + ResponseManager.send_resp(conn, 200, default_msg) end end end - def reset_password(conn, params) do project = get_project(conn.assigns[:arke_project]) auth_mode = System.get_env("AUTH_MODE", "default") @@ -634,13 +663,13 @@ defmodule ArkeServer.AuthController do defp check_token_expiration(_token), do: Error.create(:auth, "invalid token") defp auth_not_active(conn) do - {:error,msg} = Error.create(:auth, "auth method not active") + {:error, msg} = Error.create(:auth, "auth method not active") ResponseManager.send_resp(conn, 400, msg) end - defp params_required(conn,param) do - param_msg = Enum.map(param,fn p -> "#{String.downcase(p)}" end) |> Enum.join(",") - {:error,msg} = Error.create(:auth, "#{param_msg} required") - ResponseManager.send_resp(conn, 400, msg) + defp params_required(conn, param) do + param_msg = Enum.map(param, fn p -> "#{String.downcase(p)}" end) |> Enum.join(",") + {:error, msg} = Error.create(:auth, "#{param_msg} required") + ResponseManager.send_resp(conn, 400, msg) end end diff --git a/lib/arke_server/router.ex b/lib/arke_server/router.ex index 62d9867..5101df1 100644 --- a/lib/arke_server/router.ex +++ b/lib/arke_server/router.ex @@ -162,6 +162,7 @@ defmodule ArkeServer.Router do # -------- POST -------- post("/:arke_id/unit", ArkeController, :create) + post("/:arke_id/bulk/unit", ArkeController, :create_bulk) post("/:arke_id/parameter/:arke_parameter_id", TopologyController, :add_parameter) From 0a9caef2c8d0418834b77e9cd92bfe80f5b3a4f5 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Fri, 31 May 2024 17:48:23 +0200 Subject: [PATCH 02/15] feat: handle bulk update --- .../controllers/unit_controller.ex | 67 +++++++++++++++++-- lib/arke_server/router.ex | 1 + 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/lib/arke_server/controllers/unit_controller.ex b/lib/arke_server/controllers/unit_controller.ex index 09b9e44..27dc420 100644 --- a/lib/arke_server/controllers/unit_controller.ex +++ b/lib/arke_server/controllers/unit_controller.ex @@ -18,7 +18,6 @@ defmodule ArkeServer.UnitController do # Openapi request definition use ArkeServer.Openapi.Spec, module: ArkeServer.Openapi.UnitControllerSpec - alias Arke.{QueryManager, LinkManager, StructManager} alias Arke.Boundary.{ArkeManager, ParameterManager} alias UnitSerializer @@ -31,8 +30,8 @@ defmodule ArkeServer.UnitController do import ArkeServer.ArkeController, only: [data_as_klist: 1] @doc """ - Search units - """ + Search units + """ def search(conn, %{}) do project = conn.assigns[:arke_project] offset = Map.get(conn.query_params, "offset", 0) @@ -52,8 +51,8 @@ defmodule ArkeServer.UnitController do end @doc """ - Update an unit - """ + Update an unit + """ def update(%Plug.Conn{body_params: params} = conn, %{ "unit_id" => _unit_id, "arke_id" => _arke_id @@ -79,4 +78,62 @@ defmodule ArkeServer.UnitController do ResponseManager.send_resp(conn, 400, nil, error) end end + + @doc """ + Update units in bulk + """ + def update_bulk(%Plug.Conn{body_params: params} = conn, %{ + "arke_id" => id + }) do + project = conn.assigns[:arke_project] + # TODO handle query parameter with plugs + load_links = Map.get(conn.query_params, "load_links", "false") == "true" + load_values = Map.get(conn.query_params, "load_values", "false") == "true" + + arke = ArkeManager.get(String.to_atom(id), project) + + permission = conn.assigns[:permission_filter] || %{filter: nil} + member = ArkeAuth.Guardian.Plug.current_resource(conn) + + unit_ids = Enum.map(params["data"], fn unit -> Map.get(unit, "id") end) + + existing_units = + QueryManager.query(project: project, arke: arke.id) + |> QueryFilters.apply_query_filters(permission.filter) + |> QueryFilters.apply_member_child_only(member, Map.get(permission, :child_only, false)) + |> QueryManager.where(id__in: unit_ids) + |> QueryManager.all() + + QueryManager.update_bulk(project, arke, existing_units, params["data"]) + |> case do + {:ok, valid, errors} -> + parsed_errors = + Enum.map(errors, fn {unit, msg} -> + %{ + data: + StructManager.encode(unit, + load_links: load_links, + load_values: load_values, + type: :json + ), + error: msg + } + end) + + ResponseManager.send_resp(conn, 200, %{ + content: %{ + items: + StructManager.encode(valid, + load_links: load_links, + load_values: load_values, + type: :json + ), + errors: parsed_errors + } + }) + + {:error, error} -> + ResponseManager.send_resp(conn, 400, nil, error) + end + end end diff --git a/lib/arke_server/router.ex b/lib/arke_server/router.ex index 5101df1..60fcde0 100644 --- a/lib/arke_server/router.ex +++ b/lib/arke_server/router.ex @@ -150,6 +150,7 @@ defmodule ArkeServer.Router do # UNIT put("/:arke_id/unit/:unit_id", UnitController, :update) + put("/:arke_id/bulk/unit", UnitController, :update_bulk) put("/:arke_id/parameter/:arke_parameter_id", TopologyController, :update_parameter) From ede11bff27c809817097bf802da68dbc2e7d95ca Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Mon, 3 Jun 2024 12:54:36 +0200 Subject: [PATCH 03/15] feat: bulk delete --- .../controllers/arke_controller.ex | 45 +++++++++++++++++++ lib/arke_server/router.ex | 1 + 2 files changed, 46 insertions(+) diff --git a/lib/arke_server/controllers/arke_controller.ex b/lib/arke_server/controllers/arke_controller.ex index 74fea2f..f44a447 100644 --- a/lib/arke_server/controllers/arke_controller.ex +++ b/lib/arke_server/controllers/arke_controller.ex @@ -167,6 +167,51 @@ defmodule ArkeServer.ArkeController do end end + # delete bulk + @doc """ + Delete a list of units + """ + def delete_bulk(conn, %{"arke_id" => arke_id} = params) do + project = conn.assigns[:arke_project] + + permission = conn.assigns[:permission_filter] || %{filter: nil} + member = ArkeAuth.Guardian.Plug.current_resource(conn) + + unit_ids = Map.get(params, "id", []) + + existing_units = + QueryManager.query(project: project, arke: arke_id) + |> QueryFilters.apply_query_filters(permission.filter) + |> QueryFilters.apply_member_child_only(member, Map.get(permission, :child_only, false)) + |> QueryManager.where(id__in: unit_ids) + |> QueryManager.all() + + QueryManager.delete_bulk(project, existing_units) + |> case do + {:ok, valid, errors} -> + parsed_errors = + Enum.map(errors, fn {unit, msg} -> + %{ + data: + StructManager.encode(unit, + type: :json + ), + error: msg + } + end) + + ResponseManager.send_resp(conn, 204, %{ + content: %{ + items: [], + errors: parsed_errors + } + }) + + {:error, error} -> + ResponseManager.send_resp(conn, 400, nil, error) + end + end + @doc """ Get units """ diff --git a/lib/arke_server/router.ex b/lib/arke_server/router.ex index 60fcde0..da05e9d 100644 --- a/lib/arke_server/router.ex +++ b/lib/arke_server/router.ex @@ -180,6 +180,7 @@ defmodule ArkeServer.Router do :delete_node ) + delete("/:arke_id/unit/bulk", ArkeController, :delete_bulk) delete("/:arke_id/unit/:unit_id", ArkeController, :delete) # -------- CALL FUNCTION -------- From b5c8e2d08a3669168dc9f21e3929df992eb84076 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Mon, 3 Jun 2024 16:35:42 +0200 Subject: [PATCH 04/15] fix: delete response --- .../controllers/arke_controller.ex | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/lib/arke_server/controllers/arke_controller.ex b/lib/arke_server/controllers/arke_controller.ex index f44a447..e050dc0 100644 --- a/lib/arke_server/controllers/arke_controller.ex +++ b/lib/arke_server/controllers/arke_controller.ex @@ -162,7 +162,7 @@ defmodule ArkeServer.ArkeController do QueryManager.delete(project, conn.assigns[:unit]) |> case do - {:ok, nil} -> ResponseManager.send_resp(conn, 204) + {:ok, _} -> ResponseManager.send_resp(conn, 204) {:error, error} -> ResponseManager.send_resp(conn, 400, nil, error) end end @@ -188,24 +188,8 @@ defmodule ArkeServer.ArkeController do QueryManager.delete_bulk(project, existing_units) |> case do - {:ok, valid, errors} -> - parsed_errors = - Enum.map(errors, fn {unit, msg} -> - %{ - data: - StructManager.encode(unit, - type: :json - ), - error: msg - } - end) - - ResponseManager.send_resp(conn, 204, %{ - content: %{ - items: [], - errors: parsed_errors - } - }) + {:ok, _, _} -> + ResponseManager.send_resp(conn, 204) {:error, error} -> ResponseManager.send_resp(conn, 400, nil, error) From 00b1aa2d72b0db4018f6cb3798a5f69b27201357 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Tue, 4 Jun 2024 18:05:30 +0200 Subject: [PATCH 05/15] fix: better response handling --- .../controllers/arke_controller.ex | 35 ++++++++----------- .../controllers/unit_controller.ex | 34 ++++++++---------- 2 files changed, 30 insertions(+), 39 deletions(-) diff --git a/lib/arke_server/controllers/arke_controller.ex b/lib/arke_server/controllers/arke_controller.ex index e050dc0..06e814f 100644 --- a/lib/arke_server/controllers/arke_controller.ex +++ b/lib/arke_server/controllers/arke_controller.ex @@ -114,31 +114,26 @@ defmodule ArkeServer.ArkeController do runtime_data: %{conn: conn} ) |> case do - {:ok, valid, errors} -> - parsed_errors = - Enum.map(errors, fn {unit, msg} -> - %{ - data: - StructManager.encode(unit, - load_links: load_links, - load_values: load_values, - load_files: load_files, - type: :json - ), - error: msg - } - end) - - ResponseManager.send_resp(conn, 200, %{ - content: %{ - items: - StructManager.encode(valid, + {:ok, inserted_count, errors} -> + error_units = + Enum.map(errors, fn {unit, unit_errors} -> + Map.put( + StructManager.encode(unit, load_links: load_links, load_values: load_values, load_files: load_files, type: :json ), - errors: parsed_errors + "errors", + unit_errors + ) + end) + + ResponseManager.send_resp(conn, 200, %{ + content: %{ + success_count: inserted_count, + error_count: length(error_units), + error_units: error_units } }) diff --git a/lib/arke_server/controllers/unit_controller.ex b/lib/arke_server/controllers/unit_controller.ex index 27dc420..643ebf5 100644 --- a/lib/arke_server/controllers/unit_controller.ex +++ b/lib/arke_server/controllers/unit_controller.ex @@ -106,29 +106,25 @@ defmodule ArkeServer.UnitController do QueryManager.update_bulk(project, arke, existing_units, params["data"]) |> case do - {:ok, valid, errors} -> - parsed_errors = - Enum.map(errors, fn {unit, msg} -> - %{ - data: - StructManager.encode(unit, - load_links: load_links, - load_values: load_values, - type: :json - ), - error: msg - } - end) - - ResponseManager.send_resp(conn, 200, %{ - content: %{ - items: - StructManager.encode(valid, + {:ok, updated_count, errors} -> + error_units = + Enum.map(errors, fn {unit, unit_errors} -> + Map.put( + StructManager.encode(unit, load_links: load_links, load_values: load_values, type: :json ), - errors: parsed_errors + "errors", + unit_errors + ) + end) + + ResponseManager.send_resp(conn, 200, %{ + content: %{ + success_count: updated_count, + error_count: length(error_units), + error_units: error_units } }) From e6e61daf510fc9119d348193488d491c82c23289 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara <81801314+ilyichv@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:12:16 +0200 Subject: [PATCH 06/15] fix: bulk return units (#69) --- .../controllers/arke_controller.ex | 23 ++--------- .../controllers/unit_controller.ex | 22 ++--------- lib/arke_server/utils/bulk.ex | 38 +++++++++++++++++++ 3 files changed, 44 insertions(+), 39 deletions(-) create mode 100644 lib/arke_server/utils/bulk.ex diff --git a/lib/arke_server/controllers/arke_controller.ex b/lib/arke_server/controllers/arke_controller.ex index 06e814f..437174c 100644 --- a/lib/arke_server/controllers/arke_controller.ex +++ b/lib/arke_server/controllers/arke_controller.ex @@ -114,27 +114,10 @@ defmodule ArkeServer.ArkeController do runtime_data: %{conn: conn} ) |> case do - {:ok, inserted_count, errors} -> - error_units = - Enum.map(errors, fn {unit, unit_errors} -> - Map.put( - StructManager.encode(unit, - load_links: load_links, - load_values: load_values, - load_files: load_files, - type: :json - ), - "errors", - unit_errors - ) - end) - + {:ok, inserted_count, units, errors} -> ResponseManager.send_resp(conn, 200, %{ - content: %{ - success_count: inserted_count, - error_count: length(error_units), - error_units: error_units - } + content: + ArkeServer.Utils.Bulk.build_response_content(conn, inserted_count, units, errors) }) {:error, error} -> diff --git a/lib/arke_server/controllers/unit_controller.ex b/lib/arke_server/controllers/unit_controller.ex index 643ebf5..7953624 100644 --- a/lib/arke_server/controllers/unit_controller.ex +++ b/lib/arke_server/controllers/unit_controller.ex @@ -106,26 +106,10 @@ defmodule ArkeServer.UnitController do QueryManager.update_bulk(project, arke, existing_units, params["data"]) |> case do - {:ok, updated_count, errors} -> - error_units = - Enum.map(errors, fn {unit, unit_errors} -> - Map.put( - StructManager.encode(unit, - load_links: load_links, - load_values: load_values, - type: :json - ), - "errors", - unit_errors - ) - end) - + {:ok, updated_count, units, errors} -> ResponseManager.send_resp(conn, 200, %{ - content: %{ - success_count: updated_count, - error_count: length(error_units), - error_units: error_units - } + content: + ArkeServer.Utils.Bulk.build_response_content(conn, updated_count, units, errors) }) {:error, error} -> diff --git a/lib/arke_server/utils/bulk.ex b/lib/arke_server/utils/bulk.ex new file mode 100644 index 0000000..fbbd77f --- /dev/null +++ b/lib/arke_server/utils/bulk.ex @@ -0,0 +1,38 @@ +defmodule ArkeServer.Utils.Bulk do + alias Arke.StructManager + + def build_response_content(conn, count, valid, errors) do + load_links = Map.get(conn.query_params, "load_links", "false") == "true" + load_values = Map.get(conn.query_params, "load_values", "false") == "true" + load_files = Map.get(conn.query_params, "load_files", "false") == "true" + return_units = Map.get(conn.query_params, "return_units", "false") == "true" + + error_units = + Enum.map(errors, fn {unit, unit_errors} -> + Map.put( + StructManager.encode(unit, + load_links: load_links, + load_values: load_values, + load_files: load_files, + type: :json + ), + "errors", + unit_errors + ) + end) + + response = %{ + success_count: count, + error_count: length(error_units), + error_units: error_units + } + + case return_units do + true -> + Map.put(response, :units, StructManager.encode(valid, type: :json)) + + false -> + response + end + end +end From 3504a64bbb69acf7150e3fb3b4c064085b2932a3 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara <81801314+ilyichv@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:16:06 +0200 Subject: [PATCH 07/15] feat: add nested filters and sort (#73) --- lib/arke_server/utils/query_filters.ex | 60 +++++++++++++++++++------- lib/arke_server/utils/query_order.ex | 8 +++- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/lib/arke_server/utils/query_filters.ex b/lib/arke_server/utils/query_filters.ex index d7136eb..8b45232 100644 --- a/lib/arke_server/utils/query_filters.ex +++ b/lib/arke_server/utils/query_filters.ex @@ -64,20 +64,21 @@ defmodule ArkeServer.Utils.QueryFilters do remove_match(match, acc) end) |> String.split(",") - |> Enum.reduce(%{error: [],operator: []},fn x,acc -> + |> Enum.reduce(%{error: [], operator: []}, fn x, acc -> case get_operator(x) do {:ok, op} -> - Map.update(acc,:operator,[],fn old -> old ++ [op]end) + Map.update(acc, :operator, [], fn old -> old ++ [op] end) {:error, msg} -> - Map.update(acc,:error,[],fn old -> msg ++ old end) + Map.update(acc, :error, [], fn old -> msg ++ old end) end end) - errors = Map.get(operator_list,:error) - operators = Map.get(operator_list,:operator) - if length(errors) >0 do - {:error,errors} + errors = Map.get(operator_list, :error) + operators = Map.get(operator_list, :operator) + + if length(errors) > 0 do + {:error, errors} else filters = Enum.with_index(operators) @@ -124,8 +125,11 @@ defmodule ArkeServer.Utils.QueryFilters do case String.split(data, ",", parts: 2) do [parameter_id, value] -> case get_condition(conn, parameter_id, operator, value, negate) do - {:error, msg} -> {:error, msg} - {:ok, condition} -> {:ok, condition} + {:error, msg} -> + {:error, msg} + + {:ok, condition} -> + {:ok, condition} end _ -> @@ -136,12 +140,37 @@ defmodule ArkeServer.Utils.QueryFilters do defp get_condition(conn, parameter_id, operator, value, negate) do project = conn.assigns[:arke_project] - case Arke.Boundary.ParameterManager.get(parameter_id, project) do - {:error, msg} -> - {:error, msg} + {parameter_id, path_ids} = + parameter_id + |> String.split(".") + |> List.pop_at(-1) - parameter -> - {:ok, QueryManager.condition(parameter, operator, parse_value(value, operator), negate)} + with {:ok, parameter} <- fetch_parameter(parameter_id, project), + {:ok, path} <- get_path_parameters(path_ids, project) do + {:ok, + QueryManager.condition(parameter, operator, parse_value(value, operator), negate, path)} + else + {:error, msg} -> {:error, msg} + end + end + + defp get_path_parameters(path_ids, project) do + Enum.reduce_while(path_ids, {:ok, []}, fn path_id, {:ok, acc} -> + case fetch_parameter(path_id, project) do + {:ok, parameter} -> {:cont, {:ok, [parameter | acc]}} + {:error, msg} -> {:halt, {:error, msg}} + end + end) + |> case do + {:ok, path} -> {:ok, Enum.reverse(path)} + error -> error + end + end + + defp fetch_parameter(parameter_id, project) do + case Arke.Boundary.ParameterManager.get(parameter_id, project) do + {:error, msg} -> {:error, msg} + parameter -> {:ok, parameter} end end @@ -183,5 +212,6 @@ defmodule ArkeServer.Utils.QueryFilters do defp get_operator("in(" <> _rest), do: {:ok, :in} defp get_operator("isnull(" <> _rest), do: {:ok, :isnull} - defp get_operator(invalid_filter), do: Error.create(:filter, "filter `#{invalid_filter}` not available") + defp get_operator(invalid_filter), + do: Error.create(:filter, "filter `#{invalid_filter}` not available") end diff --git a/lib/arke_server/utils/query_order.ex b/lib/arke_server/utils/query_order.ex index 68150ca..74dde65 100644 --- a/lib/arke_server/utils/query_order.ex +++ b/lib/arke_server/utils/query_order.ex @@ -19,9 +19,13 @@ defmodule ArkeServer.Utils.QueryOrder do def apply_order(query, [current | tail]) do case String.split(current, ";") do - [parameter, direction] -> + [parameter_id, direction] -> + parameters = + parameter_id + |> String.split(".") + apply_order( - QueryManager.order(query, parameter, String.to_existing_atom(direction)), + QueryManager.order(query, parameters, String.to_existing_atom(direction)), tail ) From 551e85bad89698105153c20e9dc4338edfa0a026 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Sat, 30 Nov 2024 14:39:40 +0100 Subject: [PATCH 08/15] fix: single result validator --- .../controllers/auth_controller.ex | 230 ++++++++++++------ 1 file changed, 154 insertions(+), 76 deletions(-) diff --git a/lib/arke_server/controllers/auth_controller.ex b/lib/arke_server/controllers/auth_controller.ex index dc9ac3c..9434d73 100644 --- a/lib/arke_server/controllers/auth_controller.ex +++ b/lib/arke_server/controllers/auth_controller.ex @@ -89,15 +89,21 @@ defmodule ArkeServer.AuthController do case Otp.generate(project, username, "signup") do {:ok, otp} -> case channel do - "mail" -> mailer_module().signup(conn, params, mode: "otp", unit: otp, code: otp.data.code) - "sms" -> mailer_module().signup(conn, params, mode: "otp_sms", unit: otp, code: otp.data.code) + "mail" -> + mailer_module().signup(conn, params, mode: "otp", unit: otp, code: otp.data.code) + + "sms" -> + mailer_module().signup(conn, params, mode: "otp_sms", unit: otp, code: otp.data.code) end + ResponseManager.send_resp(conn, 200, %{content: "OTP send successfully"}) + {:error, errors} -> ResponseManager.send_resp(conn, 401, nil, errors) end - end - defp handle_signup_mode( + end + + defp handle_signup_mode( conn, arke, %{ @@ -110,7 +116,15 @@ defmodule ArkeServer.AuthController do project, "otp_mail" ) - when is_nil(otp), do: handle_signup_mode(conn, arke, Map.merge(params, %{"phone" => nil, "channel" => "mail"}), project, "otp_mail") + when is_nil(otp), + do: + handle_signup_mode( + conn, + arke, + Map.merge(params, %{"phone" => nil, "channel" => "mail"}), + project, + "otp_mail" + ) defp handle_signup_mode( conn, @@ -159,42 +173,50 @@ defmodule ArkeServer.AuthController do project ) do {_, params} = Map.pop(req_params, "otp") - with {:ok, params, arke_system_user} <- check_user_on_signup(params, Map.get(params, "arke_system_user", nil)), + + with {:ok, params, arke_system_user} <- + check_user_on_signup(params, Map.get(params, "arke_system_user", nil)), params = Map.put(params, "last_access_time", NaiveDateTime.utc_now()), - {:ok, _member} <- QueryManager.create(project, arke, data_as_klist(params)) - do - username = Map.get(arke_system_user, "username", nil) - password = Map.get(arke_system_user, "password", nil) - Auth.validate_credentials(username, password, project) - |> case do - {:ok, member, access_token, refresh_token} -> - content = - Map.merge(Arke.StructManager.encode(member, type: :json), %{ - access_token: access_token, - refresh_token: refresh_token - }) - mailer_module().signup(conn,params, member: member,response_body: content) - ResponseManager.send_resp(conn, 200, %{content: content}) - - {:error, error} -> - ResponseManager.send_resp(conn, 401, nil, error) - end - else - ({:error, errors} -> ResponseManager.send_resp(conn, 400, errors)) - end + {:ok, _member} <- QueryManager.create(project, arke, data_as_klist(params)) do + username = Map.get(arke_system_user, "username", nil) + password = Map.get(arke_system_user, "password", nil) + + Auth.validate_credentials(username, password, project) + |> case do + {:ok, member, access_token, refresh_token} -> + content = + Map.merge(Arke.StructManager.encode(member, type: :json), %{ + access_token: access_token, + refresh_token: refresh_token + }) + mailer_module().signup(conn, params, member: member, response_body: content) + ResponseManager.send_resp(conn, 200, %{content: content}) + + {:error, error} -> + ResponseManager.send_resp(conn, 401, nil, error) + end + else + {:error, errors} -> ResponseManager.send_resp(conn, 400, errors) end + end - defp check_user_on_signup(_params, arke_system_user) when is_nil(arke_system_user) or arke_system_user == "" or arke_system_user == %{}, do: {:error, "arke_system_user is required"} - defp check_user_on_signup(params, arke_system_user) when is_binary(arke_system_user) do + defp check_user_on_signup(_params, arke_system_user) + when is_nil(arke_system_user) or arke_system_user == "" or arke_system_user == %{}, + do: {:error, "arke_system_user is required"} + + defp check_user_on_signup(params, arke_system_user) when is_binary(arke_system_user) do case Jason.decode(arke_system_user) do {:ok, u} -> params = Map.merge(params, %{"arke_system_user" => u}) {:ok, params, u} - {:error, _} -> {:error, "arke_system_user is not a valid json"} - end + + {:error, _} -> + {:error, "arke_system_user is not a valid json"} end - defp check_user_on_signup(params, arke_system_user), do: {:ok, params, arke_system_user} + end + + defp check_user_on_signup(params, arke_system_user), do: {:ok, params, arke_system_user} @doc """ Signin a user @@ -207,22 +229,25 @@ defmodule ArkeServer.AuthController do project = get_project(conn.assigns[:arke_project]) case QueryManager.get_by(project: project, group: :arke_auth_member, auth_token: token) do - nil -> ResponseManager.send_resp(conn, 401, "Unauthorized") + nil -> + ResponseManager.send_resp(conn, 401, "Unauthorized") + member -> with {:ok, access_token, _claims} <- ArkeAuth.Guardian.encode_and_sign(member, %{}), - {:ok, refresh_token, _claims} <- ArkeAuth.Guardian.encode_and_sign(member, %{}, token_type: "refresh") - do + {:ok, refresh_token, _claims} <- + ArkeAuth.Guardian.encode_and_sign(member, %{}, token_type: "refresh") do content = Map.merge(Arke.StructManager.encode(member, type: :json), %{ access_token: access_token, refresh_token: refresh_token }) + update_member_access_time(member, auth_token: nil) ResponseManager.send_resp(conn, 200, %{content: content}) - else {:error, type} -> - ResponseManager.send_resp(conn, 401, "Unauthorized") + else + {:error, type} -> + ResponseManager.send_resp(conn, 401, "Unauthorized") end - end end @@ -230,6 +255,7 @@ defmodule ArkeServer.AuthController do def signin(conn, %{"username" => username, "password" => password} = params) do project = get_project(conn.assigns[:arke_project]) auth_mode = System.get_env("AUTH_MODE", "default") + Auth.validate_credentials(username, password, project) |> case do {:ok, member, _access_token, _refresh_token} -> @@ -245,6 +271,7 @@ defmodule ArkeServer.AuthController do ResponseManager.send_resp(conn, 401, messages) end end + def signin(conn, _params), do: ResponseManager.send_resp(conn, 404, nil) defp handle_signin_mode( @@ -255,7 +282,9 @@ defmodule ArkeServer.AuthController do ), do: handle_signin(conn, username, password, project) - defp handle_signin_mode(conn, _, _project, "default"), do: params_required(conn, ["username","password"]) + defp handle_signin_mode(conn, _, _project, "default"), + do: params_required(conn, ["username", "password"]) + defp handle_signin_mode( conn, %{"username" => username, "password" => password, "otp" => otp, "channel" => channel}, @@ -266,32 +295,44 @@ defmodule ArkeServer.AuthController do Auth.validate_credentials(username, password, project) |> case do {:ok, member, _access_token, _refresh_token} -> - data = %{ - arke_id: member.arke_id, - id: member.id, - arke_system_user: member.data.arke_system_user, - email: member.data.email, - phone: hide_phone_number(Map.get(member.data, :phone, nil)), - inactive: Map.get(member.data, :inactive, false) + arke_id: member.arke_id, + id: member.id, + arke_system_user: member.data.arke_system_user, + email: member.data.email, + phone: hide_phone_number(Map.get(member.data, :phone, nil)), + inactive: Map.get(member.data, :inactive, false) } reviewer = get_review_email() if username in reviewer do review_code = get_review_code() - mailer_module().signin(conn,member, mode: "otp", code: review_code) + mailer_module().signin(conn, member, mode: "otp", code: review_code) ResponseManager.send_resp(conn, 200, data, "OTP send successfully") else case Otp.generate(project, member.id, "signin") do - {:ok, otp} -> - case channel do - "mail" -> mailer_module().signin(conn, member, mode: "otp", unit: otp, code: otp.data.code) - "sms" -> mailer_module().signin(conn, member, mode: "otp_sms", unit: otp, code: otp.data.code) - end - ResponseManager.send_resp(conn, 200, data, "OTP send successfully") - {:error, errors} -> - ResponseManager.send_resp(conn, 401, nil, errors) + {:ok, otp} -> + case channel do + "mail" -> + mailer_module().signin(conn, member, + mode: "otp", + unit: otp, + code: otp.data.code + ) + + "sms" -> + mailer_module().signin(conn, member, + mode: "otp_sms", + unit: otp, + code: otp.data.code + ) + end + + ResponseManager.send_resp(conn, 200, data, "OTP send successfully") + + {:error, errors} -> + ResponseManager.send_resp(conn, 401, nil, errors) end end @@ -299,6 +340,7 @@ defmodule ArkeServer.AuthController do ResponseManager.send_resp(conn, 401, nil, error) end end + defp handle_signin_mode( conn, %{"username" => username, "password" => password, "otp" => otp} = params, @@ -319,6 +361,7 @@ defmodule ArkeServer.AuthController do |> case do {:ok, member, _access_token, _refresh_token} -> reviewer = get_review_email() + if username in reviewer do if otp == get_review_code() do handle_signin(conn, username, password, project) @@ -326,7 +369,7 @@ defmodule ArkeServer.AuthController do ResponseManager.send_resp(conn, 401, nil, "Unauthorized") end else - OtpManager.get_code(project,member,"signin") + OtpManager.get_code(project, member, "signin") |> case do nil -> ResponseManager.send_resp(conn, 401, nil, "Unauthorized") @@ -357,7 +400,8 @@ defmodule ArkeServer.AuthController do end end - defp handle_signin_mode(conn, _, _project, "otp_mail"), do: params_required(conn, ["username","password","otp"]) + defp handle_signin_mode(conn, _, _project, "otp_mail"), + do: params_required(conn, ["username", "password", "otp"]) defp handle_signin_mode(conn, _, _project, _), do: auth_not_active(conn) @@ -383,16 +427,22 @@ defmodule ArkeServer.AuthController do def update_member_access_time(member, args \\ []) do datetime_now = NaiveDateTime.utc_now() update_data = [last_access_time: datetime_now] - update_data = if Map.get(member.data, :first_access_time, nil) == nil, do: Keyword.put(update_data, :first_access_time, datetime_now), else: update_data + + update_data = + if Map.get(member.data, :first_access_time, nil) == nil, + do: Keyword.put(update_data, :first_access_time, datetime_now), + else: update_data + update_data = Keyword.merge(update_data, args) QueryManager.update(member, update_data) end defp hide_phone_number(nil), do: nil defp hide_phone_number(""), do: nil + defp hide_phone_number(phone_number) do - masked_part = String.duplicate("*", String.length(phone_number) - 3) - masked_part <> String.slice(phone_number, -3, 3) + masked_part = String.duplicate("*", String.length(phone_number) - 3) + masked_part <> String.slice(phone_number, -3, 3) end @doc """ @@ -438,6 +488,7 @@ defmodule ArkeServer.AuthController do handle_change_password_mode(conn, params, member, auth_mode) end end + def change_password(conn, _), do: ResponseManager.send_resp(conn, 400, nil) defp handle_change_password_mode( @@ -448,7 +499,8 @@ defmodule ArkeServer.AuthController do ), do: handle_change_password(conn, member, old_pwd, new_pwd) - defp handle_change_password_mode(conn, _, _, _mode), do: params_required(conn, ["old_password","password"]) + defp handle_change_password_mode(conn, _, _, _mode), + do: params_required(conn, ["old_password", "password"]) defp handle_change_password_mode(conn, _, _, _), do: auth_not_active(conn) @@ -478,20 +530,21 @@ defmodule ArkeServer.AuthController do case QueryManager.get_by(project: project, group_id: :arke_auth_member, email: email) do nil -> - {:error,msg} = Error.create(:auth, "member not found with given email") + {:error, msg} = Error.create(:auth, "member not found with given email") ResponseManager.send_resp(conn, 404, msg) member -> case member.arke_id do :super_admin -> handle_recover_password(conn, member, params) + _ -> handle_recover_password_mode(conn, params, member, auth_mode) end end end - def recover_password(conn, _), do: ResponseManager.send_resp(conn, 400, nil) + def recover_password(conn, _), do: ResponseManager.send_resp(conn, 400, nil) defp handle_recover_password_mode( conn, @@ -502,6 +555,7 @@ defmodule ArkeServer.AuthController do do: handle_recover_password(conn, email, "default") defp handle_recover_password_mode(conn, _, _, "default"), do: params_required(conn, ["email"]) + defp handle_recover_password_mode( conn, %{"email" => _email, "otp" => otp, "channel" => channel}, @@ -509,19 +563,31 @@ defmodule ArkeServer.AuthController do "otp_mail" ) when is_nil(otp) do - case Otp.generate(project, member.id, "reset_password") do {:ok, otp} -> case channel do - "mail" -> mailer_module().reset_password(conn,member,mode: "otp",unit: otp,code: otp.data.code) - "sms" -> mailer_module().reset_password(conn,member,mode: "otp_sms",unit: otp,code: otp.data.code) + "mail" -> + mailer_module().reset_password(conn, member, + mode: "otp", + unit: otp, + code: otp.data.code + ) + + "sms" -> + mailer_module().reset_password(conn, member, + mode: "otp_sms", + unit: otp, + code: otp.data.code + ) end + ResponseManager.send_resp(conn, 200, %{content: "OTP send successfully"}) {:error, errors} -> ResponseManager.send_resp(conn, 401, nil, errors) end end + defp handle_recover_password_mode( conn, %{"email" => _email, "otp" => otp} = params, @@ -529,19 +595,25 @@ defmodule ArkeServer.AuthController do "otp_mail" ) when is_nil(otp) do - handle_recover_password_mode(conn, Map.merge(params, %{"channel" => "mail"}), member, "otp_mail") + handle_recover_password_mode( + conn, + Map.merge(params, %{"channel" => "mail"}), + member, + "otp_mail" + ) end - defp handle_recover_password_mode(conn, _, _, "otp_mail"), do: params_required(conn, ["email","otp"]) - defp handle_recover_password_mode(conn, _, _, _), do: auth_not_active(conn) - + defp handle_recover_password_mode(conn, _, _, "otp_mail"), + do: params_required(conn, ["email", "otp"]) + defp handle_recover_password_mode(conn, _, _, _), do: auth_not_active(conn) defp handle_recover_password(conn, email, "default") do default_msg = "An email has been sent to the given email" + case QueryManager.get_by(email: email, arke_id: :user, project: :arke_system) do nil -> - ResponseManager.send_resp(conn, 200,default_msg ) + ResponseManager.send_resp(conn, 200, default_msg) user -> old_token_list = @@ -561,7 +633,13 @@ defmodule ArkeServer.AuthController do {:ok, unit} -> url_token = unit.data.token endpoint = "#{System.get_env("RESET_PASSWORD_ENDPOINT", "")}/#{url_token}" - mailer_module().reset_password(conn,user,mode: "email", unit: unit, endpoint: endpoint) + + mailer_module().reset_password(conn, user, + mode: "email", + unit: unit, + endpoint: endpoint + ) + ResponseManager.send_resp(conn, 200, default_msg) end end @@ -676,13 +754,13 @@ defmodule ArkeServer.AuthController do defp check_token_expiration(_token), do: Error.create(:auth, "invalid token") defp auth_not_active(conn) do - {:error,msg} = Error.create(:auth, "auth method not active") + {:error, msg} = Error.create(:auth, "auth method not active") ResponseManager.send_resp(conn, 400, msg) end - defp params_required(conn,param) do - param_msg = Enum.map(param,fn p -> "#{String.downcase(p)}" end) |> Enum.join(", ") - {:error,msg} = Error.create(:auth, "#{param_msg} required") + defp params_required(conn, param) do + param_msg = Enum.map(param, fn p -> "#{String.downcase(p)}" end) |> Enum.join(", ") + {:error, msg} = Error.create(:auth, "#{param_msg} required") ResponseManager.send_resp(conn, 400, msg) end end From 4c62a2cf12b503fdccf36d8f36c9686516d198f5 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Mon, 10 Feb 2025 16:52:28 +0100 Subject: [PATCH 09/15] fix: microsoft oauth --- lib/arke_server/oauth/providers/microsoft.ex | 41 ++++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/lib/arke_server/oauth/providers/microsoft.ex b/lib/arke_server/oauth/providers/microsoft.ex index 988caa0..ca53779 100644 --- a/lib/arke_server/oauth/providers/microsoft.ex +++ b/lib/arke_server/oauth/providers/microsoft.ex @@ -9,11 +9,10 @@ defmodule ArkeServer.OAuth.Provider.Microsoft do token_data = conn.private[@private_oauth_key] %UserInfo{ - first_name: token_data["givenName"], - last_name: token_data["surname"], - email: token_data["mail"] + first_name: token_data["given_name"], + last_name: token_data["family_name"], + email: token_data["upn"] } - end def uid(conn) do @@ -22,8 +21,15 @@ defmodule ArkeServer.OAuth.Provider.Microsoft do def handle_cleanup(conn), do: put_private(conn, @private_oauth_key, nil) + def handle_request( + %Plug.Conn{body_params: %{"id_token" => token, "access_token" => access_token}} = conn + ) do + IO.inspect(token, label: "token") + IO.inspect(access_token, label: "access_token") + + IO.inspect(verify_token(token), label: "verify_token") + IO.inspect(get_user_data(access_token), label: "get_user_data") - def handle_request(%Plug.Conn{body_params: %{"id_token" => token, "access_token"=> access_token}} = conn) do with {:ok, claims} <- verify_token(token), {:ok, data} <- get_user_data(access_token) do put_private(conn, @private_oauth_key, data) @@ -39,6 +45,7 @@ defmodule ArkeServer.OAuth.Provider.Microsoft do def handle_request(conn) do {:error, msg} = Error.create(:auth, "token not found") + Plug.Conn.assign( conn, :arke_server_oauth_failure, @@ -73,11 +80,11 @@ defmodule ArkeServer.OAuth.Provider.Microsoft do defp decode_and_verify(token) do jwt = JOSE.JWT.peek(token) + case validate_signature(token) do :ok -> {:ok, jwt.fields} {:error, reason} -> {:error, reason} end - end defp validate_signature(jwt) do @@ -89,27 +96,37 @@ defmodule ArkeServer.OAuth.Provider.Microsoft do end end) - {:error, reason} -> {:error, reason} + {:error, reason} -> + {:error, reason} end end defp get_public_keys do uri = "https://login.microsoftonline.com/#{get_key("AZURE_TENANT_ID")}/discovery/v2.0/keys" + case HTTPoison.get(uri) do {:ok, %HTTPoison.Response{status_code: 200, body: body}} -> keys = body |> Jason.decode!() |> Map.get("keys") {:ok, Enum.map(keys, &JOSE.JWK.from(&1))} - {:error, %HTTPoison.Error{reason: reason}} -> {:error, reason} + {:error, %HTTPoison.Error{reason: reason}} -> + {:error, reason} end end defp validate_claims(claims) do cond do - claims["iss"] != "https://login.microsoftonline.com/#{get_key("AZURE_TENANT_ID")}/v2.0" -> {:error, "Invalid issuer"} - claims["tid"] != get_key("AZURE_TENANT_ID") -> {:error, "Invalid tenant"} - DatetimeHandler.from_unix(Map.get(claims, "exp", 0)) < DatetimeHandler.now(:datetime) -> {:error, "Token expired"} - true -> :ok + claims["iss"] != "https://login.microsoftonline.com/#{get_key("AZURE_TENANT_ID")}/v2.0" -> + {:error, "Invalid issuer"} + + claims["tid"] != get_key("AZURE_TENANT_ID") -> + {:error, "Invalid tenant"} + + DatetimeHandler.from_unix(Map.get(claims, "exp", 0)) < DatetimeHandler.now(:datetime) -> + {:error, "Token expired"} + + true -> + :ok end end From 64a452e35c5cd02de8148bc9fce510f00ca81c07 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara <81801314+ilyichv@users.noreply.github.com> Date: Mon, 10 Feb 2025 17:53:48 +0100 Subject: [PATCH 10/15] wip: add topology bulk operations (#78) --- .../controllers/topology_controller.ex | 93 ++++++++++++++----- lib/arke_server/router.ex | 6 ++ lib/arke_server/utils/bulk.ex | 26 +++--- 3 files changed, 89 insertions(+), 36 deletions(-) diff --git a/lib/arke_server/controllers/topology_controller.ex b/lib/arke_server/controllers/topology_controller.ex index 20eb1c8..6743056 100644 --- a/lib/arke_server/controllers/topology_controller.ex +++ b/lib/arke_server/controllers/topology_controller.ex @@ -1,14 +1,13 @@ defmodule ArkeServer.TopologyController do @moduledoc """ - Documentation for `ArkeServer.TopologyController`. - """ + Documentation for `ArkeServer.TopologyController`. + """ use ArkeServer, :controller # Openapi request definition use ArkeServer.Openapi.Spec, module: ArkeServer.Openapi.TopologyControllerSpec - alias Arke.{QueryManager, LinkManager, StructManager} alias Arke.Utils.ErrorGenerator, as: Error alias UnitSerializer @@ -19,10 +18,9 @@ defmodule ArkeServer.TopologyController do alias OpenApiSpex.{Operation, Reference} @doc """ - Get the unit linked to an Arke - """ + Get the unit linked to an Arke + """ def get_node(conn, %{"arke_id" => _arke_id, "arke_unit_id" => _id, "direction" => direction}) do - offset = Map.get(conn.query_params, "offset", nil) limit = Map.get(conn.query_params, "limit", nil) order = Map.get(conn.query_params, "order", []) @@ -51,24 +49,28 @@ defmodule ArkeServer.TopologyController do QueryManager.query(project: project) |> QueryManager.link(conn.assigns[:unit], - depth: depth, - direction: direction, - type: link_type - ) + depth: depth, + direction: direction, + type: link_type + ) |> QueryFilters.apply_query_filters(Map.get(conn.assigns, :filter)) end - def get_node_count(conn, %{"arke_id" => _arke_id, "arke_unit_id" => _id, "direction" => direction}) do - - count = handle_get_node_query(conn, direction) - |> QueryManager.count() + def get_node_count(conn, %{ + "arke_id" => _arke_id, + "arke_unit_id" => _id, + "direction" => direction + }) do + count = + handle_get_node_query(conn, direction) + |> QueryManager.count() ResponseManager.send_resp(conn, 200, count) end @doc """ - Link two unit together - """ + Link two unit together + """ def create_node(%Plug.Conn{body_params: params} = conn, %{ "arke_id" => arke_id, "arke_id_two" => arke_id_two, @@ -90,7 +92,11 @@ defmodule ArkeServer.TopologyController do ResponseManager.send_resp( conn, 201, - StructManager.encode(unit, load_links: load_links, load_values: load_values, type: :json) + StructManager.encode(unit, + load_links: load_links, + load_values: load_values, + type: :json + ) ) {:error, error} -> @@ -99,9 +105,30 @@ defmodule ArkeServer.TopologyController do end @doc """ - Update metadata of an existing link - """ + Create a link between two units in bulk. + """ + def create_node_bulk(%Plug.Conn{body_params: params} = conn, _) do + project = conn.assigns[:arke_project] + case(LinkManager.add_node_bulk(project, params["data"])) do + {:ok, inserted_count, units, errors} -> + IO.inspect(inserted_count, label: "inserted_count") + IO.inspect(units, label: "units") + IO.inspect(errors, label: "errors") + + ResponseManager.send_resp(conn, 200, %{ + content: + ArkeServer.Utils.Bulk.build_response_content(conn, inserted_count, units, errors) + }) + + {:error, error} -> + ResponseManager.send_resp(conn, 400, nil, error) + end + end + + @doc """ + Update metadata of an existing link + """ def update_node(%Plug.Conn{body_params: params} = conn, %{ "arke_unit_id" => parent_id, "link_id" => type, @@ -118,8 +145,8 @@ defmodule ArkeServer.TopologyController do end @doc """ - Delete a connection between two units - """ + Delete a connection between two units + """ def delete_node(%Plug.Conn{body_params: params} = conn, %{ "arke_id" => _arke_id, "arke_id_two" => _arke_id_two, @@ -141,8 +168,24 @@ defmodule ArkeServer.TopologyController do end @doc """ - Associate a parameter to an Arke - """ + Delete a connection between two units in bulk. + """ + def delete_node_bulk(%Plug.Conn{body_params: params} = conn, _) do + project = conn.assigns[:arke_project] + + LinkManager.delete_node_bulk(project, params["data"]) + |> case do + {:ok, _, _} -> + ResponseManager.send_resp(conn, 204) + + {:error, error} -> + ResponseManager.send_resp(conn, 400, nil, error) + end + end + + @doc """ + Associate a parameter to an Arke + """ def add_parameter(%Plug.Conn{body_params: params} = conn, %{ "arke_parameter_id" => parameter_id, "arke_id" => arke_id @@ -173,8 +216,8 @@ defmodule ArkeServer.TopologyController do end @doc """ - Update an associated parameter of an Arke - """ + Update an associated parameter of an Arke + """ def update_parameter(%Plug.Conn{body_params: params} = conn, %{ "arke_parameter_id" => parameter_id, "arke_id" => arke_id diff --git a/lib/arke_server/router.ex b/lib/arke_server/router.ex index 118a1bc..70941e9 100644 --- a/lib/arke_server/router.ex +++ b/lib/arke_server/router.ex @@ -186,6 +186,9 @@ defmodule ArkeServer.Router do :create_node ) + post("/bulk/link", TopologyController, :create_node_bulk) + post("/bulk/link/:link_id", TopologyController, :create_node_bulk) + # -------- DELETE -------- delete( "/:arke_id/unit/:arke_unit_id/link/:link_id/:arke_id_two/unit/:unit_id_two", @@ -196,6 +199,9 @@ defmodule ArkeServer.Router do delete("/:arke_id/unit/bulk", ArkeController, :delete_bulk) delete("/:arke_id/unit/:unit_id", ArkeController, :delete) + delete("/bulk/link", TopologyController, :delete_node_bulk) + delete("/bulk/link/:link_id", TopologyController, :delete_node_bulk) + # -------- CALL FUNCTION -------- get("/:arke_id/function/:function_name", ArkeController, :call_arke_function) diff --git a/lib/arke_server/utils/bulk.ex b/lib/arke_server/utils/bulk.ex index fbbd77f..347b517 100644 --- a/lib/arke_server/utils/bulk.ex +++ b/lib/arke_server/utils/bulk.ex @@ -8,17 +8,21 @@ defmodule ArkeServer.Utils.Bulk do return_units = Map.get(conn.query_params, "return_units", "false") == "true" error_units = - Enum.map(errors, fn {unit, unit_errors} -> - Map.put( - StructManager.encode(unit, - load_links: load_links, - load_values: load_values, - load_files: load_files, - type: :json - ), - "errors", - unit_errors - ) + Enum.map(errors, fn + {unit, unit_errors} -> + Map.put( + StructManager.encode(unit, + load_links: load_links, + load_values: load_values, + load_files: load_files, + type: :json + ), + "errors", + unit_errors + ) + + error -> + error end) response = %{ From 3f2614307d0cc500bae8beb2eb6de031da93493e Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Fri, 21 Feb 2025 12:12:41 +0100 Subject: [PATCH 11/15] chore: logs --- .../controllers/oauth_controller.ex | 181 +++++++++++------- lib/arke_server/oauth/providers/microsoft.ex | 4 +- 2 files changed, 111 insertions(+), 74 deletions(-) diff --git a/lib/arke_server/controllers/oauth_controller.ex b/lib/arke_server/controllers/oauth_controller.ex index 5476de9..a97445e 100644 --- a/lib/arke_server/controllers/oauth_controller.ex +++ b/lib/arke_server/controllers/oauth_controller.ex @@ -23,7 +23,6 @@ defmodule ArkeServer.OAuthController do # Openapi request definition use ArkeServer.Openapi.Spec, module: ArkeServer.Openapi.OAuthControllerSpec - alias Arke.Boundary.GroupManager alias ArkeServer.ResponseManager @@ -49,13 +48,18 @@ defmodule ArkeServer.OAuthController do _params ) do project = conn.assigns[:arke_project] - case init_oauth_flow(project,auth, provider) do - {:ok, body,oauth_member} -> + + case init_oauth_flow(project, auth, provider) do + {:ok, body, oauth_member} -> member = QueryManager.get_by(project: project, id: oauth_member.id) - handle_member_login(conn,member) + handle_member_login(conn, member) ResponseManager.send_resp(conn, 200, %{content: body}) - {:error,[%{context: "auth", message: "unauthorized"}]=msg} -> ResponseManager.send_resp(conn, 401, msg) - {:error, msg} -> ResponseManager.send_resp(conn, 400, msg) + + {:error, [%{context: "auth", message: "unauthorized"}] = msg} -> + ResponseManager.send_resp(conn, 401, msg) + + {:error, msg} -> + ResponseManager.send_resp(conn, 400, msg) end end @@ -72,57 +76,82 @@ defmodule ArkeServer.OAuthController do end def handle_create_member( - %Plug.Conn{body_params: params}=conn, - %{"member" => member_id, "provider" => provider}=_all_params + %Plug.Conn{body_params: params} = conn, + %{"member" => member_id, "provider" => provider} = _all_params ) do user_resource = ArkeAuth.SSOGuardian.Plug.current_resource(conn) - user = QueryManager.get_by(project: :arke_system, arke_id: :user,id: user_resource.id) + user = QueryManager.get_by(project: :arke_system, arke_id: :user, id: user_resource.id) project = conn.assigns[:arke_project] provider_arke_id = String.to_existing_atom("oauth_#{provider}") - enable_sso_group = GroupManager.get(:enable_sso,project) + enable_sso_group = GroupManager.get(:enable_sso, project) # check if the given member_id is enable to sso login # check if the user has any oauth link # check if one of the oauth link has the arke_id equal to the given provider - with true <- member_id in (GroupManager.get_arke_list(enable_sso_group) |> Enum.map(fn ak -> to_string(ak.id)end)), - [_data] = link_list <- get_link(user,:child), - %Unit{}=_unit <- Enum.find(link_list, fn link_unit -> link_unit.arke_id == provider_arke_id end) do - case check_member(project,user) do + # there are no units associated with that provider or the provider does not exist + with true <- + member_id in (GroupManager.get_arke_list(enable_sso_group) + |> Enum.map(fn ak -> to_string(ak.id) end)), + [_data] = link_list <- get_link(user, :child), + %Unit{} = _unit <- + Enum.find(link_list, fn link_unit -> link_unit.arke_id == provider_arke_id end) do + case check_member(project, user) do # member does not exists so create one - {:ok,nil} -> - case create_member(project,user,params,member_id) do - {:ok,member} -> - {:ok, resource_member, access_token, refresh_token} = Auth.create_tokens(member,"default") - content = create_response_body(resource_member,access_token,refresh_token,false) - AuthController.mailer_module().signup(conn,resource_member, mode: "oauth",member: resource_member,response_body: content) - ResponseManager.send_resp(conn, 200, content) - err -> ResponseManager.send_resp(conn, 400, err) - end + {:ok, nil} -> + case create_member(project, user, params, member_id) do + {:ok, member} -> + {:ok, resource_member, access_token, refresh_token} = + Auth.create_tokens(member, "default") + + content = create_response_body(resource_member, access_token, refresh_token, false) + + AuthController.mailer_module().signup(conn, resource_member, + mode: "oauth", + member: resource_member, + response_body: content + ) + + ResponseManager.send_resp(conn, 200, content) + + err -> + ResponseManager.send_resp(conn, 400, err) + end + # member exists and it is active {:ok, resource_member, access_token, refresh_token} -> - content = create_response_body(resource_member,access_token,refresh_token,false) - AuthController.mailer_module().signup(conn,resource_member, mode: "oauth",member: resource_member,response_body: content) + content = create_response_body(resource_member, access_token, refresh_token, false) + + AuthController.mailer_module().signup(conn, resource_member, + mode: "oauth", + member: resource_member, + response_body: content + ) + ResponseManager.send_resp(conn, 200, content) + {:error, reason} -> {:error, reason} end - else nil -> # there are no units associated with that provider or the provider does not exist - # in any of the unit sso associated with the user + else + nil -> + # in any of the unit sso associated with the user {:error, msg} = Error.create(:sso, "invalid provider") ResponseManager.send_resp(conn, 400, msg) - false -> {:error, msg} = Error.create(:sso, "invalid member") - ResponseManager.send_resp(conn, 400, msg) # sso not enabled for the given member + + false -> + {:error, msg} = Error.create(:sso, "invalid member") + # sso not enabled for the given member + ResponseManager.send_resp(conn, 400, msg) end end def handle_create_member( - conn, + conn, _params ) do {:error, msg} = Error.create(:auth, "invalid token/provider") ResponseManager.send_resp(conn, 400, msg) end - # ------- Client Side ------- # ------- Using redirects ------- @@ -135,31 +164,36 @@ defmodule ArkeServer.OAuthController do _params ) do project = conn.assigns[:arke_project] - case init_oauth_flow(project,auth, provider) do - {:ok, body,_member} -> + + case init_oauth_flow(project, auth, provider) do + {:ok, body, _member} -> ResponseManager.send_resp(conn, 200, %{content: body}) - {:error, msg} -> ResponseManager.send_resp(conn, 400, msg) + + {:error, msg} -> + ResponseManager.send_resp(conn, 400, msg) end end # ------- end Using redirects ------- - defp init_oauth_flow(project,auth_info, provider) do + defp init_oauth_flow(project, auth_info, provider) do with {:ok, nil} <- check_provider(provider), {:ok, user} <- check_oauth(auth_info) do - case check_member(project,user) do - #if member does not exists creat a SSO token - {:ok,nil} -> {:ok, user, access_token, refresh_token} = Auth.create_tokens(user,"sso") - content = create_response_body(user,access_token,refresh_token,true) - {:ok, content,user} - # if exists and is active authenticate the user - {:ok, resource_member, access_token, refresh_token} -> - - content = create_response_body(resource_member,access_token,refresh_token,false) - {:ok, content,resource_member} - {:error, reason} -> - {:error, reason} - end + case check_member(project, user) do + # if member does not exists creat a SSO token + {:ok, nil} -> + {:ok, user, access_token, refresh_token} = Auth.create_tokens(user, "sso") + content = create_response_body(user, access_token, refresh_token, true) + {:ok, content, user} + + # if exists and is active authenticate the user + {:ok, resource_member, access_token, refresh_token} -> + content = create_response_body(resource_member, access_token, refresh_token, false) + {:ok, content, resource_member} + + {:error, reason} -> + {:error, reason} + end else {:error, reason} -> {:error, reason} @@ -200,31 +234,34 @@ defmodule ArkeServer.OAuthController do check_oauth_user(oauth_user_data, provider) end - defp create_response_body(resource,access_token,refresh_token,uncompleted_data) do + defp create_response_body(resource, access_token, refresh_token, uncompleted_data) do Map.merge(Arke.StructManager.encode(resource, type: :json), %{ access_token: access_token, refresh_token: refresh_token, - uncompleted_data: uncompleted_data, + uncompleted_data: uncompleted_data }) end - defp create_member(project,user,params,member_id) do - member_model = ArkeManager.get(String.to_atom(member_id),project) - member_data = Map.put(params,"arke_system_user", to_string(user.id)) |> Map.put("email",user.data.email) + defp create_member(project, user, params, member_id) do + member_model = ArkeManager.get(String.to_atom(member_id), project) + + member_data = + Map.put(params, "arke_system_user", to_string(user.id)) |> Map.put("email", user.data.email) + new_data = for {key, val} <- member_data, into: %{}, do: {String.to_atom(key), val} - QueryManager.create(project,member_model,new_data) + QueryManager.create(project, member_model, new_data) end defp create_user(user_data) do user_model = ArkeManager.get(:user, :arke_system) pwd = UUID.uuid4() updated_data = Map.put(user_data, :password, pwd) - email = Map.get(user_data,:email) + email = Map.get(user_data, :email) + case QueryManager.get_by(project: :arke_system, arke_id: :user, email: email) do nil -> QueryManager.create(:arke_system, user_model, updated_data) - user -> {:ok,user} + user -> {:ok, user} end - end defp create_link(parent_id, child_id, provider) do @@ -233,13 +270,13 @@ defmodule ArkeServer.OAuthController do }) end - defp get_link(unit,direction) do + defp get_link(unit, direction) do QueryManager.query(project: :arke_system) |> QueryManager.link(unit, - depth: 1, - direction: direction, - type: "oauth" - ) + depth: 1, + direction: direction, + type: "oauth" + ) |> QueryManager.all() end @@ -269,7 +306,7 @@ defmodule ArkeServer.OAuthController do oauth_unit -> # check if there is a link between the given oauth_unit and an user - case get_link(oauth_unit,:parent) do + case get_link(oauth_unit, :parent) do [] -> # create a user and connect the two with {:ok, user} <- create_user(oauth_user_data), @@ -290,17 +327,19 @@ defmodule ArkeServer.OAuthController do end end - defp check_member(project,user) do - case Auth.get_project_member(project,user) do - {:ok , member} -> Auth.create_tokens(Auth.format_member(member),"default") - {:error, [%{context: "auth", message: "member not exists"}]} -> {:ok,nil} # if not exists return {:ok,nil} - {:error, _msg} -> Error.create(:auth, "unauthorized") + defp check_member(project, user) do + case Auth.get_project_member(project, user) do + {:ok, member} -> Auth.create_tokens(Auth.format_member(member), "default") + # if not exists return {:ok,nil} + {:error, [%{context: "auth", message: "member not exists"}]} -> {:ok, nil} + {:error, _msg} -> Error.create(:auth, "unauthorized") end end - defp handle_member_login(_conn,nil), do: nil - defp handle_member_login(conn,member) do + defp handle_member_login(_conn, nil), do: nil + + defp handle_member_login(conn, member) do AuthController.update_member_access_time(member) - AuthController.mailer_module().signin(conn,member, mode: "oauth") + AuthController.mailer_module().signin(conn, member, mode: "oauth") end end diff --git a/lib/arke_server/oauth/providers/microsoft.ex b/lib/arke_server/oauth/providers/microsoft.ex index 822727f..662e63b 100644 --- a/lib/arke_server/oauth/providers/microsoft.ex +++ b/lib/arke_server/oauth/providers/microsoft.ex @@ -16,7 +16,7 @@ defmodule ArkeServer.OAuth.Provider.Microsoft do end def uid(conn) do - conn.private[@private_oauth_key]["id"] + conn.private[@private_oauth_key]["sub"] end def handle_cleanup(conn), do: put_private(conn, @private_oauth_key, nil) @@ -24,8 +24,6 @@ defmodule ArkeServer.OAuth.Provider.Microsoft do def handle_request( %Plug.Conn{body_params: %{"id_token" => token, "access_token" => access_token}} = conn ) do - IO.inspect(decode_access_token(access_token), label: "decode_access_token") - with {:ok, claims} <- verify_token(token), {:ok, access_token_claims} <- decode_access_token(access_token) do put_private(conn, @private_oauth_key, access_token_claims) From 89f4c8bee24c6eb4a8e22ef579c61fa104cd8665 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Fri, 9 May 2025 15:29:30 +0200 Subject: [PATCH 12/15] log --- .../controllers/oauth_controller.ex | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/arke_server/controllers/oauth_controller.ex b/lib/arke_server/controllers/oauth_controller.ex index a97445e..7167b65 100644 --- a/lib/arke_server/controllers/oauth_controller.ex +++ b/lib/arke_server/controllers/oauth_controller.ex @@ -177,8 +177,11 @@ defmodule ArkeServer.OAuthController do # ------- end Using redirects ------- defp init_oauth_flow(project, auth_info, provider) do - with {:ok, nil} <- check_provider(provider), - {:ok, user} <- check_oauth(auth_info) do + IO.inspect(project) + IO.inspect(auth_info) + + with {:ok, nil} <- check_provider(provider) |> IO.inspect(), + {:ok, user} <- check_oauth(auth_info) |> IO.inspect() do case check_member(project, user) do # if member does not exists creat a SSO token {:ok, nil} -> @@ -329,10 +332,17 @@ defmodule ArkeServer.OAuthController do defp check_member(project, user) do case Auth.get_project_member(project, user) do - {:ok, member} -> Auth.create_tokens(Auth.format_member(member), "default") + {:ok, member} -> + IO.inspect(project) + IO.inspect(member) + Auth.create_tokens(Auth.format_member(member), "default") + # if not exists return {:ok,nil} - {:error, [%{context: "auth", message: "member not exists"}]} -> {:ok, nil} - {:error, _msg} -> Error.create(:auth, "unauthorized") + {:error, [%{context: "auth", message: "member not exists"}]} -> + {:ok, nil} + + {:error, _msg} -> + Error.create(:auth, "unauthorized") end end From 19c645f0608a68874dcb7a87eaa37d37f9d29dbb Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Fri, 9 May 2025 16:53:01 +0200 Subject: [PATCH 13/15] log --- lib/arke_server/controllers/oauth_controller.ex | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/arke_server/controllers/oauth_controller.ex b/lib/arke_server/controllers/oauth_controller.ex index 7167b65..0a268f6 100644 --- a/lib/arke_server/controllers/oauth_controller.ex +++ b/lib/arke_server/controllers/oauth_controller.ex @@ -177,11 +177,8 @@ defmodule ArkeServer.OAuthController do # ------- end Using redirects ------- defp init_oauth_flow(project, auth_info, provider) do - IO.inspect(project) - IO.inspect(auth_info) - - with {:ok, nil} <- check_provider(provider) |> IO.inspect(), - {:ok, user} <- check_oauth(auth_info) |> IO.inspect() do + with {:ok, nil} <- check_provider(provider), + {:ok, user} <- check_oauth(auth_info) do case check_member(project, user) do # if member does not exists creat a SSO token {:ok, nil} -> @@ -339,6 +336,7 @@ defmodule ArkeServer.OAuthController do # if not exists return {:ok,nil} {:error, [%{context: "auth", message: "member not exists"}]} -> + IO.inspect("member not exists") {:ok, nil} {:error, _msg} -> From 7545c18313b7b48d32b99d32180b7456db8c7216 Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Fri, 9 May 2025 17:06:28 +0200 Subject: [PATCH 14/15] log --- lib/arke_server/controllers/oauth_controller.ex | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/arke_server/controllers/oauth_controller.ex b/lib/arke_server/controllers/oauth_controller.ex index 0a268f6..04b4054 100644 --- a/lib/arke_server/controllers/oauth_controller.ex +++ b/lib/arke_server/controllers/oauth_controller.ex @@ -330,13 +330,10 @@ defmodule ArkeServer.OAuthController do defp check_member(project, user) do case Auth.get_project_member(project, user) do {:ok, member} -> - IO.inspect(project) - IO.inspect(member) Auth.create_tokens(Auth.format_member(member), "default") # if not exists return {:ok,nil} {:error, [%{context: "auth", message: "member not exists"}]} -> - IO.inspect("member not exists") {:ok, nil} {:error, _msg} -> From dbede0e3e55b06007a52fec02aa45f21f3ea375f Mon Sep 17 00:00:00 2001 From: Ilyich Vismara Date: Mon, 23 Jun 2025 11:37:19 +0200 Subject: [PATCH 15/15] chore: update arke --- .github/workflows/publish_hex.yml | 2 +- mix.exs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish_hex.yml b/.github/workflows/publish_hex.yml index 0011197..2adeaaa 100644 --- a/.github/workflows/publish_hex.yml +++ b/.github/workflows/publish_hex.yml @@ -2,7 +2,7 @@ name: Publish package to Hex 📦 on: push: tags: - - "v[0-9]+.[0-9]+.[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]*" jobs: publish: diff --git a/mix.exs b/mix.exs index b377eb2..40f3c6b 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule ArkeServer.MixProject do use Mix.Project - @version "0.3.18" + @version "0.4.0-bulk.0" @scm_url "https://github.com/arkemishub/arke-server" @site_url "https://arkehub.com" @@ -69,9 +69,9 @@ defmodule ArkeServer.MixProject do {:ymlr, "~> 2.0", only: :dev}, {:excoveralls, "~> 0.10", only: :test}, {:credo, "~> 1.6", only: [:dev, :test], runtime: false}, - {:arke, "~> 0.3.16"}, - {:arke_postgres, "~> 0.3.7"}, - {:arke_auth, "~> 0.3.5"}, + {:arke, "~> 0.4.0-bulk.0"}, + {:arke_postgres, "~> 0.4.0-bulk.0"}, + {:arke_auth, "~> 0.4.0-bulk.0"}, {:hackney, "~> 1.18"}, {:swoosh, "~> 1.11"} ])