defmodule Blossom.Models.Users do alias Blossom.Models.Users alias Blossom.Utils alias KilnCore.Builders.Model, as: Builder alias KilnCore.Utils, as: KilnCoreUtils def fetch(func, params, user, ctx) do if ctx[:realms].is_admin?(user["sub"], user["iss"]) do apply(ctx[:schema], func, [Map.put(params, "realm", user["iss"])]) else allowed_casks = ["users/*", "users/list"] |> ctx[:casks_roles].get_perms_casks([], [], user) new_params = params |> Map.put("allowed_ids", user["sub"]) |> Map.put("allowed_casks", allowed_casks) apply(ctx[:schema], func, [new_params]) end end def new(params, user, ctx) do case user do :system -> ctx[:schema].new(params) :public -> params |> Builder.handle_params(ctx[:protected_fields], user) |> Map.delete("role") |> ctx[:schema].new() %{"sub" => _} -> if ctx[:realms].is_admin?(user["sub"], params["realm"]) do ctx[:schema].new(params) else {:error, :forbidden} end end end def get(params, user, ctx) do case user do :system -> ctx[:schema].get(params) %{"sub" => _} -> Users.fetch(:get, params, user, ctx) _ -> [] end end def get_count(params, user, ctx) do case user do :system -> ctx[:schema].get_count(params) %{"sub" => _} -> Users.fetch(:get_count, params, user, ctx) _ -> 0 end end def show_as_admin(id, user, ctx) do allowed_casks = ["users/*", "users/list", "users/show"] |> ctx[:casks_roles].get_perms_casks([], id, user) params = %{ "id" => id, "items" => 1, "access" => "show", "cask" => allowed_casks } case ctx[:schema].get(params) do [] -> {:error, :forbidden} users -> users end end def show(id, user, ctx) do case user do :system -> ctx[:schema].show(id) %{"sub" => _} -> cond do id == user["sub"] -> ctx[:schema].show(id) Utils.item_realm_admin?(id, user, ctx) -> ctx[:schema].show(id) true -> Users.show_as_admin(id, user, ctx) end _ -> {:error, :forbidden} end end def edit(params, id, user, ctx) do case user do :system -> ctx[:schema].edit(params, id) %{"sub" => _} -> cond do Utils.item_realm_admin?(id, user, ctx) -> params |> Map.delete("realm") |> ctx[:schema].edit(id) id == user["sub"] -> params |> Builder.handle_params(ctx[:protected_fields], user) |> Map.drop(["id", "email", "realm", "role"]) |> ctx[:schema].edit(id) true -> {:error, :forbidden} end _ -> {:error, :forbidden} end end def delete(id, user, ctx) do case user do :system -> ctx[:schema].delete(id) %{"sub" => _} -> cond do id == user["sub"] -> ctx[:schema].delete(id) Utils.item_realm_admin?(id, user, ctx) -> ctx[:schema].delete(id) true -> {:error, :forbidden} end _ -> {:error, :forbidden} end end defmacro __using__(opts \\ []) do quote do protected_fields = ["blocked", "email_verified"] use KilnCore.Model, protected_fields: Keyword.get(unquote(opts), :protected_fields, protected_fields), schema: unquote(Keyword.get(opts, :schema)) @casks_roles KilnCoreUtils.option_or_mod_replace( @caller, unquote(opts), :casks_roles, CasksRoles, 2 ) @realms KilnCoreUtils.option_or_mod_replace( @caller, unquote(opts), :realms, Realms, 2 ) @ctx [ schema: @schema, casks_roles: @casks_roles, realms: @realms, protected_fields: @protected_fields ] def new(params, user) do Users.new(params, user, @ctx) end def get(params, user) do Users.get(params, user, @ctx) end def get_count(params, user) do Users.get_count(params, user, @ctx) end def edit(params, id, user) do Users.edit(params, id, user, @ctx) end def show(id, user) do Users.show(id, user, @ctx) end def delete(id, user) do Users.delete(id, user, @ctx) end end end end