revise_auth-jets 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +32 -0
  4. data/Rakefile +18 -0
  5. data/app/config/routes.rb +31 -0
  6. data/app/controllers/main_controller.rb +9 -0
  7. data/app/controllers/revise_auth/email_controller.rb +28 -0
  8. data/app/controllers/revise_auth/password_controller.rb +24 -0
  9. data/app/controllers/revise_auth/registrations_controller.rb +44 -0
  10. data/app/controllers/revise_auth/sessions_controller.rb +19 -0
  11. data/app/controllers/revise_auth_controller.rb +12 -0
  12. data/app/mailers/revise_auth/mailer.rb +8 -0
  13. data/app/views/main/authenticated.html.erb +16 -0
  14. data/app/views/main/index.html.erb +15 -0
  15. data/app/views/revise_auth/mailer/confirm_email.html.erb +7 -0
  16. data/app/views/revise_auth/registrations/edit.html.erb +71 -0
  17. data/app/views/revise_auth/registrations/new.html.erb +30 -0
  18. data/app/views/revise_auth/sessions/new.html.erb +17 -0
  19. data/config/locales/de.yml +16 -0
  20. data/config/locales/el.yml +16 -0
  21. data/config/locales/en.yml +16 -0
  22. data/config/locales/fr.yml +16 -0
  23. data/config/locales/nl.yml +16 -0
  24. data/config/locales/tr.yml +16 -0
  25. data/config/locales/zh-TW.yml +16 -0
  26. data/lib/generators/revise_auth/model_generator.rb +64 -0
  27. data/lib/generators/revise_auth/templates/README +5 -0
  28. data/lib/generators/revise_auth/views_generator.rb +38 -0
  29. data/lib/revise_auth/authentication.rb +64 -0
  30. data/lib/revise_auth/backports.rb +24 -0
  31. data/lib/revise_auth/current.rb +6 -0
  32. data/lib/revise_auth/engine.rb +18 -0
  33. data/lib/revise_auth/model.rb +37 -0
  34. data/lib/revise_auth/route_constraint.rb +15 -0
  35. data/lib/revise_auth/routes.rb +49 -0
  36. data/lib/revise_auth/version.rb +3 -0
  37. data/lib/revise_auth.rb +11 -0
  38. data/lib/tasks/revise_auth_tasks.rake +4 -0
  39. metadata +97 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 867f8d44bffd162dfeb8d75ed9c55b7b7afb687c655f8523bd5413ba76bcd8cd
