Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Clivern committed Jun 26, 2023
1 parent 3ba7abf commit eba8aa5
Show file tree
Hide file tree
Showing 16 changed files with 1,636 additions and 84 deletions.
21 changes: 21 additions & 0 deletions lib/campfire/context/user_context.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ defmodule Campfire.Context.UserContext do
|> Repo.one()
end

@doc """
Get user by API Key
"""
def get_user_by_api_key(api_key) do
from(
u in User,
where: u.api_key == ^api_key
)
|> Repo.one()
end

@doc """
Get user by email
"""
Expand Down Expand Up @@ -121,6 +132,16 @@ defmodule Campfire.Context.UserContext do
|> Repo.all()
end

@doc """
Count all users
"""
def count_users() do
from(u in User,
select: count(u.id)
)
|> Repo.one()
end

@doc """
Create a new user meta
"""
Expand Down
58 changes: 58 additions & 0 deletions lib/campfire/middleware/auth.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright 2023 Clivern. All rights reserved.
# Use of this source code is governed by the MIT
# license that can be found in the LICENSE file.

defmodule Campfire.Service.AuthMiddleware do
@moduledoc """
Auth Middleware
"""
import Plug.Conn

alias Campfire.Service.AuthService

@doc """
UI Auth
"""
def auth_ui(conn, _opts) do
result =
AuthService.is_authenticated(
conn.req_cookies["_uid"],
conn.req_cookies["_token"]
)

case result do
false ->
conn = assign(conn, :is_logged, false)
conn = assign(conn, :user_role, :anonymous)
conn = assign(conn, :user_id, "")
conn = assign(conn, :sess_token, "")
conn

{true, session} ->
case UserModule.get_user_by_id(session.user_id) do

Check warning on line 32 in lib/campfire/middleware/auth.ex

View workflow job for this annotation

GitHub Actions / OTP 25.1 / Elixir 1.14.5

UserModule.get_user_by_id/1 is undefined (module UserModule is not available or is yet to be defined)

Check warning on line 32 in lib/campfire/middleware/auth.ex

View workflow job for this annotation

GitHub Actions / OTP 25.1 / Elixir 1.14.4

UserModule.get_user_by_id/1 is undefined (module UserModule is not available or is yet to be defined)

Check warning on line 32 in lib/campfire/middleware/auth.ex

View workflow job for this annotation

GitHub Actions / OTP 25.1 / Elixir 1.14.3

UserModule.get_user_by_id/1 is undefined (module UserModule is not available or is yet to be defined)
{:ok, user} ->
conn = assign(conn, :is_logged, true)
conn = assign(conn, :user_role, String.to_atom(user.role))
conn = assign(conn, :user_id, session.user_id)
conn = assign(conn, :sess_token, session.value)
conn

{:not_found, _} ->
conn = assign(conn, :is_logged, false)
conn = assign(conn, :user_role, :anonymous)
conn = assign(conn, :user_id, "")
conn = assign(conn, :sess_token, "")
conn
end
end

conn
end

@doc """
API Auth
"""
def auth_api(conn, _opts) do
conn
end
end
2 changes: 1 addition & 1 deletion lib/campfire/module/install_module.ex
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ defmodule Campfire.Module.InstallModule do
password_hash: AuthService.hash_password(data[:admin_password], data[:app_key]),
verified: false,
last_seen: DateTime.utc_now(),
role: "super_admin",
role: "super",
api_key: AuthService.get_uuid()
})

Expand Down
132 changes: 132 additions & 0 deletions lib/campfire/module/user_module.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,136 @@ defmodule Campfire.Module.UserModule do
@moduledoc """
User Module
"""

alias Campfire.Context.UserContext
alias Campfire.Service.ValidatorService
alias Campfire.Service.AuthService

@doc """
Get User By ID
"""
def get_user_by_id(user_id) do
case UserContext.get_user_by_id(user_id) do
nil ->
{:not_found, nil}

user ->
{:ok, user}
end
end

@doc """
Count Users
"""
def count_users() do
UserContext.count_users()
end

@doc """
Get Users
"""
def get_users(offset, limit) do
UserContext.get_users(offset, limit)
end

@doc """
Create User
"""
def create_user(params \\ %{}) do
user =
UserContext.new_user(%{
email: params[:email],
name: params[:name],
password_hash:
AuthService.hash_password(
params[:password],
params[:app_key]
),
verified: false,
api_key: params[:api_key],
role: params[:role],
last_seen: DateTime.utc_now()
})

case UserContext.create_user(user) do
{:ok, user} ->
{:ok, user}

