- Full auth system with email/password (using phx.gen.auth) - Login, registration, password reset - Session management with remember-me functionality - Magic link login support 2. Organization Management - Multi-tenant organization system - Organizations schema with unique slugs - Automatic organization creation when users register - Organization switcher UI at /orgs 3. Membership System - Users can belong to multiple organizations - 4 permission levels: Owner, Admin, Member, Viewer - Complete permission matrix implemented - Join/leave organizations 4. Invitation System - Email-based invitations with secure tokens - 7-day expiration on invites - Track who invited and who accepted 5. Authorization - Full policy system (Organizations.Policy) - can?(membership, :action, :resource) helper - Enforced via plugs in router 6. LiveView Pages - /orgs - List all your organizations - /orgs/new - Create new organization - /orgs/:slug - Organization dashboard (placeholder) 7. Database Schema - users table - organizations table - organization_memberships table - organization_invitations table - All migrations run successfully
59 lines
1.8 KiB
Text
59 lines
1.8 KiB
Text
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
|
<div class="mx-auto max-w-sm">
|
|
<div class="text-center">
|
|
<.header>Welcome {@user.email}</.header>
|
|
</div>
|
|
|
|
<.form
|
|
:if={!@user.confirmed_at}
|
|
for={@form}
|
|
id="confirmation_form"
|
|
action={~p"/users/log-in?_action=confirmed"}
|
|
phx-mounted={JS.focus_first()}
|
|
>
|
|
<input type="hidden" name={@form[:token].name} value={@form[:token].value} />
|
|
<.button
|
|
name={@form[:remember_me].name}
|
|
value="true"
|
|
phx-disable-with="Confirming..."
|
|
class="btn btn-primary w-full"
|
|
>
|
|
Confirm and stay logged in
|
|
</.button>
|
|
<.button phx-disable-with="Confirming..." class="btn btn-primary btn-soft w-full mt-2">
|
|
Confirm and log in only this time
|
|
</.button>
|
|
</.form>
|
|
|
|
<.form
|
|
:if={@user.confirmed_at}
|
|
for={@form}
|
|
id="login_form"
|
|
action={~p"/users/log-in"}
|
|
phx-mounted={JS.focus_first()}
|
|
>
|
|
<input type="hidden" name={@form[:token].name} value={@form[:token].value} />
|
|
<%= if @current_scope do %>
|
|
<.button variant="primary" phx-disable-with="Logging in..." class="btn btn-primary w-full">
|
|
Log in
|
|
</.button>
|
|
<% else %>
|
|
<.button
|
|
name={@form[:remember_me].name}
|
|
value="true"
|
|
phx-disable-with="Logging in..."
|
|
class="btn btn-primary w-full"
|
|
>
|
|
Keep me logged in on this device
|
|
</.button>
|
|
<.button phx-disable-with="Logging in..." class="btn btn-primary btn-soft w-full mt-2">
|
|
Log me in only this time
|
|
</.button>
|
|
<% end %>
|
|
</.form>
|
|
|
|
<p :if={!@user.confirmed_at} class="alert alert-outline mt-8">
|
|
Tip: If you prefer passwords, you can enable them in the user settings.
|
|
</p>
|
|
</div>
|
|
</Layouts.app>
|