Packages

phoenix_kit

1.3.2
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib phoenix_kit_web live modules emails settings.ex
Raw

lib/phoenix_kit_web/live/modules/emails/settings.ex

defmodule PhoenixKitWeb.Live.Modules.Emails.Settings do
@moduledoc """
LiveView for email system configuration and settings management.
This module provides a comprehensive interface for managing all aspects
of the PhoenixKit email system, including:
- **System Control**: Enable/disable the entire email system
- **Storage Settings**: Configure email body and header storage
- **AWS SES Integration**: Manage SES event tracking and configuration
- **Data Management**: Set retention periods and sampling rates
- **Advanced Features**: Configure compression and S3 archival
- **SQS Configuration**: Control SQS polling and message processing
## Route
This LiveView is mounted at `{prefix}/admin/settings/emails` and requires
appropriate admin permissions.
Note: `{prefix}` is your configured PhoenixKit URL prefix (default: `/phoenix_kit`).
## Features
- Real-time settings updates with immediate effect
- AWS infrastructure configuration (SES, SNS, SQS)
- Data lifecycle management (retention, compression, archival)
- Performance tuning (sampling rate, polling intervals)
- Validation with user-friendly error messages
## Permissions
Access is restricted to users with admin or owner roles in PhoenixKit.
"""
use PhoenixKitWeb, :live_view
alias PhoenixKit.Emails
alias PhoenixKit.Settings
alias PhoenixKit.Utils.Routes
def mount(_params, session, socket) do
# Get current path for navigation
current_path = get_current_path(socket, session)
# Get project title from settings
project_title = Settings.get_setting("project_title", "PhoenixKit")
# Load email configuration
email_config = Emails.get_config()
# Load AWS settings
aws_settings = %{
access_key_id: Settings.get_setting("aws_access_key_id", ""),
secret_access_key: Settings.get_setting("aws_secret_access_key", ""),
region: Settings.get_setting("aws_region", "eu-north-1"),
sqs_queue_url: Settings.get_setting("aws_sqs_queue_url", ""),
sqs_dlq_url: Settings.get_setting("aws_sqs_dlq_url", ""),
sqs_queue_arn: Settings.get_setting("aws_sqs_queue_arn", ""),
sns_topic_arn: Settings.get_setting("aws_sns_topic_arn", ""),
ses_configuration_set:
Settings.get_setting("aws_ses_configuration_set", "phoenixkit-tracking"),
sqs_polling_interval_ms: Settings.get_setting("sqs_polling_interval_ms", "5000")
}
socket =
socket
|> assign(:current_path, current_path)
|> assign(:page_title, "Emails")
|> assign(:project_title, project_title)
|> assign(:email_enabled, email_config.enabled)
|> assign(:email_save_body, email_config.save_body)
|> assign(:email_save_headers, Emails.save_headers_enabled?())
|> assign(:email_ses_events, email_config.ses_events)
|> assign(:email_retention_days, email_config.retention_days)
|> assign(:email_sampling_rate, email_config.sampling_rate)
|> assign(:email_compress_body, email_config.compress_after_days)
|> assign(:email_archive_to_s3, email_config.archive_to_s3)
|> assign(:sqs_polling_enabled, email_config.sqs_polling_enabled)
|> assign(:sqs_polling_interval_ms, email_config.sqs_polling_interval_ms)
|> assign(:sqs_max_messages_per_poll, email_config.sqs_max_messages_per_poll)
|> assign(:sqs_visibility_timeout, email_config.sqs_visibility_timeout)
|> assign(:aws_settings, aws_settings)
|> assign(:saving, false)
{:ok, socket}
end
def handle_event("toggle_emails", _params, socket) do
# Toggle email system
new_enabled = !socket.assigns.email_enabled
result =
if new_enabled do
Emails.enable_system()
else
Emails.disable_system()
end
case result do
{:ok, _setting} ->
socket =
socket
|> assign(:email_enabled, new_enabled)
|> put_flash(
:info,
if(new_enabled,
do: "Email system enabled",
else: "Email system disabled"
)
)
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update email system")
{:noreply, socket}
end
end
def handle_event("toggle_email_save_body", _params, socket) do
# Toggle email body saving
new_save_body = !socket.assigns.email_save_body
result = Emails.set_save_body(new_save_body)
case result do
{:ok, _setting} ->
socket =
socket
|> assign(:email_save_body, new_save_body)
|> put_flash(
:info,
if(new_save_body,
do: "Email body saving enabled",
else: "Email body saving disabled"
)
)
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update email body saving setting")
{:noreply, socket}
end
end
def handle_event("toggle_email_save_headers", _params, socket) do
# Toggle email headers saving
new_save_headers = !socket.assigns.email_save_headers
result = Emails.set_save_headers(new_save_headers)
case result do
{:ok, _setting} ->
socket =
socket
|> assign(:email_save_headers, new_save_headers)
|> put_flash(
:info,
if(new_save_headers,
do: "Email headers saving enabled",
else: "Email headers saving disabled"
)
)
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update email headers saving setting")
{:noreply, socket}
end
end
def handle_event("toggle_email_ses_events", _params, socket) do
# Toggle AWS SES events tracking
new_ses_events = !socket.assigns.email_ses_events
result = Emails.set_ses_events(new_ses_events)
case result do
{:ok, _setting} ->
socket =
socket
|> assign(:email_ses_events, new_ses_events)
|> put_flash(
:info,
if(new_ses_events,
do: "AWS SES events tracking enabled",
else: "AWS SES events tracking disabled"
)
)
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update AWS SES events tracking")
{:noreply, socket}
end
end
def handle_event("update_email_sampling_rate", %{"sampling_rate" => value}, socket) do
case Integer.parse(value) do
{sampling_rate, _} when sampling_rate >= 0 and sampling_rate <= 100 ->
case Emails.set_sampling_rate(sampling_rate) do
{:ok, _setting} ->
socket =
socket
|> assign(:email_sampling_rate, sampling_rate)
|> put_flash(:info, "Email sampling rate updated to #{sampling_rate}%")
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update email sampling rate")
{:noreply, socket}
end
_ ->
socket = put_flash(socket, :error, "Please enter a valid number between 0 and 100")
{:noreply, socket}
end
end
def handle_event("toggle_sqs_polling", _params, socket) do
# Toggle SQS polling
new_sqs_polling = !socket.assigns.sqs_polling_enabled
result = Emails.set_sqs_polling(new_sqs_polling)
case result do
{:ok, _setting} ->
socket =
socket
|> assign(:sqs_polling_enabled, new_sqs_polling)
|> put_flash(
:info,
if(new_sqs_polling,
do: "SQS polling enabled",
else: "SQS polling disabled"
)
)
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update SQS polling setting")
{:noreply, socket}
end
end
def handle_event("update_email_retention", %{"retention_days" => value}, socket) do
case Integer.parse(value) do
{retention_days, _} when retention_days > 0 and retention_days <= 365 ->
case Emails.set_retention_days(retention_days) do
{:ok, _setting} ->
socket =
socket
|> assign(:email_retention_days, retention_days)
|> put_flash(:info, "Email retention period updated to #{retention_days} days")
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update email retention period")
{:noreply, socket}
end
_ ->
socket = put_flash(socket, :error, "Please enter a valid number between 1 and 365")
{:noreply, socket}
end
end
def handle_event("update_compress_days", %{"compress_days" => value}, socket) do
case Integer.parse(value) do
{compress_days, _} when compress_days >= 7 and compress_days <= 365 ->
case Emails.set_compress_after_days(compress_days) do
{:ok, _setting} ->
socket =
socket
|> assign(:email_compress_body, compress_days)
|> put_flash(:info, "Email body compression updated to #{compress_days} days")
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update compression days")
{:noreply, socket}
end
_ ->
socket = put_flash(socket, :error, "Please enter a valid number between 7 and 365")
{:noreply, socket}
end
end
def handle_event("toggle_s3_archival", _params, socket) do
new_s3_archival = !socket.assigns.email_archive_to_s3
result = Emails.set_s3_archival(new_s3_archival)
case result do
{:ok, _setting} ->
socket =
socket
|> assign(:email_archive_to_s3, new_s3_archival)
|> put_flash(
:info,
if(new_s3_archival,
do: "S3 archival enabled",
else: "S3 archival disabled"
)
)
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update S3 archival setting")
{:noreply, socket}
end
end
def handle_event("update_max_messages", %{"max_messages" => value}, socket) do
case Integer.parse(value) do
{max_messages, _} when max_messages >= 1 and max_messages <= 10 ->
case Emails.set_sqs_max_messages(max_messages) do
{:ok, _setting} ->
socket =
socket
|> assign(:sqs_max_messages_per_poll, max_messages)
|> put_flash(:info, "SQS max messages updated to #{max_messages}")
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update SQS max messages")
{:noreply, socket}
end
_ ->
socket = put_flash(socket, :error, "Please enter a valid number between 1 and 10")
{:noreply, socket}
end
end
def handle_event("update_visibility_timeout", %{"timeout" => value}, socket) do
case Integer.parse(value) do
{timeout, _} when timeout >= 30 and timeout <= 43_200 ->
case Emails.set_sqs_visibility_timeout(timeout) do
{:ok, _setting} ->
socket =
socket
|> assign(:sqs_visibility_timeout, timeout)
|> put_flash(:info, "SQS visibility timeout updated to #{timeout} seconds")
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update SQS visibility timeout")
{:noreply, socket}
end
_ ->
socket =
put_flash(socket, :error, "Please enter a valid number between 30 and 43200 seconds")
{:noreply, socket}
end
end
def handle_event("save_aws_settings", %{"aws_settings" => aws_params}, socket) do
socket = assign(socket, :saving, true)
update_results = update_all_aws_settings(aws_params)
case Enum.all?(update_results, &match?({:ok, _}, &1)) do
true ->
new_aws_settings = build_aws_settings_map(aws_params)
socket =
socket
|> assign(:aws_settings, new_aws_settings)
|> assign(:saving, false)
|> put_flash(:info, "AWS settings saved successfully")
{:noreply, socket}
false ->
socket =
socket
|> assign(:saving, false)
|> put_flash(:error, "Failed to save AWS settings")
{:noreply, socket}
end
end
defp get_current_path(_socket, _session) do
# For Email settings page
Routes.path("/admin/settings/emails")
end
# Update all AWS settings in database
defp update_all_aws_settings(aws_params) do
[
Settings.update_setting("aws_access_key_id", aws_params["access_key_id"] || ""),
Settings.update_setting("aws_secret_access_key", aws_params["secret_access_key"] || ""),
Settings.update_setting("aws_region", aws_params["region"] || "eu-north-1"),
Settings.update_setting("aws_sqs_queue_url", aws_params["sqs_queue_url"] || ""),
Settings.update_setting("aws_sqs_dlq_url", aws_params["sqs_dlq_url"] || ""),
Settings.update_setting("aws_sqs_queue_arn", aws_params["sqs_queue_arn"] || ""),
Settings.update_setting("aws_sns_topic_arn", aws_params["sns_topic_arn"] || ""),
Settings.update_setting(
"aws_ses_configuration_set",
aws_params["ses_configuration_set"] || "phoenixkit-tracking"
),
Settings.update_setting(
"sqs_polling_interval_ms",
aws_params["sqs_polling_interval_ms"] || "5000"
)
]
end
# Build AWS settings map from params
defp build_aws_settings_map(aws_params) do
%{
access_key_id: aws_params["access_key_id"] || "",
secret_access_key: aws_params["secret_access_key"] || "",
region: aws_params["region"] || "eu-north-1",
sqs_queue_url: aws_params["sqs_queue_url"] || "",
sqs_dlq_url: aws_params["sqs_dlq_url"] || "",
sqs_queue_arn: aws_params["sqs_queue_arn"] || "",
sns_topic_arn: aws_params["sns_topic_arn"] || "",
ses_configuration_set: aws_params["ses_configuration_set"] || "phoenixkit-tracking",
sqs_polling_interval_ms: aws_params["sqs_polling_interval_ms"] || "5000"
}
end
end