yaag 0.0.11 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/MIT-LICENSE +20 -0
- data/README.md +57 -16
- data/Rakefile +7 -9
- data/{lib/generators/yaag/templates/app → app}/controllers/sessions_controller.rb +4 -4
- data/{lib/generators/yaag/templates/app → app}/controllers/signins_controller.rb +2 -2
- data/{lib/generators/yaag/templates/app → app}/mailers/signins_mailer.rb +1 -1
- data/{lib/generators/yaag/templates/app → app}/models/user.rb +1 -1
- data/app/views/signins/new.html.erb +14 -0
- data/app/views/signins_mailer/token.html.erb +6 -0
- data/app/views/signins_mailer/token.text.erb +5 -0
- data/config/locales/en.yml +15 -0
- data/config/routes.rb +6 -0
- data/db/migrate/20260108164812_create_users.rb +10 -0
- data/db/migrate/20260108165215_create_sessions.rb +11 -0
- data/lib/generators/{yaag → authentication}/USAGE +2 -1
- data/lib/generators/authentication/copy/views_generator.rb +14 -0
- data/lib/generators/authentication/install_generator.rb +18 -0
- data/lib/generators/authentication/templates/README +39 -0
- data/lib/tasks/yaag_tasks.rake +4 -0
- data/lib/yaag/engine.rb +1 -2
- data/lib/yaag/version.rb +1 -3
- data/lib/yaag.rb +48 -5
- metadata +26 -24
- data/.rubocop.yml +0 -8
- data/LICENSE.txt +0 -21
- data/lib/generators/yaag/install_generator.rb +0 -64
- data/lib/generators/yaag/templates/README +0 -1
- data/lib/generators/yaag/templates/active_model/passwordless_login.rb +0 -51
- data/lib/generators/yaag/templates/app/channels/application_cable/connection.rb +0 -16
- data/lib/generators/yaag/templates/app/views/signins/new.html.erb +0 -8
- data/lib/generators/yaag/templates/app/views/signins_mailer/token.html.erb +0 -8
- data/lib/generators/yaag/templates/app/views/signins_mailer/token.text.erb +0 -6
- data/mise.toml +0 -2
- data/sig/yaag.rbs +0 -4
- /data/{lib/generators/yaag/templates/app → app}/controllers/concerns/authentication.rb +0 -0
- /data/{lib/generators/yaag/templates/app → app}/models/current.rb +0 -0
- /data/{lib/generators/yaag/templates/app → app}/models/session.rb +0 -0
- /data/{lib/generators/yaag/templates/app → app}/views/sessions/new.html.erb +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4ae888409d5afb7a721b266a6952749b1abc3255a6f3d4671a9204c5b24dd8f4
|
|
4
|
+
data.tar.gz: 2eb44833be4f5d0d20f6b3318982697ca754fb3b9ce41f4698532557f0635ef1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c59715e2e986d0a012abd80f2d7376dbd106c28d2d9ec12c64bf8db2b1a0207e07760953e652cfdc6e259ec3100e025e9fdb516c6caa199bb424ab6127c06245
|
|
7
|
+
data.tar.gz: f20893f3c65274ab3ea55b41efb76d70132a3765f97155b837b4e6c0e21e5068a0d3a3055cf101b7ef10e46550fc2f5dcf1a64b05edaec011fde9ab168a4d958
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright
|
|
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
CHANGED
|
@@ -1,35 +1,76 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Yet Another Authentication Gem
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Yet Another Authentication Gem (YAAG) provides passwordless authentication for your rails app, all it takes is the user's e-mail address.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
No password. No e-mail confirmation. No registration.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## TL;DR
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
bundle add yaag
|
|
11
|
+
bundle install
|
|
12
|
+
|
|
13
|
+
rails g authentication:install
|
|
14
|
+
rails db:migrate
|
|
15
|
+
```
|
|
8
16
|
|
|
9
|
-
|
|
17
|
+
## How it works
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
It's the same mechanics of password reset in traditional authentication: the user provides an e-amil address and receives a link with a token to sign in. At its core, it implements the same logic of the built-in rails authentication (in fact most of the gem's code came from the rails library).
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
Add this line to your application's Gemfile:
|
|
12
23
|
|
|
13
|
-
|
|
24
|
+
```bash
|
|
25
|
+
bundle add yaag
|
|
26
|
+
```
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
And then execute:
|
|
29
|
+
```bash
|
|
30
|
+
bundle
|
|
31
|
+
```
|
|
16
32
|
|
|
17
|
-
|
|
33
|
+
Generate the authentication components (migrations, etc):
|
|
34
|
+
```bash
|
|
35
|
+
rails g authentication:install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Follow the on-screen post-installation instructions.
|
|
18
39
|
|
|
19
40
|
## Usage
|
|
20
41
|
|
|
21
|
-
|
|
42
|
+
By default, all controllers require signing in via the inclusion of `include Authentication` in the `ApplicationController`. If you have a route that doesn't require signing in, add `allow_unauthenticated_access` to it:
|
|
22
43
|
|
|
23
|
-
|
|
44
|
+
```
|
|
45
|
+
class GuestController < ApplicationController
|
|
46
|
+
allow_unauthenticated_access only: %i[ index ]
|
|
47
|
+
...
|
|
48
|
+
end
|
|
49
|
+
```
|
|
24
50
|
|
|
25
|
-
|
|
51
|
+
Get the current user with `Current.user` and the current session with `Current.session`
|
|
26
52
|
|
|
27
|
-
|
|
53
|
+
```
|
|
54
|
+
class MyController < ApplicationController
|
|
55
|
+
def something
|
|
56
|
+
user = Current.user
|
|
57
|
+
session = Current.session
|
|
58
|
+
...
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
```
|
|
28
62
|
|
|
29
|
-
|
|
63
|
+
To create a copy of the views for customization, run:
|
|
30
64
|
|
|
31
|
-
|
|
65
|
+
```bash
|
|
66
|
+
rails g authentication:copy:views
|
|
67
|
+
```
|
|
32
68
|
|
|
33
|
-
##
|
|
69
|
+
## Release
|
|
34
70
|
|
|
71
|
+
```bash
|
|
72
|
+
git tag $(bundle exec rake version | tr -d '"') && git push --tags
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## License
|
|
35
76
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
require "bundler/setup"
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Minitest::TestTask.create
|
|
3
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
|
4
|
+
load "rails/tasks/engine.rake"
|
|
7
5
|
|
|
8
|
-
require "
|
|
9
|
-
|
|
10
|
-
RuboCop::RakeTask.new
|
|
6
|
+
require "bundler/gem_tasks"
|
|
11
7
|
|
|
12
|
-
task
|
|
8
|
+
task :version do
|
|
9
|
+
p "v#{Yaag::VERSION}"
|
|
10
|
+
end
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
class SessionsController < ApplicationController
|
|
2
2
|
allow_unauthenticated_access only: %i[ new create ]
|
|
3
3
|
before_action :set_user_by_token, only: %i[ create ]
|
|
4
|
-
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_path, alert: "
|
|
4
|
+
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_path, alert: I18n.t("yaag.errors.rate_limit") }
|
|
5
5
|
|
|
6
6
|
def new
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def create
|
|
10
10
|
start_new_session_for @user
|
|
11
|
-
redirect_to after_authentication_url
|
|
11
|
+
redirect_to after_authentication_url, notice: I18n.t("yaag.sessions.successful")
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def destroy
|
|
15
15
|
terminate_session
|
|
16
|
-
redirect_to new_signin_path, status: :see_other
|
|
16
|
+
redirect_to new_signin_path, notice: I18n.t("yaag.sessions.destroy"), status: :see_other
|
|
17
17
|
end
|
|
18
18
|
private
|
|
19
19
|
def set_user_by_token
|
|
20
20
|
@user = User.find_by_email_address_login_token!(params[:token])
|
|
21
21
|
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
|
22
|
-
redirect_to new_signin_path, alert: "
|
|
22
|
+
redirect_to new_signin_path, alert: I18n.t("yaag.errors.invalid_token"), status: :see_other
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
class SigninsController < ApplicationController
|
|
2
2
|
allow_unauthenticated_access
|
|
3
|
-
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_signin_path, alert: "
|
|
3
|
+
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_signin_path, alert: I18n.t("yaag.errors.rate_limit") }
|
|
4
4
|
def new
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
def create
|
|
8
8
|
user = User.find_or_create_by(email_address: params[:email_address])
|
|
9
9
|
SigninsMailer.token(user).deliver_now
|
|
10
|
-
redirect_to new_session_path, notice: "
|
|
10
|
+
redirect_to new_session_path, notice: I18n.t("yaag.signins.email_sent"), status: :see_other
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
|
|
2
|
+
<%= tag.div(flash[:notice], style: "color:green") if flash[:notice] %>
|
|
3
|
+
|
|
4
|
+
<div class="container w-50 ">
|
|
5
|
+
<h2>Sign In</h2>
|
|
6
|
+
<%= form_with url: signin_path do |form| %>
|
|
7
|
+
<div class="field mt-3">
|
|
8
|
+
<%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: t("yaag.forms.signin_placeholder"), value: params[:email_address], class: "form-control" %><br>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="actions mb-3">
|
|
11
|
+
<%= form.submit t("yaag.forms.signin_button"), class: "form-control btn btn-primary" %>
|
|
12
|
+
</div>
|
|
13
|
+
<% end %>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
en:
|
|
3
|
+
yaag:
|
|
4
|
+
errors:
|
|
5
|
+
invalid_token: "Signin link is invalid or has expired."
|
|
6
|
+
rate_limit: "Try again later."
|
|
7
|
+
forms:
|
|
8
|
+
signin_button: "Sign in"
|
|
9
|
+
signin_placeholder: "Enter your email address"
|
|
10
|
+
sessions:
|
|
11
|
+
successful: "Signed in successfully."
|
|
12
|
+
destroy: "Signed out successfully."
|
|
13
|
+
signins:
|
|
14
|
+
email_sent: "Sign in address sent to provided e-mail."
|
|
15
|
+
email_subject: "Sign in link"
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Authentication
|
|
2
|
+
module Copy
|
|
3
|
+
class ViewsGenerator < Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path("../../../../", __dir__)
|
|
5
|
+
|
|
6
|
+
def copy_views
|
|
7
|
+
copy_file "app/views/sessions/new.html.erb"
|
|
8
|
+
copy_file "app/views/signins/new.html.erb"
|
|
9
|
+
copy_file "app/views/signins_mailer/token.html.erb"
|
|
10
|
+
copy_file "app/views/signins_mailer/token.text.erb"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Authentication
|
|
2
|
+
class InstallGenerator < Rails::Generators::Base
|
|
3
|
+
source_root File.expand_path("templates", __dir__)
|
|
4
|
+
|
|
5
|
+
def configure_application_controller
|
|
6
|
+
inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " include Authentication\n"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def generate_migrations
|
|
10
|
+
generate "migration", "CreateUsers", "email_address:string!:uniq", "--force"
|
|
11
|
+
generate "migration", "CreateSessions", "user:references ip_address:string user_agent:string", "--force"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show_readme
|
|
15
|
+
readme "README" if behavior == :invoke
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
|
|
2
|
+
Yet Another Authentication Gem (YAAG)
|
|
3
|
+
|
|
4
|
+
===============================================================
|
|
5
|
+
|
|
6
|
+
To complete the installation, run a database migration:
|
|
7
|
+
|
|
8
|
+
./bin/rails db:migrate
|
|
9
|
+
|
|
10
|
+
===============================================================
|
|
11
|
+
|
|
12
|
+
Make sure root route is present in config/routes.rb. Example:
|
|
13
|
+
|
|
14
|
+
Rails.application.routes.draw do
|
|
15
|
+
...
|
|
16
|
+
root "controller#action"
|
|
17
|
+
...
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
===============================================================
|
|
21
|
+
|
|
22
|
+
By default, all controllers require user signin.
|
|
23
|
+
|
|
24
|
+
To allow unauthenticated access, add allow_unauthenticated_access to your controller. Example:
|
|
25
|
+
|
|
26
|
+
class MyController < ApplicationController
|
|
27
|
+
allow_unauthenticated_access only: %i[ index ]
|
|
28
|
+
...
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
===============================================================
|
|
32
|
+
|
|
33
|
+
More generators available for customizations:
|
|
34
|
+
|
|
35
|
+
./bin/rails db:migrate g authentication:copy:views
|
|
36
|
+
|
|
37
|
+
===============================================================
|
|
38
|
+
|
|
39
|
+
See more at: https://github.com/nu12/yaag
|
data/lib/yaag/engine.rb
CHANGED
data/lib/yaag/version.rb
CHANGED
data/lib/yaag.rb
CHANGED
|
@@ -1,8 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require_relative "yaag/version"
|
|
1
|
+
require "yaag/version"
|
|
2
|
+
require "yaag/engine"
|
|
4
3
|
|
|
5
4
|
module Yaag
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
module PasswordlessLogin
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
DEFAULT_LOGIN_TOKEN_EXPIRES_IN = 15.minutes
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module ClassMethods
|
|
14
|
+
def has_passwordless_login(attribute = :email_address)
|
|
15
|
+
include InstanceMethodsOnActivation.new(attribute)
|
|
16
|
+
|
|
17
|
+
if respond_to?(:generates_token_for)
|
|
18
|
+
login_token_expires_in = DEFAULT_LOGIN_TOKEN_EXPIRES_IN
|
|
19
|
+
|
|
20
|
+
silence_redefinition_of_method(:"#{attribute}_login_token_expires_in")
|
|
21
|
+
define_method(:"#{attribute}_login_token_expires_in") { login_token_expires_in }
|
|
22
|
+
|
|
23
|
+
generates_token_for :"#{attribute}_login", expires_in: login_token_expires_in do
|
|
24
|
+
public_send(:"#{attribute}")&.first(10)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
28
|
+
silence_redefinition_of_method :find_by_#{attribute}_login_token
|
|
29
|
+
def self.find_by_#{attribute}_login_token(token)
|
|
30
|
+
find_by_token_for(:#{attribute}_login, token)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
silence_redefinition_of_method :find_by_#{attribute}_login_token!
|
|
34
|
+
def self.find_by_#{attribute}_login_token!(token)
|
|
35
|
+
find_by_token_for!(:#{attribute}_login, token)
|
|
36
|
+
end
|
|
37
|
+
RUBY
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class InstanceMethodsOnActivation < Module
|
|
43
|
+
def initialize(attribute)
|
|
44
|
+
# attr_accessor attribute
|
|
45
|
+
define_method("#{attribute}_login_token") do
|
|
46
|
+
generate_token_for(:"#{attribute}_login")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
8
51
|
end
|
metadata
CHANGED
|
@@ -1,47 +1,49 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yaag
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nu12
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description:
|
|
13
|
+
description: Yet Another Authentication Gem (YAAG) provides passwordless authentication
|
|
14
|
+
for your Ruby on Rails app, all it takes is the user's e-mail address.
|
|
14
15
|
email:
|
|
15
16
|
- 34694287+nu12@users.noreply.github.com
|
|
16
17
|
executables: []
|
|
17
18
|
extensions: []
|
|
18
19
|
extra_rdoc_files: []
|
|
19
20
|
files:
|
|
20
|
-
-
|
|
21
|
-
- LICENSE.txt
|
|
21
|
+
- MIT-LICENSE
|
|
22
22
|
- README.md
|
|
23
23
|
- Rakefile
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
- lib/generators/
|
|
24
|
+
- app/controllers/concerns/authentication.rb
|
|
25
|
+
- app/controllers/sessions_controller.rb
|
|
26
|
+
- app/controllers/signins_controller.rb
|
|
27
|
+
- app/mailers/signins_mailer.rb
|
|
28
|
+
- app/models/current.rb
|
|
29
|
+
- app/models/session.rb
|
|
30
|
+
- app/models/user.rb
|
|
31
|
+
- app/views/sessions/new.html.erb
|
|
32
|
+
- app/views/signins/new.html.erb
|
|
33
|
+
- app/views/signins_mailer/token.html.erb
|
|
34
|
+
- app/views/signins_mailer/token.text.erb
|
|
35
|
+
- config/locales/en.yml
|
|
36
|
+
- config/routes.rb
|
|
37
|
+
- db/migrate/20260108164812_create_users.rb
|
|
38
|
+
- db/migrate/20260108165215_create_sessions.rb
|
|
39
|
+
- lib/generators/authentication/USAGE
|
|
40
|
+
- lib/generators/authentication/copy/views_generator.rb
|
|
41
|
+
- lib/generators/authentication/install_generator.rb
|
|
42
|
+
- lib/generators/authentication/templates/README
|
|
43
|
+
- lib/tasks/yaag_tasks.rake
|
|
40
44
|
- lib/yaag.rb
|
|
41
45
|
- lib/yaag/engine.rb
|
|
42
46
|
- lib/yaag/version.rb
|
|
43
|
-
- mise.toml
|
|
44
|
-
- sig/yaag.rbs
|
|
45
47
|
homepage: https://github.com/nu12/yaag
|
|
46
48
|
licenses:
|
|
47
49
|
- MIT
|
|
@@ -66,5 +68,5 @@ requirements: []
|
|
|
66
68
|
rubygems_version: 3.4.19
|
|
67
69
|
signing_key:
|
|
68
70
|
specification_version: 4
|
|
69
|
-
summary: Passwordless authentication.
|
|
71
|
+
summary: Passwordless authentication for your Ruby on Rails app.
|
|
70
72
|
test_files: []
|
data/.rubocop.yml
DELETED
data/LICENSE.txt
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
The MIT License (MIT)
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 nu12
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
all copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
-
THE SOFTWARE.
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "rails/generators/bundle_helper"
|
|
4
|
-
|
|
5
|
-
module Yaag
|
|
6
|
-
module Generators
|
|
7
|
-
class InstallGenerator < Rails::Generators::Base # :nodoc:
|
|
8
|
-
include Rails::Generators::BundleHelper
|
|
9
|
-
source_root File.expand_path("../templates", __FILE__)
|
|
10
|
-
|
|
11
|
-
class_option :api, type: :boolean,
|
|
12
|
-
desc: "Generate API-only controllers and models, with no view templates"
|
|
13
|
-
|
|
14
|
-
# hook_for :template_engine do |template_engine|
|
|
15
|
-
#invoke template_engine unless options.api?
|
|
16
|
-
# end
|
|
17
|
-
|
|
18
|
-
def create_authentication_files
|
|
19
|
-
|
|
20
|
-
template "app/models/session.rb"
|
|
21
|
-
template "app/models/user.rb"
|
|
22
|
-
template "app/models/current.rb"
|
|
23
|
-
|
|
24
|
-
template "app/controllers/signins_controller.rb"
|
|
25
|
-
template "app/controllers/sessions_controller.rb"
|
|
26
|
-
template "app/controllers/concerns/authentication.rb"
|
|
27
|
-
|
|
28
|
-
template "app/channels/application_cable/connection.rb" # if defined?(ActionCable::Engine)
|
|
29
|
-
|
|
30
|
-
copy_file "app/views/sessions/new.html.erb"
|
|
31
|
-
copy_file "app/views/signins/new.html.erb"
|
|
32
|
-
|
|
33
|
-
#if defined?(ActionMailer::Railtie)
|
|
34
|
-
template "app/mailers/signins_mailer.rb"
|
|
35
|
-
|
|
36
|
-
copy_file "app/views/signins_mailer/token.html.erb"
|
|
37
|
-
copy_file "app/views/signins_mailer/token.text.erb"
|
|
38
|
-
#end
|
|
39
|
-
|
|
40
|
-
template "active_model/passwordless_login.rb", "lib/active_model/passwordless_login.rb"
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def configure_application_controller
|
|
44
|
-
inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " include Authentication\n" # if File.exist? "app/controllers/application_controller.rb"
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def configure_authentication_routes
|
|
48
|
-
route "resource :signin, only: [:new, :create]" # if File.exist? "config/routes.rb"
|
|
49
|
-
route "resource :session, only: [:new, :destroy] do\n get \"/:token/create\" => \"sessions#create\", as: :create\nend" # if File.exist? "config/routes.rb"
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def add_migrations
|
|
53
|
-
generate "migration", "CreateUsers", "email_address:string!:uniq", "--force"
|
|
54
|
-
generate "migration", "CreateSessions", "user:references ip_address:string user_agent:string", "--force"
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def show_readme
|
|
58
|
-
readme "README" if behavior == :invoke
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
#hook_for :test_framework
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
===============================================================================
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module ActiveModel
|
|
4
|
-
module PasswordlessLogin
|
|
5
|
-
extend ActiveSupport::Concern
|
|
6
|
-
|
|
7
|
-
DEFAULT_LOGIN_TOKEN_EXPIRES_IN = 15.minutes
|
|
8
|
-
|
|
9
|
-
class << self
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
module ClassMethods
|
|
13
|
-
def has_passwordless_login(attribute = :email_address)
|
|
14
|
-
include InstanceMethodsOnActivation.new(attribute)
|
|
15
|
-
|
|
16
|
-
if respond_to?(:generates_token_for)
|
|
17
|
-
login_token_expires_in = DEFAULT_LOGIN_TOKEN_EXPIRES_IN
|
|
18
|
-
|
|
19
|
-
silence_redefinition_of_method(:"#{attribute}_login_token_expires_in")
|
|
20
|
-
define_method(:"#{attribute}_login_token_expires_in") { login_token_expires_in }
|
|
21
|
-
|
|
22
|
-
generates_token_for :"#{attribute}_login", expires_in: login_token_expires_in do
|
|
23
|
-
public_send(:"#{attribute}")&.first(10)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
27
|
-
silence_redefinition_of_method :find_by_#{attribute}_login_token
|
|
28
|
-
def self.find_by_#{attribute}_login_token(token)
|
|
29
|
-
find_by_token_for(:#{attribute}_login, token)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
silence_redefinition_of_method :find_by_#{attribute}_login_token!
|
|
33
|
-
def self.find_by_#{attribute}_login_token!(token)
|
|
34
|
-
find_by_token_for!(:#{attribute}_login, token)
|
|
35
|
-
end
|
|
36
|
-
RUBY
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
class InstanceMethodsOnActivation < Module
|
|
42
|
-
def initialize(attribute)
|
|
43
|
-
attr_reader attribute
|
|
44
|
-
|
|
45
|
-
define_method("#{attribute}_login_token") do
|
|
46
|
-
generate_token_for(:"#{attribute}_login")
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
module ApplicationCable
|
|
2
|
-
class Connection < ActionCable::Connection::Base
|
|
3
|
-
identified_by :current_user
|
|
4
|
-
|
|
5
|
-
def connect
|
|
6
|
-
set_current_user || reject_unauthorized_connection
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
private
|
|
10
|
-
def set_current_user
|
|
11
|
-
if session = Session.find_by(id: cookies.signed[:session_id])
|
|
12
|
-
self.current_user = session.user
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
|
|
2
|
-
<%= tag.div(flash[:notice], style: "color:green") if flash[:notice] %>
|
|
3
|
-
|
|
4
|
-
<%= form_with url: signin_path do |form| %>
|
|
5
|
-
<%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address] %><br>
|
|
6
|
-
<%= form.submit "Sign in" %>
|
|
7
|
-
<% end %>
|
|
8
|
-
<br>
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<% if @user %>
|
|
2
|
-
<p>
|
|
3
|
-
You can reset your password on
|
|
4
|
-
<%= link_to "this password reset page", create_session_url(@user.email_address_login_token) %>.
|
|
5
|
-
|
|
6
|
-
This link will expire in <%= distance_of_time_in_words(0, @user.email_address_login_token_expires_in) %>.
|
|
7
|
-
</p>
|
|
8
|
-
<% end %>
|
data/mise.toml
DELETED
data/sig/yaag.rbs
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|