4
+ data.tar.gz: c5ba8737f091102a67ca738593446ed3d238859b1ca365dc077ebc7c857a767f
5
+ SHA512:
6
+ metadata.gz: db195a90a24feb5d13c96d48f441c16fe8fe1569f1f8e478e9010601be8dbc9e98f590905b77642f47319af0f3e57f303307d7893c991f6bd73f1fcd527167ab
7
+ data.tar.gz: 550ba5cea3dce8912526a108dfc1f883647dc86cf52a7ba5d638a07c3fcd895ad15f863b9b22dbda5f6f513d9634e027976f294f514b942fde1808a7b30eaf27
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2023 Chris Oliver
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # ReviseAuth
2
+
3
+ A pure Ruby on Jets authentication system like Devise.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ bundle add "revise_auth"
11
+ ```
12
+
13
+ And then execute the following to generate a `User` model (optionally adding other fields such as `first_name` and `last_name`):
14
+ ```bash
15
+ $ jetsg revise_auth:model User first_name last_name
16
+ $ jets db:migrate
17
+ $ jetsg revise_auth:views
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ReviseAuth is designed around a single `User` model.
23
+
24
+ ### Roles / Other User Types
25
+
26
+ ReviseAuth only works with a single model to keep things simple. We recommend adding roles to handle other types of users.
27
+
28
+ You can accomplish this in a few different ways:
29
+
30
+ * A `roles` attribute on the `User` model
31
+ * The Rolify gem
32
+
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require "bundler/setup"
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
6
+ load "rails/tasks/engine.rake"
7
+ load "rails/tasks/statistics.rake"
8
+
9
+ desc "Run tests"
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.libs << "lib"
12
+ t.libs << "test"
13
+ t.pattern = "test/**/*_test.rb"
14
+ t.verbose = true
15
+ t.warning = false
16
+ end
17
+
18
+ task default: :test
@@ -0,0 +1,31 @@
1
+ Jets.application.routes.draw do
2
+ root "main#index"
3
+
4
+ get "authenticated", to: "main#authenticated", as: :authenticated
5
+
6
+ scope module: :revise_auth do
7
+
8
+ get "sign_up", to: "registrations#new", as: :sign_up
9
+ post "sign_up", to: "registrations#create"
10
+ get "login", to: "sessions#new", as: :login
11
+ post "login", to: "sessions#create"
12
+
13
+ get "profile", to: "registrations#edit", as: :profile
14
+ patch "profile", to: "registrations#update"
15
+ delete "profile", to: "registrations#destroy"
16
+ patch "profile/email", to: "email#update"
17
+ get "profile/password", to: "registrations#edit", as: :profile_password
18
+ patch "profile/password", to: "password#update"
19
+
20
+ # Email confirmation
21
+ get "profile/email", to: "email#show", as: :profile_email
22
+
23
+ delete "logout", to: "sessions#delete"
24
+ end
25
+
26
+ # The jets/public#show controller can serve static utf8 content out of the public folder.
27
+ # Note, as part of the deploy process Jets uploads files in the public folder to s3
28
+ # and serves them out of s3 directly. S3 is well suited to serve static assets.
29
+ # More info here: https://rubyonjets.com/docs/extras/assets-serving/
30
+ any "*catchall", to: "jets/public#show"
31
+ end
@@ -0,0 +1,9 @@
1
+ class MainController < ReviseAuthController
2
+ before_action :authenticate_user!, only: [:authenticated]
3
+
4
+ def index
5
+ end
6
+
7
+ def authenticated
8
+ end
9
+ end
@@ -0,0 +1,28 @@
1
+ class ReviseAuth::EmailController < ReviseAuthController
2
+ before_action :authenticate_user!, except: [:show]
3
+
4
+ # GET /profile/email?confirmation_token=abcdef
5
+ def show
6
+ if User.find_by_token_for(:email_verification, params[:confirmation_token])&.confirm_email_change
7
+ #flash[:notice] = I18n.t("revise_auth.email_confirmed")
8
+ redirect_to(user_signed_in? ? profile_path : root_path)
9
+ else
10
+ redirect_to root_path, alert: I18n.t("revise_auth.email_confirm_failed")
11
+ end
12
+ end
13
+
14
+ def update
15
+ if current_user.update(email_params)
16
+ current_user.send_confirmation_instructions
17
+ #flash[:notice] = I18n.t("revise_auth.confirmation_email_sent", email: current_user.unconfirmed_email)
18
+ end
19
+
20
+ redirect_to profile_path
21
+ end
22
+
23
+ private
24
+
25
+ def email_params
26
+ params.require(:user).permit(:unconfirmed_email)
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ class ReviseAuth::PasswordController < ReviseAuthController
2
+ before_action :validate_current_password, only: [:update]
3
+
4
+ def update
5
+ if current_user.update(password_params)
6
+ #flash[:notice] = I18n.t("revise_auth.password_changed")
7
+ end
8
+
9
+ redirect_to profile_path
10
+ end
11
+
12
+ private
13
+
14
+ def password_params
15
+ params.require(:user).permit(:password, :password_confirmation)
16
+ end
17
+
18
+ def validate_current_password
19
+ unless current_user.authenticate(params[:current_password])
20
+ #flash[:alert] = I18n.t("revise_auth.incorrect_password")
21
+ render "revise_auth/registrations/edit", status: :unprocessable_entity
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,44 @@
1
+ class ReviseAuth::RegistrationsController < ReviseAuthController
2
+ before_action :authenticate_user!, except: [:new, :create]
3
+
4
+ def new
5
+ @user = User.new
6
+ end
7
+
8
+ def create
9
+ @user = User.new(sign_up_params)
10
+ if @user.save
11
+ login(@user)
12
+ redirect_to root_path
13
+ else
14
+ render :new, status: :unprocessable_entity
15
+ end
16
+ end
17
+
18
+ def edit
19
+ end
20
+
21
+ def update
22
+ if current_user.update(profile_params)
23
+ redirect_to profile_path, notice: I18n.t("revise_auth.account_updated")
24
+ else
25
+ render :edit, status: :unprocessable_entity
26
+ end
27
+ end
28
+
29
+ def destroy
30
+ current_user.destroy
31
+ logout
32
+ redirect_to root_path, status: :see_other, alert: I18n.t("revise_auth.account_deleted")
33
+ end
34
+
35
+ private
36
+
37
+ def sign_up_params
38
+ params.require(:user).permit(:name, :email, :password, :password_confirmation)
39
+ end
40
+
41
+ def profile_params
42
+ params.require(:user).permit(:name)
43
+ end
44
+ end
@@ -0,0 +1,19 @@
1
+ class ReviseAuth::SessionsController < ReviseAuthController
2
+ def new
3
+ end
4
+
5
+ def create
6
+ if (user = User.authenticate_by(email: params[:email], password: params[:password]))
7
+ login(user)
8
+ redirect_to root_path
9
+ else
10
+ #flash[:alert] = I18n.t("revise_auth.invalid_email_or_password")
11
+ render :new, status: :unprocessable_entity
12
+ end
13
+ end
14
+
15
+ def delete
16
+ logout
17
+ redirect_back(fallback_location: root_path)
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ require 'revise_auth'
2
+ class ReviseAuthController < ApplicationController
3
+ # Return true if it's a revise_auth_controller. false to all controllers unless
4
+ # the controllers defined inside revise_auth. Useful if you want to apply a before
5
+ # filter to all controllers, except the ones in revise_auth:
6
+ #
7
+ # before_action :authenticate_user!, except: :revise_auth_controller?
8
+ include ReviseAuth::Authentication
9
+ def revise_auth_controller?
10
+ is_a?(::ReviseAuthController)
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ class ReviseAuth::Mailer < ApplicationMailer
2
+ def confirm_email
3
+ @user = params[:user]
4
+ @token = params[:token]
5
+
6
+ mail to: @user.unconfirmed_email
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ <nav>
2
+ <%= link_to "Home", root_path %>
3
+
4
+ <% if user_signed_in? %>
5
+ <%= link_to "Profile", profile_path %>
6
+ <%= button_to "Log out", 'logout', method: :delete %>
7
+ <% else %>
8
+ <%= link_to "Sign Up", sign_up_path %>
9
+ <%= link_to "Log in", login_path %>
10
+ <% end %>
11
+ </nav>
12
+
13
+ <h1>Authenticated Route</h1>
14
+
15
+ <p>You can only access this route when authenticated.</p>
16
+ <p>Authenticated as <%= current_user.email %></p>
@@ -0,0 +1,15 @@
1
+ <h1>Revise Auth</h1>
2
+ <nav>
3
+ <%= link_to "Home", root_path %>
4
+
5
+ <% if user_signed_in? %>
6
+ <%= link_to "Profile", profile_path %>
7
+ <%= button_to "Log out", 'logout', method: :delete %>
8
+ <% else %>
9
+ <%= link_to "Sign Up", sign_up_path %>
10
+ <%= link_to "Log in", login_path %>
11
+ <% end %>
12
+ </nav>
13
+ <div>
14
+ <%= link_to "Authentication Required", authenticated_path %>
15
+ </div>
@@ -0,0 +1,7 @@
1
+ <p>Welcome <%= @user.unconfirmed_email %>!</p>
2
+
3
+ <p>You can confirm your account email through the link below:</p>
4
+
5
+ <p><%= link_to "Confirm my account", profile_email_url(confirmation_token: @token) %></p>
6
+
7
+ <p>This link will expire in 24 hours.</p>
@@ -0,0 +1,71 @@
1
+ <h1>Profile</h1>
2
+
3
+ <%= form_with model: current_user, url: profile_email_path do |form| %>
4
+ <fieldset>
5
+ <legend>Change Email Address</legend>
6
+
7
+ <% if current_user.unconfirmed_email? %>
8
+ <p>Waiting for confirmation of <%= current_user.unconfirmed_email %></p>
9
+ <% end %>
10
+
11
+ <% if form.object.errors.any? %>
12
+ <ul>
13
+ <% form.object.errors.full_messages.each do |message| %>
14
+ <li><%= message %></li>
15
+ <% end %>
16
+ </ul>
17
+ <% end %>
18
+
19
+ <p>Your email address is: <%= current_user.email %>
20
+ <p>To change your email, we will send a confirmation email to your new address to complete the change.</p>
21
+
22
+ <div>
23
+ <%= form.label :unconfirmed_email, "Email address" %>
24
+ <%= form.email_field :unconfirmed_email, required: true %>
25
+ </div>
26
+
27
+ <div>
28
+ <%= form.button "Save Changes" %>
29
+ </div>
30
+ </fieldset>
31
+ <% end %>
32
+
33
+ <%= form_with model: current_user, url: profile_password_path do |form| %>
34
+ <fieldset>
35
+ <legend>Change Password</legend>
36
+
37
+ <% if form.object.errors.any? %>
38
+ <ul>
39
+ <% form.object.errors.full_messages.each do |message| %>
40
+ <li><%= message %></li>
41
+ <% end %>
42
+ </ul>
43
+ <% end %>
44
+
45
+ <div>
46
+ <%= label_tag :current_password %>
47
+ <%= password_field_tag :current_password, nil, required: true %>
48
+ </div>
49
+
50
+ <div>
51
+ <%= form.label :password, "New password" %>
52
+ <%= form.password_field :password, required: true %>
53
+ </div>
54
+
55
+ <div>
56
+ <%= form.label :password_confirmation %>
57
+ <%= form.password_field :password_confirmation, required: true %>
58
+ </div>
59
+
60
+ <div>
61
+ <%= form.button "Save Changes" %>
62
+ </div>
63
+ </fieldset>
64
+ <% end %>
65
+
66
+ <%= form_with url: profile_path, method: :delete do |form| %>
67
+ <fieldset>
68
+ <legend>Delete my account</legend>
69
+ <%= form.button "Delete account", data: { turbo_confirm: "Are you sure?" } %>
70
+ </fieldset>
71
+ <% end %>
@@ -0,0 +1,30 @@
1
+ <h1>Sign Up</h1>
2
+
3
+ <%= form_with local: true, model: @user, url: sign_up_path do |form| %>
4
+ <% if form.object.errors.any? %>
5
+ <ul>
6
+ <% form.object.errors.full_messages.each do |message| %>
7
+ <li><%= message %></li>
8
+ <% end %>
9
+ </ul>
10
+ <% end %>
11
+
12
+ <div>
13
+ <%= form.label :email %>
14
+ <%= form.email_field :email, required: true, autofocus: true %>
15
+ </div>
16
+
17
+ <div>
18
+ <%= form.label :password %>
19
+ <%= form.password_field :password, required: true %>
20
+ </div>
21
+
22
+ <div>
23
+ <%= form.label :password_confirmation %>
24
+ <%= form.password_field :password_confirmation, required: true %>
25
+ </div>
26
+
27
+ <div>
28
+ <%= form.button "Sign Up" %>
29
+ </div>
30
+ <% end %>
@@ -0,0 +1,17 @@
1
+ <h1>Log in</h1>
2
+
3
+ <%= form_with(url: login_path, local: true) do |form| %>
4
+ <div>
5
+ <%= form.label :email %>
6
+ <%= form.email_field :email, required: true, autofocus: true %>
7
+ </div>
8
+
9
+ <div>
10
+ <%= form.label :password %>
11
+ <%= form.password_field :password, required: true %>
12
+ </div>
13
+
14
+ <div>
15
+ <%= form.button "Login" %>
16
+ </div>
17
+ <% end %>
@@ -0,0 +1,16 @@
1
+ de:
2
+ revise_auth:
3
+ account_deleted: "Dein Account wurde gelöscht."
4
+ account_updated: "Account wurde erfolgreich aktualisiert."
5
+
6
+ invalid_email_or_password: "Ungültige Email oder Passwort."
7
+ sign_up_or_login: "Registrieren oder anmelden um fortzufahren."
8
+
9
+ # Password changes
10
+ password_changed: "Dein Passwort wurde erfolgreich geändert."
11
+ incorrect_password: "Das Passwort ist ungültig. Bitte versuche es erneut."
12
+
13
+ # Email confirmations
14
+ email_confirmed: "Deine Email wurde erfogreich bestätigt."
15
+ email_confirm_failed: "Email Adresse kann nicht bestätigt werden."
16
+ confirmation_email_sent: "Eine Bestätigungsemail wurde versandt an %{email}"
@@ -0,0 +1,16 @@
1
+ el:
2
+ revise_auth:
3
+ account_deleted: "Ο λογαριασμός σας έχει διαγραφεί."
4
+ account_updated: "Ο λογαριασμός σας έχει ενημερωθεί επιτυχώς."
5
+
6
+ invalid_email_or_password: "Μη έγκυρο email ή κωδικός πρόσβασης."
7
+ sign_up_or_login: "Εγγραφείτε ή συνδεθείτε για να συνεχίσετε."
8
+
9
+ # Password changes
10
+ password_changed: "Ο κωδικός πρόσβασής σας άλλαξε με επιτυχία."
11
+ incorrect_password: "Ο τρέχων κωδικός πρόσβασής σας είναι λανθασμένος. Παρακαλώ δοκιμάστε ξανά."
12
+
13
+ # Email confirmations
14
+ email_confirmed: "Η διεύθυνση email σας επιβεβαιώθηκε επιτυχώς."
15
+ email_confirm_failed: "Δεν είναι δυνατή η επιβεβαίωση της διεύθυνσης email."
16
+ confirmation_email_sent: "Ένα email επιβεβαίωσης έχει σταλεί στο %{email}"
@@ -0,0 +1,16 @@
1
+ en:
2
+ revise_auth:
3
+ account_deleted: "Your account has been deleted."
4
+ account_updated: "Account updated successfully."
5
+
6
+ invalid_email_or_password: "Invalid email or password."
7
+ sign_up_or_login: "Sign up or log in to continue."
8
+
9
+ # Password changes
10
+ password_changed: "Your password has been changed successfully."
11
+ incorrect_password: "Your current password is incorrect. Please try again."
12
+
13
+ # Email confirmations
14
+ email_confirmed: "Your email address has been successfully confirmed."
15
+ email_confirm_failed: "Unable to confirm email address."
16
+ confirmation_email_sent: "A confirmation email has been sent to %{email}"
@@ -0,0 +1,16 @@
1
+ fr:
2
+ revise_auth:
3
+ account_deleted: "Votre compte a été supprimé."
4
+ account_updated: "Votre compte a été mis à jour."
5
+
6
+ invalid_email_or_password: "Email ou mot de passe incorrect."
7
+ sign_up_or_login: "Vous devez être connecté ou vous enregistrer pour continuer."
8
+
9
+ # Password changes
10
+ password_changed: "Votre mot de passe a été mis à jour avec succès."
11
+ incorrect_password: "Mot de passe incorrect. Merci de réessayer"
12
+
13
+ # Email confirmations
14
+ email_confirmed: "Votre adresse email vient d'être confirmé."
15
+ email_confirm_failed: "Impossible de confirmer votre adresse email."
16
+ confirmation_email_sent: "Un email de confirmation vient d'être envoyé à %{email}"
@@ -0,0 +1,16 @@
1
+ nl:
2
+ revise_auth:
3
+ account_deleted: "Uw account is verwijderd."
4
+ account_updated: "Account succesvol bijgewerkt."
5
+
6
+ invalid_email_of_password: "Ongeldige e-mail of wachtwoord."
7
+ sign_up_or_login: "Aanmelden of inloggen om door te gaan."
8
+
9
+ # Password changes
10
+ password_changed: "Uw wachtwoord is succesvol gewijzigd."
11
+ incorrect_password: "Uw huidige wachtwoord is onjuist. Probeer het opnieuw."
12
+
13
+ # E-mail confirmations
14
+ email_confirmed: "Uw e-mailadres is succesvol bevestigd."
15
+ email_confirm_failed: "E-mailadres bevestigen niet mogelijk."
16
+ confirmation_email_sent: "Er is een bevestigingsmail verzonden naar %{email}"
@@ -0,0 +1,16 @@
1
+ tr:
2
+ revise_auth:
3
+ account_deleted: "Hesabınız silindi."
4
+ account_updated: "Hesap başarıyla güncellendi."
5
+
6
+ invalid_email_or_password: "Geçersiz e-posta veya şifre."
7
+ sign_up_or_login: "Devam etmek için kaydol veya giriş yap."
8
+
9
+ # Password changes
10
+ password_changed: "Şifreniz başarıyla güncellendi."
11
+ incorrect_password: "Şu anki şifreniz yanlış. Lütfen tekrar deneyiniz."
12
+
13
+ # Email confirmations
14
+ email_confirmed: "E-posta adresiniz başarıyla onaylandı."
15
+ email_confirm_failed: "E-posta adresi doğrulanamıyor."
16
+ confirmation_email_sent: "%{email} adresine onay e-postası gönderildi."
@@ -0,0 +1,16 @@
1
+ zh-TW:
2
+ revise_auth:
3
+ account_deleted: "您的帳號已經被刪除"
4
+ account_updated: "帳號更新成功"
5
+
6
+ invalid_email_or_password: "錯誤的信箱或是密碼"
7
+ sign_up_or_login: "需要註冊或是登入才能進行"
8
+
9
+ # Password changes
10
+ password_changed: "您的密碼已經成功地更新"
11
+ incorrect_password: "您現在輸入的密碼不正確, 請重新嘗試"
12
+
13
+ # Email confirmations
14
+ email_confirmed: "您的電子信箱已經成功地通過驗證"
15
+ email_confirm_failed: "無法驗證您的電子信箱"
16
+ confirmation_email_sent: "電子信箱驗證信已寄往 %{email}"
@@ -0,0 +1,64 @@
1
+ module ReviseAuth
2
+ module Generators
3
+ class ModelGenerator < Rails::Generators::NamedBase
4
+ include Rails::Generators::ResourceHelpers
5
+
6
+ desc "Generates a model for authentication, default User"
7
+
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ argument :name, required: false, default: "User"
11
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
12
+
13
+ def initialize(args, *options)
14
+ @original_attributes = args[1..] || []
15
+ super
16
+ end
17
+
18
+ def generate_model
19
+ model_attributess = model_attributes.join(', ').gsub(':index', '').gsub(',', '')
20
+ puts "jets g model #{name} #{model_attributess}"
21
+ system "jets g model #{name} #{model_attributess}"
22
+ #generate :model, name, *model_attributes
23
+ end
24
+
25
+ def add_revise_auth_model
26
+ prepend_to_file model_path, "require 'revise_auth'\n"
27
+ inject_into_class model_path, class_name, " include ReviseAuth::Model\n"
28
+ end
29
+
30
+ def add_uniq_to_email_index
31
+ puts migration_path
32
+ puts name.downcase.pluralize
33
+ insert_into_file migration_path, after: "#{name.downcase.pluralize}, :email", force: true do
34
+ ", unique: true"
35
+ end
36
+ end
37
+
38
+ def done
39
+ readme "README" if behavior == :invoke
40
+ end
41
+
42
+ private
43
+
44
+ def migration_path
45
+ @migration_path ||= Dir.glob(Jets.root.join("db/migrate/*")).max_by { |f| File.mtime(f) }
46
+ end
47
+
48
+ def model_path
49
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
50
+ end
51
+
52
+ def model_attributes
53
+ [
54
+ "email:string:index",
55
+ "password_digest:string",
56
+ "confirmation_token:string",
57
+ "confirmed_at:datetime",
58
+ "confirmation_sent_at:datetime",
59
+ "unconfirmed_email:string"
60
+ ] + @original_attributes
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+ 🚚 Your Revise auth database model has been generated!
2
+
3
+ Next step:
4
+ Add "add_index :users, :email, unique: true" at the bottom of the change method
5
+ Run "jets db:migrate"
@@ -0,0 +1,38 @@
1
+ require "rails/generators"
2
+
3
+ module ReviseAuth
4
+ module Generators
5
+ class ViewsGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../../../..", __FILE__)
7
+
8
+ class_option :views, aliases: "-v", type: :array, desc: "Select specific view directories to generate (confirmations, passwords, registrations, sessions, unlocks, mailer)"
9
+
10
+ def copy_config
11
+ template "app/config/routes.rb", "config/routes.rb"
12
+ end
13
+
14
+ def copy_controllers
15
+ template "app/controllers/main_controller.rb", "app/controllers/main_controller.rb"
16
+ template "app/controllers/revise_auth_controller.rb", "app/controllers/revise_auth_controller.rb"
17
+ if options[:controllers]
18
+ options[:controllers].each do |directory|
19
+ directory "app/controllers/revise_auth/#{directory}"
20
+ end
21
+ else
22
+ directory "app/controllers/revise_auth"
23
+ end
24
+ end
25
+
26
+ def copy_views
27
+ if options[:views]
28
+ options[:views].each do |directory|
29
+ directory "app/views/revise_auth/#{directory}"
30
+ end
31
+ else
32
+ directory "app/views/revise_auth"
33
+ directory "app/views/main"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,64 @@
1
+ module ReviseAuth
2
+ module Authentication
3
+ # Provides methods for controllers and views for authentication
4
+ #
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ helper_method :user_signed_in?
9
+ helper_method :current_user
10
+ end
11
+
12
+ # Returns a boolean whether the user is signed in or not
13
+ def user_signed_in?
14
+ !!current_user
15
+ end
16
+
17
+ # Authenticates the user if not already authenticated
18
+ # Returns a User or nil
19
+ def current_user
20
+ Current.user ||= authenticate_user
21
+ end
22
+
23
+ # Authenticates a user or redirects to the login page
24
+ def authenticate_user!
25
+ redirect_to login_path unless user_signed_in?
26
+ end
27
+
28
+ # Authenticates the current user
29
+ # - from session cookie
30
+ # - (future) from Authorization header
31
+ def authenticate_user
32
+ Current.user = authenticated_user_from_session
33
+ end
34
+
35
+ # Returns a user from session cookie
36
+ def authenticated_user_from_session
37
+ user_id = session[:user_id]
38
+ return unless user_id
39
+ User.find_by(id: user_id)
40
+ end
41
+
42
+ # Logs in the user
43
+ # - Set Current.user for the current request
44
+ # - Save a session cookie so the next request is authenticated
45
+ def login(user)
46
+ Current.user = user
47
+ reset_session
48
+ session[:user_id] = user.id
49
+ end
50
+
51
+ def logout
52
+ Current.user = nil
53
+ reset_session
54
+ end
55
+
56
+ def reset_session
57
+ if session && session.respond_to?(:destroy)
58
+ session.destroy
59
+ else
60
+ self.session = {}
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,24 @@
1
+ module ReviseAuth
2
+ module Backports
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ # Prevent timing-based enumeration attacks.
7
+ # This can be removed when Rails 7.1 is released.
8
+ def authenticate_by(attributes)
9
+ passwords, identifiers = attributes.to_h.partition do |name, value|
10
+ !has_attribute?(name) && has_attribute?("#{name}_digest")
11
+ end.map(&:to_h)
12
+
13
+ raise ArgumentError, "One or more password arguments are required" if passwords.empty?
14
+ raise ArgumentError, "One or more finder arguments are required" if identifiers.empty?
15
+ if (record = find_by(identifiers))
16
+ record if passwords.count { |name, value| record.send(:"authenticate_#{name}", value) } == passwords.size
17
+ else
18
+ new(passwords)
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,6 @@
1
+ module ReviseAuth
2
+ class Current < ActiveSupport::CurrentAttributes
3
+ # Stores the current user for the request
4
+ attribute :user
5
+ end
6
+ end
@@ -0,0 +1,18 @@
1
+ module ReviseAuth
2
+ class Turbine < ::Jets::Turbine
3
+ initializer :revise_auth_controller do
4
+ ActiveSupport.on_load(:action_controller_base) do
5
+ include ReviseAuth::Authentication
6
+ end
7
+ end
8
+
9
+ # Set default session expiration of 30 days if not specified
10
+ # Runs immediately after Rails defines the default session store
11
+ # https://github.com/rails/rails/blob/7-0-stable/railties/lib/rails/application/finisher.rb#L43-L49
12
+ # initializer :revise_auth_cookie_session_expiry, after: :setup_default_session_store do |app|
13
+ # if Jets.config.session[:store] == ActionDispatch::Session::CookieStore
14
+ # app.config.session_options.with_defaults! expire_after: 30.days
15
+ # end
16
+ # end
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ module ReviseAuth
2
+ module Model
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include Backports
7
+
8
+ EMAIL_VERIFICATION_TOKEN_VALIDITY = 1.day
9
+
10
+ has_secure_password
11
+ has_secure_token :confirmation_token
12
+
13
+ # generates_token_for :email_verification, expires_in: EMAIL_VERIFICATION_TOKEN_VALIDITY do
14
+ # email
15
+ # end
16
+
17
+ validates :email, format: {with: URI::MailTo::EMAIL_REGEXP}, presence: true, uniqueness: true
18
+ validates :unconfirmed_email, format: {with: URI::MailTo::EMAIL_REGEXP}, allow_blank: true
19
+ validates_length_of :password, minimum: 6, allow_nil: true
20
+
21
+ before_validation do
22
+ email&.downcase!&.strip!
23
+ unconfirmed_email&.downcase!
24
+ end
25
+ end
26
+
27
+ # Generates a confirmation token and send email to the user
28
+ def send_confirmation_instructions
29
+ token = generate_token_for(:email_verification)
30
+ ReviseAuth::Mailer.with(user: self, token: token).confirm_email.deliver_later
31
+ end
32
+
33
+ def confirm_email_change
34
+ update(confirmed_at: Time.current, email: unconfirmed_email)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ module ReviseAuth
2
+ class RouteConstraint
3
+ attr_reader :request
4
+
5
+ # Stub out helper_method
6
+ def self.helper_method(...)
7
+ end
8
+
9
+ include Authentication
10
+
11
+ def initialize(request)
12
+ @request = request
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,49 @@
1
+ #module ActionDispatch::Routing
2
+ # class Mapper
3
+ # def revise_auth
4
+ # scope module: :revise_auth do
5
+ # revise_registration
6
+
7
+ # get "login", to: "sessions#new"
8
+ # post "login", to: "sessions#create"
9
+
10
+ # revise_profile
11
+
12
+ # patch "profile/email", to: "email#update"
13
+ # patch "profile/password", to: "password#update"
14
+
15
+ # # Email confirmation
16
+ # get "profile/email", to: "email#show"
17
+
18
+ # delete "logout", to: "sessions#destroy"
19
+ # end
20
+ # end
21
+
22
+ # # Adds helpers for config/routes.rb to constraint routes with authentication
23
+ # #
24
+ # def authenticated
25
+ # constraints ->(request) { ReviseAuth::RouteConstraint.new(request).user_signed_in? } do
26
+ # yield
27
+ # end
28
+ # end
29
+
30
+ # def unauthenticated
31
+ # constraints ->(request) { !ReviseAuth::RouteConstraint.new(request).user_signed_in? } do
32
+ # yield
33
+ # end
34
+ # end
35
+
36
+ # private
37
+
38
+ # def revise_registration
39
+ # get "sign_up", to: "registrations#new"
40
+ # post "sign_up", to: "registrations#create"
41
+ # end
42
+
43
+ # def revise_profile
44
+ # get "profile", to: "registrations#edit"
45
+ # patch "profile", to: "registrations#update"
46
+ # delete "profile", to: "registrations#destroy"
47
+ # end
48
+ # end
49
+ #end
@@ -0,0 +1,3 @@
1
+ module ReviseAuth
2
+ VERSION = "0.2.1"
3
+ end
@@ -0,0 +1,11 @@
1
+ require "revise_auth/version"
2
+ require "revise_auth/engine"
3
+ require "revise_auth/routes"
4
+
5
+ module ReviseAuth
6
+ autoload :Authentication, "revise_auth/authentication"
7
+ autoload :Backports, "revise_auth/backports"
8
+ autoload :Current, "revise_auth/current"
9
+ autoload :Model, "revise_auth/model"
10
+ autoload :RouteConstraint, "revise_auth/route_constraint"
11
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :revise_auth do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: revise_auth-jets
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeremiah Parrack
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-09-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bcrypt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ description: Authentication for Ruby on Jets apps
28
+ email:
29
+ - jeremiahlukus1@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - app/config/routes.rb
38
+ - app/controllers/main_controller.rb
39
+ - app/controllers/revise_auth/email_controller.rb
40
+ - app/controllers/revise_auth/password_controller.rb
41
+ - app/controllers/revise_auth/registrations_controller.rb
42
+ - app/controllers/revise_auth/sessions_controller.rb
43
+ - app/controllers/revise_auth_controller.rb
44
+ - app/mailers/revise_auth/mailer.rb
45
+ - app/views/main/authenticated.html.erb
46
+ - app/views/main/index.html.erb
47
+ - app/views/revise_auth/mailer/confirm_email.html.erb
48
+ - app/views/revise_auth/registrations/edit.html.erb
49
+ - app/views/revise_auth/registrations/new.html.erb
50
+ - app/views/revise_auth/sessions/new.html.erb
51
+ - config/locales/de.yml
52
+ - config/locales/el.yml
53
+ - config/locales/en.yml
54
+ - config/locales/fr.yml
55
+ - config/locales/nl.yml
56
+ - config/locales/tr.yml
57
+ - config/locales/zh-TW.yml
58
+ - lib/generators/revise_auth/model_generator.rb
59
+ - lib/generators/revise_auth/templates/README
60
+ - lib/generators/revise_auth/views_generator.rb
61
+ - lib/revise_auth.rb
62
+ - lib/revise_auth/authentication.rb
63
+ - lib/revise_auth/backports.rb
64
+ - lib/revise_auth/current.rb
65
+ - lib/revise_auth/engine.rb
66
+ - lib/revise_auth/model.rb
67
+ - lib/revise_auth/route_constraint.rb
68
+ - lib/revise_auth/routes.rb
69
+ - lib/revise_auth/version.rb
70
+ - lib/tasks/revise_auth_tasks.rake
71
+ homepage: https://github.com/jeremiahlukus/revise_auth-jets
72
+ licenses:
73
+ - MIT
74
+ metadata:
75
+ homepage_uri: https://github.com/jeremiahlukus/revise_auth-jets
76
+ source_code_uri: https://github.com/jeremiahlukus/revise_auth-jets
77
+ changelog_uri: https://github.com/jeremiahlukus/revise_auth-jets/blob/main/CHANGELOG.md
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubygems_version: 3.4.1
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Simple authentication for Ruby on Jets apps
97
+ test_files: []