Packages
phoenix_kit
1.4.1
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
Current section
Files
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
## Automatic Integration
When you run `mix phoenix_kit.install`, the following is automatically added to your
`:browser` pipeline:
plug PhoenixKitWeb.Plugs.Integration
This plug handles all PhoenixKit features including maintenance mode, and ensures
they work across your entire application
## 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
Public pages routes (if Pages module enabled):
- /pages/* (explicit prefix)
- /* (catch-all at root level)
- Example: /test2 renders test2.md
## 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
# Public pages routes (no authentication required)
get "/pages/*path", PagesController, :show
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/settings/users", Live.Settings.Users, :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/settings/maintenance",
Live.Modules.Maintenance.Settings,
: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/: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
# Pages Management
live "/admin/pages", Live.Modules.Pages.Pages, :index
live "/admin/pages/view", Live.Modules.Pages.View, :view
live "/admin/pages/edit", Live.Modules.Pages.Editor, :edit
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/settings/users", Live.Settings.Users, :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/settings/maintenance",
Live.Modules.Maintenance.Settings,
: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/: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
# Pages Management
live "/admin/pages", Live.Modules.Pages.Pages, :index
live "/admin/pages/view", Live.Modules.Pages.View, :view
live "/admin/pages/edit", Live.Modules.Pages.Editor, :edit
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
# Only runs if OAuth is enabled in settings
if Code.ensure_loaded?(PhoenixKit.Users.OAuthConfig) and
Code.ensure_loaded?(PhoenixKit.Settings) do
spawn(fn ->
# Small delay to ensure database is ready
Process.sleep(100)
try do
# Only configure if OAuth is enabled in settings
if PhoenixKit.Settings.get_boolean_setting("oauth_enabled", false) do
alias PhoenixKit.Users.OAuthConfig
OAuthConfig.configure_providers()
end
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))
# Generate root-level public pages (catch-all, placed last)
scope "/", PhoenixKitWeb do
pipe_through [:browser, :phoenix_kit_auto_setup]
# Catch-all route for public pages at root level
# This allows /test2 to render test2.md
get "/*path", PagesController, :show
end
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