{:error, changeset} ->
messages =
changeset.errors()
|> Enum.map(fn {field, {message, _options}} -> "#{field}: #{message}" end)

{:error, Enum.at(messages, 0)}
end
end

@doc """
Update User
"""
def update_user(params \\ %{}) do
id = params[:id]

case ValidatorService.validate_int(id) do
true ->
user =
id
|> ValidatorService.parse_int()
|> UserContext.get_user_by_id()

case user do
nil ->
{:not_found, "User with ID #{id} not found"}

_ ->
new_user =
UserContext.new_user(%{
email: ValidatorService.get_str(params[:email], user.email),
name: ValidatorService.get_str(params[:name], user.name),
api_key: ValidatorService.get_str(params[:api_key], user.api_key),
role: ValidatorService.get_str(params[:role], user.role)
})

case UserContext.update_user(user, new_user) do
{:ok, user} ->
{:ok, user}

{:error, changeset} ->
messages =
changeset.errors()
|> Enum.map(fn {field, {message, _options}} -> "#{field}: #{message}" end)

{:error, Enum.at(messages, 0)}
end
end

false ->
{:error, "Invalid User ID"}
end
end

@doc """
Delete User
"""
def delete_user(id) do
case ValidatorService.validate_int(id) do
true ->
user =
id
|> ValidatorService.parse_int()
|> UserContext.get_user_by_id()

case user do
nil ->
{:not_found, "User with ID #{id} not found"}

_ ->
UserContext.delete_user(user)
{:ok, "User with ID #{id} deleted successfully"}
end

false ->
{:error, "Invalid User ID"}
end
end
end
19 changes: 18 additions & 1 deletion lib/campfire/service/auth_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ defmodule Campfire.Service.AuthService do
end

def authenticate(user_id) when is_nil(user_id) == true do
{:error, "Invalid user id"}
{:error, "Invalid User ID"}
end

@doc """
Expand All @@ -154,4 +154,21 @@ defmodule Campfire.Service.AuthService do
def logout(user_id) when is_nil(user_id) do
nil
end

@doc """
Get User By API Key
"""
def get_user_by_api(api_key) when is_nil(api_key) == false do
case UserContext.get_user_by_api_key(api_key) do
nil ->
{:not_found, "Invalid API Key"}

user ->
{:ok, user}
end
end

def get_user_by_api(api_key) when is_nil(api_key) do
{:not_found, "Invalid API Key"}
end
end
63 changes: 55 additions & 8 deletions lib/campfire_web/controllers/user_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,47 @@ defmodule CampfireWeb.UserController do
"""

use CampfireWeb, :controller
alias Campfire.Module.UserModule
alias Campfire.Service.ValidatorService
import Campfire.Service.AuthMiddleware

@default_list_limit "10"
@default_list_offset "0"

plug :auth_ui, only: [:list, :add, :edit, :delete]
plug :auth_api, only: [:list, :add, :edit, :delete]
plug :only_super_user, only: [:list, :add, :edit, :delete]

@doc """
List Action Endpoint
Allow only super users
"""
def list(conn, _params) do
def only_super_user(conn, _opts) do
# If user not super, return forbidden access
if conn.assigns[:user_role] != :super do
conn
|> put_status(:forbidden)
|> render("error.json", %{error: "Forbidden Access"})
|> halt()
end

conn
|> put_resp_content_type("application/json")
|> send_resp(200, Jason.encode!(%{status: "ok"}))
end

@doc """
List Action Endpoint
"""
def list(conn, params) do
limit = ValidatorService.get_int(params["limit"], @default_list_limit)
offset = ValidatorService.get_int(params["offset"], @default_list_offset)

render(conn, "list.json", %{
users: UserModule.get_users(offset, limit),
metadata: %{
limit: limit,
offset: offset,
totalCount: UserModule.count_users()
}
})
end

@doc """
Expand All @@ -39,9 +72,23 @@ defmodule CampfireWeb.UserController do
@doc """
Delete Action Endpoint
"""
def delete(conn, _params) do
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Jason.encode!(%{status: "ok"}))
def delete(conn, %{"id" => id}) do
result = UserModule.delete_user(id)

case result do
{:not_found, msg} ->
conn
|> put_status(:not_found)
|> render("error.json", %{error: msg})

{:ok, _} ->
conn
|> send_resp(:no_content, "")

{:error, msg} ->
conn
|> put_status(:bad_request)
|> render("error.json", %{error: msg})
end
end
end
Loading

0 comments on commit eba8aa5

Please sign in to comment.