Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
nelsonkopliku committed Jul 2, 2024
1 parent e881ff3 commit 16c8a8a
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 3 deletions.
38 changes: 35 additions & 3 deletions lib/trento/activity_logging/activity_logger.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,41 @@ defmodule Trento.ActivityLog.ActivityLogger do
ActivityLogger entry point
"""

@callback log_activity(context :: any()) :: :ok
alias Trento.ActivityLog.ActivityLog
alias Trento.ActivityLogging.Registry

def log_activity(context), do: adapter().log_activity(context)
@callback log_activity(activity_context :: any()) :: :ok

defp adapter, do: Application.fetch_env!(:trento, __MODULE__)[:adapter]
def log_activity(activity_context) do
activity_parser = get_activity_parser(activity_context)

detected_activity = activity_parser.detect_activity(activity_context)

if Registry.interested?(detected_activity, activity_context) do
%ActivityLog{}
|> ActivityLog.changeset(%{
type: get_activity_type(detected_activity),
actor: get_actor(activity_parser, detected_activity, activity_context),
metadata: get_metadata(activity_parser, detected_activity, activity_context)
})
|> Trento.Repo.insert()
end

:ok
end

defp get_activity_parser(%Plug.Conn{}), do: Trento.ActivityLogging.Logger.PhoenixConnParser
# defp get_logger(%Pipeline{}), do: Trento.ActivityLogging.Logger.CommandedRecongnizer

defp get_activity_type(detected_activity),
do:
detected_activity
|> Registry.get_activity_type()
|> Atom.to_string()

defp get_actor(activity_parser, detected_activity, activity_context),
do: activity_parser.get_activity_actor(detected_activity, activity_context)

defp get_metadata(activity_parser, detected_activity, activity_context),
do: activity_parser.get_activity_metadata(detected_activity, activity_context)
end
20 changes: 20 additions & 0 deletions lib/trento/activity_logging/activity_parser.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
defmodule Trento.ActivityLogging.ActivityParser do
@moduledoc """
Behavior for activity parsers.
It extracts the activity relevant information from the context.
"""

alias Trento.ActivityLogging.Registry

@callback detect_activity(activity_context :: any()) :: Registry.logged_activity() | nil

@callback get_activity_actor(
activity :: Registry.logged_activity(),
activity_context :: any()
) :: any()

@callback get_activity_metadata(
activity :: Registry.logged_activity(),
activity_context :: any()
) :: map()
end
127 changes: 127 additions & 0 deletions lib/trento/activity_logging/phoenix_conn_parser.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
defmodule Trento.ActivityLogging.Logger.PhoenixConnParser do
@moduledoc """
Phoenix connection activity parser
"""

alias Phoenix.Controller

alias Trento.Users.User

require Trento.ActivityLogging.Registry, as: Registry

@behaviour Trento.ActivityLogging.ActivityParser

def detect_activity(%Plug.Conn{} = conn) do
{Controller.controller_module(conn), Controller.action_name(conn)}
rescue
_ -> nil
end

def get_activity_actor(Registry.login_attempt(), %Plug.Conn{body_params: request_payload}),
do: Map.get(request_payload, "username", "no_username")

def get_activity_actor(_, %Plug.Conn{} = conn) do
case Pow.Plug.current_user(conn) do
%User{username: username} -> username
_ -> "system"
end
end

def get_activity_metadata(
Registry.login_attempt() = action,
%Plug.Conn{
assigns: %{
reason: reason
},
status: 401
} = conn
) do
%{
username: get_activity_actor(action, conn),
reason: reason
}
end

def get_activity_metadata(
Registry.resource_tagging(),
%Plug.Conn{
params: %{id: resource_id},
assigns: %{
resource_type: resource_type
},
body_params: %{value: added_tag}
}
) do
%{
resource_id: resource_id,
resource_type: resource_type,
added_tag: added_tag
}
end

def get_activity_metadata(
Registry.resource_untagging(),
%Plug.Conn{
params: %{
id: resource_id,
value: removed_tag
},
assigns: %{
resource_type: resource_type
}
}
) do
%{
resource_id: resource_id,
resource_type: resource_type,
removed_tag: removed_tag
}
end

def get_activity_metadata(
Registry.api_key_generation(),
%Plug.Conn{
body_params: request_body
}
) do
request_body
end

def get_activity_metadata(
action,
%Plug.Conn{
body_params: request_body
}
)
when action in [Registry.saving_suma_settings(), Registry.changing_suma_settings()] do
request_body
|> redact(:password)
|> redact(:ca_cert)
end

def get_activity_metadata(
action,
%Plug.Conn{
body_params: request_body
}
)
when action in [
Registry.user_creation(),
Registry.user_modification(),
Registry.profile_update()
] do
request_body
|> redact(:password)
|> redact(:current_password)
|> redact(:password_confirmation)
end

def get_activity_metadata, do: %{}

defp redact(request_body, key) do
case Map.has_key?(request_body, key) && Map.fetch!(request_body, key) != nil do
true -> Map.update!(request_body, key, fn _ -> "REDACTED" end)
false -> request_body
end
end
end
65 changes: 65 additions & 0 deletions lib/trento/activity_logging/registry.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
defmodule Trento.ActivityLogging.Registry do
@moduledoc """
Activity logging registry
"""

@type logged_activity :: {controller :: module(), action :: atom()}

@login_attempt {TrentoWeb.SessionController, :create}
@api_key_generation {TrentoWeb.V1.SettingsController, :update_api_key_settings}
@saving_suma_settings {TrentoWeb.V1.SUMACredentialsController, :create}
@changing_suma_settings {TrentoWeb.V1.SUMACredentialsController, :update}
@clearing_suma_settings {TrentoWeb.V1.SUMACredentialsController, :delete}
@tagging {TrentoWeb.V1.TagsController, :add_tag}
@untagging {TrentoWeb.V1.TagsController, :remove_tag}
@user_creation {TrentoWeb.V1.UsersController, :create}
@user_modification {TrentoWeb.V1.UsersController, :update}
@user_deletion {TrentoWeb.V1.UsersController, :delete}
@profile_update {TrentoWeb.V1.ProfileController, :update}
# @cluster_checks_selection {TrentoWeb.V1.ClusterController, :select_checks} # <-- this is event sourced
@cluster_checks_execution_request {TrentoWeb.V1.ClusterController, :request_checks_execution}

@action_registry %{
@login_attempt => {:login_attempt, :any},
@tagging => {:resource_tagging, 201},
@untagging => {:resource_untagging, 204},
@api_key_generation => {:api_key_generation, 200},
@saving_suma_settings => {:saving_suma_settings, 201},
@changing_suma_settings => {:changing_suma_settings, 200},
@clearing_suma_settings => {:clearing_suma_settings, 204},
@user_creation => {:user_creation, 201},
@user_modification => {:user_modification, 200},
@user_deletion => {:user_deletion, 204},
@profile_update => {:profile_update, 200},
@cluster_checks_execution_request => {:cluster_checks_selection, 202}
}

Enum.each(@action_registry, fn {action, {action_type, _}} ->
defmacro unquote(action_type)(), do: unquote(action)
end)

def interested?(activity, %Plug.Conn{status: status}),
do:
Map.has_key?(@action_registry, activity) &&
@action_registry
|> Map.fetch!(activity)
|> interesting_status?(status)

def interested?(_, _), do: false

@spec get_activity_type(logged_activity()) :: atom()
def get_activity_type(activity) do
@action_registry
|> Map.fetch!(activity)
|> elem(0)
end

@spec interesting_status?(
request_activity :: {activity_type :: atom(), relevant_status :: integer() | :any},
detected_status :: integer()
) ::
boolean()
defp interesting_status?({_, :any}, _), do: true
defp interesting_status?({_, status}, status), do: true
defp interesting_status?(_, _), do: false
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule Trento.Infrastructure.ActivityLog.Logger.PersistentLogger do
@moduledoc """
Persistent Activity Logger Adapter
"""

@behaviour Trento.ActivityLog.ActivityLogger

@impl true
def log_activity(_activity) do
:ok
end
end

0 comments on commit 16c8a8a

Please sign in to comment.