When creating a new Lucky project you can choose to generate files for authentication with email and password.
If you have an API only Lucky app, Lucky will generate operations, models, mixins, and actions for signing up and authenticating with an auth token (JWT).
If you have a full Lucky app you will still get API auth, but also actions and pages for signing in, signing out, and resetting your password through the browser.
There are in depth guides on authentication with HTML pages and APIs, but here are some quick examples of working with the signed in user.
To get the currently signed in user, call current_user
in your actions.
If your action requires sign in, current_user
will always return a User
and never nil
. If sign in is
optional
then current_user
may be nil
.
In HTML pages using the MainLayout
you can get the signed in user with
@current_user
.
If the current user might be nil
by
allowing guests
or skipping the auth token
you need to use a conditional before using current_user
class Hello::Show < BrowserAction
# This will allow users that are not signed in
include Auth::AllowGuests
get "/hello" do
user = current_user
# Check if user is signed in
if user
plain_text "Hello #{user.name}"
else
plain_text "Hello!"
end
end
end
This works because Crystal will ensure a variable isn’t nil when you use
an if
statement. Read more about how Crystal handles if
here
Let’s say we have an Article
model with a title : String
and belongs_to author : User
.
To create the article and associate it the signed in user, do this:
class Articles::Create < BrowserAction
post "/articles" do
# Set 'author_id' to the current_user's id
SaveArticle.create!(params, author_id: current_user.id) do |op, article|
# ...
end
end
end
If we only want to return articles for the signed in user. We can do it like this:
class MyArticles::Index < BrowserAction
get "/articles" do
# Filter articles by 'author_id'
articles = ArticleQuery.new.author_id(current_user.id)
html MyArticles::IndexPage, articles: articles
end
end
These are the files generated with lucky init
with auth.
src/actions/browser_action.cr
- includes mixins for checking sign in, getting current user, and signing users in using cookies.src/actions/home/index.cr
- redirects users based on whether signed in/out.src/actions/me/show.cr
- the current user’s profile.src/actions/sign_ins/*
src/actions/sign_ups/*
src/actions/sign_outs/*
src/actions/password_resets/*
src/actions/password_reset_requests/*
src/actions/mixins/auth/*
- mixins for requiring sign in, skipping sign in, etc.src/actions/mixins/password_resets/*
- mixins for working with password resets.src/actions/mixins/api/auth/*
- mixins for checking sign in, getting current user, and signing users in with a token.src/actions/api_action.cr
- includes mixins for token auth.src/actions/api/sign_ins/*
- generate a token for the user.src/actions/api/sign_ups/*
src/actions/api/me/show.cr
- the currently signed in user as JSON.src/operations/mixins/password_validations.cr
- mixin used in the SignUpUser
and ResetPassword
so password validations are the same in both.src/operations/sign_up_user.cr
src/operations/sign_in_user.cr
src/operations/request_password_reset.cr
- not in API only apps.src/operations/reset_password.cr
- not in API only apps.src/serializers/user_serializer.cr
src/pages/main_layout.cr
- this layout requires a sign in user.src/pages/auth_layout.cr
- this layout is used by the auth pages (sign
in, sign up, password reset) and does not require or have access to the current_user
.src/pages/sign_ups/*
src/pages/sign_ins/*
src/pages/request_password_resets/*
src/pages/password_resets/*
src/pages/me/show_page.cr
db/migrations/00000000000001_create_users.cr
- create the initial users tablesrc/models/user.cr
src/queries/user_query.cr