linked_rails-auth 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +28 -0
- data/Rakefile +34 -0
- data/app/actions/linked_rails/auth/access_token_action_list.rb +16 -0
- data/app/actions/linked_rails/auth/confirmation_action_list.rb +17 -0
- data/app/actions/linked_rails/auth/otp_attempt_action_list.rb +13 -0
- data/app/actions/linked_rails/auth/otp_secret_action_list.rb +31 -0
- data/app/actions/linked_rails/auth/password_action_list.rb +25 -0
- data/app/actions/linked_rails/auth/registration_action_list.rb +15 -0
- data/app/actions/linked_rails/auth/session_action_list.rb +22 -0
- data/app/actions/linked_rails/auth/unlock_action_list.rb +17 -0
- data/app/controllers/linked_rails/auth/access_tokens_controller.rb +131 -0
- data/app/controllers/linked_rails/auth/confirmations_controller.rb +87 -0
- data/app/controllers/linked_rails/auth/otp_attempts_controller.rb +21 -0
- data/app/controllers/linked_rails/auth/otp_secrets_controller.rb +40 -0
- data/app/controllers/linked_rails/auth/passwords_controller.rb +63 -0
- data/app/controllers/linked_rails/auth/registrations_controller.rb +33 -0
- data/app/controllers/linked_rails/auth/sessions_controller.rb +55 -0
- data/app/controllers/linked_rails/auth/unlocks_controller.rb +44 -0
- data/app/forms/linked_rails/auth/access_token_form.rb +20 -0
- data/app/forms/linked_rails/auth/confirmation_form.rb +9 -0
- data/app/forms/linked_rails/auth/otp_attempt_form.rb +9 -0
- data/app/forms/linked_rails/auth/otp_secret_form.rb +12 -0
- data/app/forms/linked_rails/auth/password_form.rb +21 -0
- data/app/forms/linked_rails/auth/registration_form.rb +21 -0
- data/app/forms/linked_rails/auth/session_form.rb +13 -0
- data/app/forms/linked_rails/auth/unlock_form.rb +9 -0
- data/app/helpers/linked_rails/auth/otp_helper.rb +30 -0
- data/app/models/linked_rails/auth/access_token.rb +40 -0
- data/app/models/linked_rails/auth/confirmation.rb +70 -0
- data/app/models/linked_rails/auth/guest_user.rb +29 -0
- data/app/models/linked_rails/auth/otp_attempt.rb +41 -0
- data/app/models/linked_rails/auth/otp_base.rb +57 -0
- data/app/models/linked_rails/auth/otp_secret.rb +91 -0
- data/app/models/linked_rails/auth/password.rb +47 -0
- data/app/models/linked_rails/auth/registration.rb +39 -0
- data/app/models/linked_rails/auth/session.rb +46 -0
- data/app/models/linked_rails/auth/unlock.rb +59 -0
- data/app/policies/linked_rails/auth/access_token_policy.rb +17 -0
- data/app/policies/linked_rails/auth/confirmation_policy.rb +17 -0
- data/app/policies/linked_rails/auth/otp_attempt_policy.rb +17 -0
- data/app/policies/linked_rails/auth/otp_secret_policy.rb +37 -0
- data/app/policies/linked_rails/auth/password_policy.rb +23 -0
- data/app/policies/linked_rails/auth/registration_policy.rb +13 -0
- data/app/policies/linked_rails/auth/session_policy.rb +17 -0
- data/app/policies/linked_rails/auth/unlock_policy.rb +21 -0
- data/app/serializers/linked_rails/auth/access_token_serializer.rb +11 -0
- data/app/serializers/linked_rails/auth/confirmation_serializer.rb +10 -0
- data/app/serializers/linked_rails/auth/otp_attempt_serializer.rb +12 -0
- data/app/serializers/linked_rails/auth/otp_secret_serializer.rb +14 -0
- data/app/serializers/linked_rails/auth/password_serializer.rb +18 -0
- data/app/serializers/linked_rails/auth/registration_serializer.rb +12 -0
- data/app/serializers/linked_rails/auth/session_serializer.rb +10 -0
- data/app/serializers/linked_rails/auth/unlock_serializer.rb +9 -0
- data/config/routes.rb +4 -0
- data/lib/generators/linked_rails/auth/install_generator.rb +155 -0
- data/lib/generators/linked_rails/auth/templates/README +2 -0
- data/lib/generators/linked_rails/auth/templates/doorkeeper_jwt_initializer.rb +52 -0
- data/lib/generators/linked_rails/auth/templates/locales.yml +39 -0
- data/lib/generators/linked_rails/auth/templates/migration.rb.erb +20 -0
- data/lib/linked_rails/auth/auth_helper.rb +101 -0
- data/lib/linked_rails/auth/controller/error_handling.rb +17 -0
- data/lib/linked_rails/auth/controller.rb +16 -0
- data/lib/linked_rails/auth/engine.rb +8 -0
- data/lib/linked_rails/auth/errors/account_locked.rb +10 -0
- data/lib/linked_rails/auth/errors/expired.rb +10 -0
- data/lib/linked_rails/auth/errors/unauthorized.rb +10 -0
- data/lib/linked_rails/auth/errors/unknown_email.rb +14 -0
- data/lib/linked_rails/auth/errors/wrong_password.rb +14 -0
- data/lib/linked_rails/auth/errors.rb +7 -0
- data/lib/linked_rails/auth/routes.rb +86 -0
- data/lib/linked_rails/auth/version.rb +7 -0
- data/lib/linked_rails/auth.rb +46 -0
- data/lib/tasks/linked_rails/auth_tasks.rake +6 -0
- metadata +257 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class OtpAttemptsController < LinkedRails.controller_parent_class
|
6
|
+
private
|
7
|
+
|
8
|
+
def create_success
|
9
|
+
sign_in(current_resource.owner, otp_verified: true)
|
10
|
+
|
11
|
+
head 200
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def controller_class
|
16
|
+
LinkedRails.otp_attempt_class
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class OtpSecretsController < LinkedRails.controller_parent_class
|
6
|
+
active_response :show
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def create_success
|
11
|
+
active_response_block do
|
12
|
+
sign_in(current_resource.owner, otp_verified: true) if current_user.guest?
|
13
|
+
|
14
|
+
respond_with_redirect(
|
15
|
+
location: current_resource.redirect_url,
|
16
|
+
reload: true
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy_success
|
22
|
+
active_response_block do
|
23
|
+
respond_with_redirect(location: LinkedRails.iri.to_s, reload: true)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def permit_params
|
28
|
+
return super unless action_name == 'create'
|
29
|
+
|
30
|
+
super.merge(active: true)
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def controller_class
|
35
|
+
LinkedRails.otp_secret_class
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class PasswordsController < Devise::PasswordsController
|
6
|
+
skip_before_action :require_no_authentication, only: :create
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def after_sending_reset_password_instructions_path_for(_resource_name)
|
11
|
+
LinkedRails.iri(path: '/u/session/new').path
|
12
|
+
end
|
13
|
+
|
14
|
+
def after_resetting_password_path_for(_resource)
|
15
|
+
LinkedRails.iri(path: '/u/session/new').path
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_execute
|
19
|
+
@current_resource = resource_class.send_reset_password_instructions(resource_params)
|
20
|
+
successfully_sent?(current_resource)
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_failure_message; end
|
24
|
+
|
25
|
+
def create_success_location
|
26
|
+
after_sending_reset_password_instructions_path_for(resource_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_success_message
|
30
|
+
find_message(:send_instructions)
|
31
|
+
end
|
32
|
+
|
33
|
+
def new_session_path(*_args)
|
34
|
+
LinkedRails.iri(path: 'u/session/new').path
|
35
|
+
end
|
36
|
+
|
37
|
+
def resource_params
|
38
|
+
params.fetch(resource_name, nil) ||
|
39
|
+
params.fetch(controller_name.singularize, {})
|
40
|
+
end
|
41
|
+
|
42
|
+
def update_execute
|
43
|
+
@current_resource = resource_class.reset_password_by_token(resource_params)
|
44
|
+
|
45
|
+
current_resource.errors.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def update_success_message
|
49
|
+
find_message(:updated_not_active)
|
50
|
+
end
|
51
|
+
|
52
|
+
def update_success_location
|
53
|
+
after_resetting_password_path_for(current_resource)
|
54
|
+
end
|
55
|
+
|
56
|
+
class << self
|
57
|
+
def controller_class
|
58
|
+
LinkedRails.password_class
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class RegistrationsController < Devise::RegistrationsController
|
6
|
+
skip_before_action :assert_is_devise_resource!, only: :show
|
7
|
+
active_response :show
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def active_response_success_message; end
|
12
|
+
|
13
|
+
def create_success
|
14
|
+
sign_in(current_resource)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_success_location
|
19
|
+
current_resource.redirect_url
|
20
|
+
end
|
21
|
+
|
22
|
+
def resource_params
|
23
|
+
params.require(permit_param_key)
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def controller_class
|
28
|
+
LinkedRails.registration_class
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class SessionsController < ApplicationController
|
6
|
+
active_response :create
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def active_response_success_message; end
|
11
|
+
|
12
|
+
def active_response_failure_message; end
|
13
|
+
|
14
|
+
def create_execute
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_success_location
|
19
|
+
if requested_user
|
20
|
+
LinkedRails.iri(path: 'u/access_token/new').to_s
|
21
|
+
else
|
22
|
+
LinkedRails.iri(path: 'u/registration/new').to_s
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def requested_user
|
27
|
+
@requested_user ||= LinkedRails.user_class.find_for_database_authentication(email: permit_params[:email])
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy_execute
|
31
|
+
sign_out
|
32
|
+
end
|
33
|
+
|
34
|
+
def destroy_success
|
35
|
+
respond_with_redirect(
|
36
|
+
location: '/'
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def permit_params
|
41
|
+
params.require(:session).permit(:redirect_url, :email)
|
42
|
+
end
|
43
|
+
|
44
|
+
def r_param
|
45
|
+
new_resource_params[:redirect_url] || (params.key?(:session) ? permit_params[:redirect_url] : nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
class << self
|
49
|
+
def controller_class
|
50
|
+
LinkedRails.session_class
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class UnlocksController < Devise::UnlocksController
|
6
|
+
private
|
7
|
+
|
8
|
+
def after_sending_unlock_instructions_path_for(_resource)
|
9
|
+
LinkedRails.iri(path: '/u/session/new').path
|
10
|
+
end
|
11
|
+
|
12
|
+
def after_unlock_path_for(_resource)
|
13
|
+
LinkedRails.iri(path: '/u/session/new').path
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_execute
|
17
|
+
@current_resource = resource_class.send_unlock_instructions(resource_params)
|
18
|
+
|
19
|
+
successfully_sent?(current_resource!)
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_failure_message; end
|
23
|
+
|
24
|
+
def create_success_location
|
25
|
+
after_sending_unlock_instructions_path_for(current_resource)
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_success_message
|
29
|
+
find_message(:send_instructions)
|
30
|
+
end
|
31
|
+
|
32
|
+
def resource_params
|
33
|
+
params.fetch(resource_name, nil) ||
|
34
|
+
params.fetch(controller_name.singularize, {})
|
35
|
+
end
|
36
|
+
|
37
|
+
class << self
|
38
|
+
def controller_class
|
39
|
+
LinkedRails.unlock_class
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class AccessTokenForm < LinkedRails.form_parent_class
|
6
|
+
field :email,
|
7
|
+
input_field: LinkedRails::Form::Field::EmailInput,
|
8
|
+
min_count: 1
|
9
|
+
field :password,
|
10
|
+
description: '',
|
11
|
+
input_field: LinkedRails::Form::Field::PasswordInput,
|
12
|
+
min_count: 1
|
13
|
+
resource :reset_password, url: -> { LinkedRails.iri(path: '/u/password/new') }
|
14
|
+
|
15
|
+
hidden do
|
16
|
+
field :redirect_url
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class OtpSecretForm < LinkedRails.form_parent_class
|
6
|
+
resource :provision_image,
|
7
|
+
description: -> { I18n.t('otp_secrets.properties.provision_image.description') },
|
8
|
+
path: Vocab.schema.image
|
9
|
+
field :otp_attempt, description: '', min_count: 1
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class PasswordForm < LinkedRails.form_parent_class
|
6
|
+
field :email,
|
7
|
+
input_field: LinkedRails::Form::Field::EmailInput,
|
8
|
+
min_count: 1
|
9
|
+
field :password,
|
10
|
+
input_field: LinkedRails::Form::Field::PasswordInput,
|
11
|
+
min_count: 1
|
12
|
+
field :password_confirmation,
|
13
|
+
input_field: LinkedRails::Form::Field::PasswordInput,
|
14
|
+
min_count: 1
|
15
|
+
|
16
|
+
hidden do
|
17
|
+
field :reset_password_token
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class RegistrationForm < LinkedRails.form_parent_class
|
6
|
+
field :email,
|
7
|
+
input_field: LinkedRails::Form::Field::EmailInput,
|
8
|
+
min_count: 1
|
9
|
+
field :password,
|
10
|
+
input_field: LinkedRails::Form::Field::PasswordInput,
|
11
|
+
min_count: 1
|
12
|
+
field :password_confirmation,
|
13
|
+
input_field: LinkedRails::Form::Field::PasswordInput,
|
14
|
+
min_count: 1
|
15
|
+
|
16
|
+
hidden do
|
17
|
+
field :redirect_url
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class SessionForm < LinkedRails.form_parent_class
|
6
|
+
field :email, input_field: LinkedRails::Form::Field::EmailInput, min_count: 1
|
7
|
+
|
8
|
+
hidden do
|
9
|
+
field :redirect_url
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
module OtpHelper
|
6
|
+
def handle_expired_session
|
7
|
+
raise LinkedRails::Auth::Errors::Expired, I18n.t('messages.otp_secrets.expired')
|
8
|
+
end
|
9
|
+
|
10
|
+
def session_from_param(session_param)
|
11
|
+
return {} unless session_param
|
12
|
+
|
13
|
+
JWT.decode(
|
14
|
+
session_param,
|
15
|
+
Doorkeeper::JWT.configuration.secret_key,
|
16
|
+
true,
|
17
|
+
algorithms: [Doorkeeper::JWT.configuration.encryption_method.to_s.upcase]
|
18
|
+
).first || {}
|
19
|
+
rescue JWT::ExpiredSignature
|
20
|
+
handle_expired_session
|
21
|
+
end
|
22
|
+
|
23
|
+
def owner_from_session(session_param)
|
24
|
+
user_id = session_from_param(session_param)['user_id']
|
25
|
+
|
26
|
+
LinkedRails.otp_owner_class.find_by(id: user_id) if user_id
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LinkedRails
|
4
|
+
module Auth
|
5
|
+
class AccessToken < LinkedRails::Resource
|
6
|
+
enhance LinkedRails::Enhancements::Actionable
|
7
|
+
enhance LinkedRails::Enhancements::Creatable
|
8
|
+
enhance LinkedRails::Enhancements::Singularable
|
9
|
+
|
10
|
+
attr_accessor :email, :redirect_url, :password
|
11
|
+
alias root_relative_iri root_relative_singular_iri
|
12
|
+
|
13
|
+
def singular_iri_opts
|
14
|
+
{redirect_url: redirect_url}
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def action_list
|
19
|
+
LinkedRails.access_token_action_list_class
|
20
|
+
end
|
21
|
+
|
22
|
+
def form_class
|
23
|
+
LinkedRails.access_token_form_class
|
24
|
+
end
|
25
|
+
|
26
|
+
def singular_iri_template
|
27
|
+
@singular_iri_template ||= URITemplate.new("/#{singular_route_key}{?redirect_url}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def singular_route_key
|
31
|
+
'u/access_token'
|
32
|
+
end
|
33
|
+
|
34
|
+
def requested_singular_resource(params, _user_context)
|
35
|
+
new(redirect_url: params[:redirect_url])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|