Packages

phoenix_kit

1.3.0
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 integration.ex
Raw

lib/phoenix_kit_web/integration.ex

defmodule PhoenixKitWeb.Integration do
alias PhoenixKit.Module.Languages
@moduledoc """
Integration helpers for adding PhoenixKit to Phoenix applications.
## Basic Usage
Add to your router:
defmodule MyAppWeb.Router do
use MyAppWeb, :router
import PhoenixKitWeb.Integration
# Add PhoenixKit routes
phoenix_kit_routes() # Default: /phoenix_kit prefix
end
## Layout Integration
Configure parent layouts in config.exs:
config :phoenix_kit,
repo: MyApp.Repo,
layout: {MyAppWeb.Layouts, :app},
root_layout: {MyAppWeb.Layouts, :root}
## Authentication Callbacks
Use in your app's live_sessions:
- `:phoenix_kit_mount_current_scope` - Mounts user and scope (recommended)
- `:phoenix_kit_ensure_authenticated_scope` - Requires authentication
- `:phoenix_kit_redirect_if_authenticated_scope` - Redirects if logged in
## Routes Created
Authentication routes:
- /users/register, /users/log-in, /users/magic-link
- /users/settings, /users/reset-password, /users/confirm
- /users/log-out (GET/DELETE)
Admin routes (Owner/Admin only):
- /admin/dashboard, /admin/users, /admin/users/roles
- /admin/users/live_sessions, /admin/users/sessions
- /admin/settings, /admin/modules
## DaisyUI Setup
1. Install: `npm install daisyui@latest`
2. Add to tailwind.config.js:
- Content: `"../../deps/phoenix_kit"`
- Plugin: `require('daisyui')`
## Layout Templates
Use `{@inner_content}` not `render_slot(@inner_block)`:
<%!-- Correct --%>
<main>{@inner_content}</main>
## Scope Usage in Templates
<%= if PhoenixKit.Users.Auth.Scope.authenticated?(@phoenix_kit_current_scope) do %>
Welcome, {PhoenixKit.Users.Auth.Scope.user_email(@phoenix_kit_current_scope)}!
<% end %>
"""
@doc """
Creates locale-aware routing scopes based on enabled languages.
This macro generates both a localized scope (e.g., `/en/`) and a non-localized
scope for backward compatibility. The locale pattern is dynamically generated
from the database-stored enabled language codes.
## Examples
locale_scope do
live "/admin/dashboard", DashboardLive, :index
end
# Generates routes like:
# /phoenix_kit/en/admin/dashboard (with locale)
# /phoenix_kit/admin/dashboard (without locale, defaults to "en")
"""
defmacro locale_scope(opts \\ [], do: block) do
# Get URL prefix at compile time
raw_prefix =
try do
PhoenixKit.Config.get_url_prefix()
rescue
_ -> "/phoenix_kit"
end
url_prefix =
case raw_prefix do
"" -> "/"
prefix -> prefix
end
quote do
alias PhoenixKit.Module.Languages
# Get enabled locales at compile time with fallback
enabled_locales =
try do
Languages.enabled_locale_codes()
rescue
# Fallback if module not available at compile time
_ -> ["en"]
end
# Create regex pattern for enabled locales
pattern = Enum.join(enabled_locales, "|")
# Define locale validation pipeline
pipeline :phoenix_kit_locale_validation do
plug PhoenixKitWeb.Users.Auth, :phoenix_kit_validate_and_set_locale
end
# Localized scope with locale parameter
scope "#{unquote(url_prefix)}/:locale",
PhoenixKitWeb,
Keyword.put(unquote(opts), :locale, ~r/^(#{pattern})$/) do
pipe_through [:browser, :phoenix_kit_auto_setup, :phoenix_kit_locale_validation]
unquote(block)
end
# Non-localized scope for backward compatibility (defaults to "en")
scope unquote(url_prefix), PhoenixKitWeb, unquote(opts) do
pipe_through [:browser, :phoenix_kit_auto_setup, :phoenix_kit_locale_validation]
unquote(block)
end
end
end
# Helper function to generate pipeline definitions
defp generate_pipelines do
quote do
alias PhoenixKit.Module.Languages
# Define the auto-setup pipeline
pipeline :phoenix_kit_auto_setup do
plug PhoenixKitWeb.Integration, :phoenix_kit_auto_setup
end
pipeline :phoenix_kit_redirect_if_authenticated do
plug PhoenixKitWeb.Users.Auth, :phoenix_kit_redirect_if_user_is_authenticated
end
pipeline :phoenix_kit_require_authenticated do
plug PhoenixKitWeb.Users.Auth, :fetch_phoenix_kit_current_user
plug PhoenixKitWeb.Users.Auth, :phoenix_kit_require_authenticated_user
end
pipeline :phoenix_kit_admin_only do
plug PhoenixKitWeb.Users.Auth, :fetch_phoenix_kit_current_user
plug PhoenixKitWeb.Users.Auth, :fetch_phoenix_kit_current_scope
plug PhoenixKitWeb.Users.Auth, :phoenix_kit_require_admin
end
# Define locale validation pipeline
pipeline :phoenix_kit_locale_validation do
plug PhoenixKitWeb.Users.Auth, :phoenix_kit_validate_and_set_locale
end
end
end
# Helper function to generate basic scope routes
defp generate_basic_scope(url_prefix) do
quote do
scope unquote(url_prefix), PhoenixKitWeb do
pipe_through [:browser, :phoenix_kit_auto_setup]
post "/users/log-in", Users.Session, :create
delete "/users/log-out", Users.Session, :delete
get "/users/log-out", Users.Session, :get_logout
get "/users/magic-link/:token", Users.MagicLinkVerify, :verify
# OAuth routes for external provider authentication
get "/users/auth/:provider", Users.OAuth, :request
get "/users/auth/:provider/callback", Users.OAuth, :callback
# Magic Link Registration routes
get "/users/register/verify/:token", Users.MagicLinkRegistrationVerify, :verify
# Email webhook endpoint (no authentication required)
post "/webhooks/email", Controllers.EmailWebhookController, :handle
end
# Email export routes (require admin or owner role)
scope unquote(url_prefix), PhoenixKitWeb do
pipe_through [:browser, :phoenix_kit_auto_setup, :phoenix_kit_admin_only]
get "/admin/emails/export", Controllers.EmailExportController, :export_logs
get "/admin/emails/metrics/export", Controllers.EmailExportController, :export_metrics
get "/admin/emails/blocklist/export", Controllers.EmailExportController, :export_blocklist
get "/admin/emails/:id/export", Controllers.EmailExportController, :export_email_details
end
end
end
# Helper function to generate localized routes
defp generate_localized_routes(url_prefix, pattern) do
quote do
# Localized scope with locale parameter
scope "#{unquote(url_prefix)}/:locale", PhoenixKitWeb,
locale: ~r/^(#{unquote(pattern)})$/ do
pipe_through [:browser, :phoenix_kit_auto_setup, :phoenix_kit_locale_validation]
live_session :phoenix_kit_redirect_if_user_is_authenticated_locale,
on_mount: [{PhoenixKitWeb.Users.Auth, :phoenix_kit_redirect_if_authenticated_scope}] do
live "/users/register", Users.Registration, :new, as: :user_registration
live "/users/register/magic-link", Users.MagicLinkRegistrationRequest, :new,
as: :user_magic_link_registration_request
live "/users/register/complete/:token", Users.MagicLinkRegistration, :complete,
as: :user_magic_link_registration
live "/users/log-in", Users.Login, :new, as: :user_login
live "/users/magic-link", Users.MagicLink, :new, as: :user_magic_link
live "/users/reset-password", Users.ForgotPassword, :new, as: :user_reset_password
live "/users/reset-password/:token", Users.ResetPassword, :edit,
as: :user_reset_password_edit
end
live_session :phoenix_kit_current_user_locale,
on_mount: [{PhoenixKitWeb.Users.Auth, :phoenix_kit_mount_current_scope}] do
live "/users/confirm/:token", Users.Confirmation, :edit, as: :user_confirmation
live "/users/confirm", Users.ConfirmationInstructions, :new,
as: :user_confirmation_instructions
end
live_session :phoenix_kit_require_authenticated_user_locale,
on_mount: [{PhoenixKitWeb.Users.Auth, :phoenix_kit_ensure_authenticated_scope}] do
live "/users/settings", Users.Settings, :edit, as: :user_settings
live "/users/settings/confirm-email/:token", Users.Settings, :confirm_email,
as: :user_settings_confirm_email
end
live_session :phoenix_kit_admin_locale,
on_mount: [{PhoenixKitWeb.Users.Auth, :phoenix_kit_ensure_admin}] do
live "/admin/dashboard", Live.Dashboard, :index
live "/admin", Live.Dashboard, :index
live "/admin/users", Live.Users.Users, :index
live "/admin/users/new", Users.UserForm, :new, as: :user_form
live "/admin/users/edit/:id", Users.UserForm, :edit, as: :user_form_edit
live "/admin/users/roles", Live.Users.Roles, :index
live "/admin/users/live_sessions", Live.Users.LiveSessions, :index
live "/admin/users/sessions", Live.Users.Sessions, :index
live "/admin/settings", Live.Settings, :index
live "/admin/modules", Live.Modules, :index
live "/admin/settings/referral-codes", Live.Modules.ReferralCodes, :index
live "/admin/settings/email-tracking", Live.Modules.Emails.EmailTracking, :index
live "/admin/settings/languages", Live.Modules.Languages, :index
live "/admin/users/referral-codes", Live.Users.ReferralCodes, :index
live "/admin/users/referral-codes/new", Live.Users.ReferralCodeForm, :new
live "/admin/users/referral-codes/edit/:id", Live.Users.ReferralCodeForm, :edit
live "/admin/emails/dashboard", Live.Modules.Emails.Metrics, :index
live "/admin/emails", Live.Modules.Emails.Emails, :index
live "/admin/emails/email/:id", Live.Modules.Emails.Details, :show
live "/admin/emails/queue", Live.Modules.Emails.Queue, :index
live "/admin/emails/blocklist", Live.Modules.Emails.Blocklist, :index
# Entities Management
live "/admin/entities", Live.Modules.Entities.Entities, :index, as: :entities
live "/admin/entities/new", Live.Modules.Entities.EntityForm, :new, as: :entities_new
live "/admin/entities/:id/edit", Live.Modules.Entities.EntityForm, :edit,
as: :entities_edit
live "/admin/entities/data", Live.Modules.Entities.DataNavigator, :index,
as: :entities_data
live "/admin/entities/:entity_slug/data", Live.Modules.Entities.DataNavigator, :entity,
as: :entities_data_entity
live "/admin/entities/:entity_slug/data/new", Live.Modules.Entities.DataForm, :new,
as: :entities_data_new
live "/admin/entities/:entity_slug/data/:id", Live.Modules.Entities.DataForm, :show,
as: :entities_data_show
live "/admin/entities/:entity_slug/data/:id/edit",
Live.Modules.Entities.DataForm,
:edit,
as: :entities_data_edit
live "/admin/settings/entities", Live.Modules.Entities.EntitiesSettings, :index,
as: :entities_settings
end
end
end
end
# Helper function to generate non-localized routes
defp generate_non_localized_routes(url_prefix) do
quote do
# Non-localized scope for backward compatibility (defaults to "en")
scope unquote(url_prefix), PhoenixKitWeb do
pipe_through [:browser, :phoenix_kit_auto_setup, :phoenix_kit_locale_validation]
live_session :phoenix_kit_redirect_if_user_is_authenticated,
on_mount: [{PhoenixKitWeb.Users.Auth, :phoenix_kit_redirect_if_authenticated_scope}] do
live "/users/register", Users.Registration, :new, as: :user_registration
live "/users/register/magic-link", Users.MagicLinkRegistrationRequest, :new,
as: :user_magic_link_registration_request
live "/users/register/complete/:token", Users.MagicLinkRegistration, :complete,
as: :user_magic_link_registration
live "/users/log-in", Users.Login, :new, as: :user_login
live "/users/magic-link", Users.MagicLink, :new, as: :user_magic_link
live "/users/reset-password", Users.ForgotPassword, :new, as: :user_reset_password
live "/users/reset-password/:token", Users.ResetPassword, :edit,
as: :user_reset_password_edit
end
live_session :phoenix_kit_current_user,
on_mount: [{PhoenixKitWeb.Users.Auth, :phoenix_kit_mount_current_scope}] do
live "/users/confirm/:token", Users.Confirmation, :edit, as: :user_confirmation
live "/users/confirm", Users.ConfirmationInstructions, :new,
as: :user_confirmation_instructions
end
live_session :phoenix_kit_require_authenticated_user,
on_mount: [{PhoenixKitWeb.Users.Auth, :phoenix_kit_ensure_authenticated_scope}] do
live "/users/settings", Users.Settings, :edit, as: :user_settings
live "/users/settings/confirm-email/:token", Users.Settings, :confirm_email,
as: :user_settings_confirm_email
end
live_session :phoenix_kit_admin,
on_mount: [{PhoenixKitWeb.Users.Auth, :phoenix_kit_ensure_admin}] do
live "/admin/dashboard", Live.Dashboard, :index
live "/admin", Live.Dashboard, :index
live "/admin/users", Live.Users.Users, :index
live "/admin/users/new", Users.UserForm, :new, as: :user_form
live "/admin/users/edit/:id", Users.UserForm, :edit, as: :user_form_edit
live "/admin/users/roles", Live.Users.Roles, :index
live "/admin/users/live_sessions", Live.Users.LiveSessions, :index
live "/admin/users/sessions", Live.Users.Sessions, :index
live "/admin/settings", Live.Settings, :index
live "/admin/modules", Live.Modules, :index
live "/admin/settings/referral-codes", Live.Modules.ReferralCodes, :index
live "/admin/settings/emails", Live.Modules.Emails.Settings, :index
live "/admin/settings/languages", Live.Modules.Languages, :index
live "/admin/users/referral-codes", Live.Users.ReferralCodes, :index
live "/admin/users/referral-codes/new", Live.Users.ReferralCodeForm, :new
live "/admin/users/referral-codes/edit/:id", Live.Users.ReferralCodeForm, :edit
live "/admin/emails/dashboard", Live.Modules.Emails.Metrics, :index
live "/admin/emails", Live.Modules.Emails.Emails, :index
live "/admin/emails/email/:id", Live.Modules.Emails.Details, :show
live "/admin/emails/queue", Live.Modules.Emails.Queue, :index
live "/admin/emails/blocklist", Live.Modules.Emails.Blocklist, :index
# Email Templates Management
live "/admin/modules/emails/templates", Live.Modules.Emails.Templates, :index
live "/admin/modules/emails/templates/new", Live.Modules.Emails.TemplateEditor, :new
live "/admin/modules/emails/templates/:id/edit",
Live.Modules.Emails.TemplateEditor,
:edit
# Entities Management
live "/admin/entities", Live.Modules.Entities.Entities, :index, as: :entities
live "/admin/entities/new", Live.Modules.Entities.EntityForm, :new, as: :entities_new
live "/admin/entities/:id/edit", Live.Modules.Entities.EntityForm, :edit,
as: :entities_edit
live "/admin/entities/data", Live.Modules.Entities.DataNavigator, :index,
as: :entities_data
live "/admin/entities/:entity_slug/data", Live.Modules.Entities.DataNavigator, :entity,
as: :entities_data_entity
live "/admin/entities/:entity_slug/data/new", Live.Modules.Entities.DataForm, :new,
as: :entities_data_new
live "/admin/entities/:entity_slug/data/:id", Live.Modules.Entities.DataForm, :show,
as: :entities_data_show
live "/admin/entities/:entity_slug/data/:id/edit",
Live.Modules.Entities.DataForm,
:edit,
as: :entities_data_edit
live "/admin/settings/entities", Live.Modules.Entities.EntitiesSettings, :index,
as: :entities_settings
end
end
end
end
defmacro phoenix_kit_routes do
# Initialize OAuth configuration from database on router setup
# This ensures OAuth providers are configured before any requests
if Code.ensure_loaded?(PhoenixKit.Users.OAuthConfig) do
spawn(fn ->
# Small delay to ensure database is ready
Process.sleep(100)
try do
alias PhoenixKit.Users.OAuthConfig
OAuthConfig.configure_providers()
rescue
error ->
require Logger
Logger.debug("OAuth config initialization skipped: #{inspect(error)}")
end
end)
end
# Get URL prefix at compile time and handle empty string case for router compatibility
raw_prefix =
try do
PhoenixKit.Config.get_url_prefix()
rescue
# Fallback if config not available at compile time
_ -> "/phoenix_kit"
end
url_prefix =
case raw_prefix do
"" -> "/"
prefix -> prefix
end
# Get enabled locales at compile time with fallback
enabled_locales =
try do
Languages.enabled_locale_codes()
rescue
# Fallback if module not available at compile time
_ -> ["en"]
end
# Create regex pattern for enabled locales
pattern = Enum.join(enabled_locales, "|")
quote do
# Generate pipeline definitions
unquote(generate_pipelines())
# Generate basic routes scope
unquote(generate_basic_scope(url_prefix))
# Generate localized routes
unquote(generate_localized_routes(url_prefix, pattern))
# Generate non-localized routes
unquote(generate_non_localized_routes(url_prefix))
end
end
def init(opts) do
opts
end
def call(conn, :phoenix_kit_auto_setup) do
# Add backward compatibility for layouts that use render_slot(@inner_block)
Plug.Conn.assign(conn, :inner_block, [])
end
end