linked_rails-auth 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +28 -0
  4. data/Rakefile +34 -0
  5. data/app/actions/linked_rails/auth/access_token_action_list.rb +16 -0
  6. data/app/actions/linked_rails/auth/confirmation_action_list.rb +17 -0
  7. data/app/actions/linked_rails/auth/otp_attempt_action_list.rb +13 -0
  8. data/app/actions/linked_rails/auth/otp_secret_action_list.rb +31 -0
  9. data/app/actions/linked_rails/auth/password_action_list.rb +25 -0
  10. data/app/actions/linked_rails/auth/registration_action_list.rb +15 -0
  11. data/app/actions/linked_rails/auth/session_action_list.rb +22 -0
  12. data/app/actions/linked_rails/auth/unlock_action_list.rb +17 -0
  13. data/app/controllers/linked_rails/auth/access_tokens_controller.rb +131 -0
  14. data/app/controllers/linked_rails/auth/confirmations_controller.rb +87 -0
  15. data/app/controllers/linked_rails/auth/otp_attempts_controller.rb +21 -0
  16. data/app/controllers/linked_rails/auth/otp_secrets_controller.rb +40 -0
  17. data/app/controllers/linked_rails/auth/passwords_controller.rb +63 -0
  18. data/app/controllers/linked_rails/auth/registrations_controller.rb +33 -0
  19. data/app/controllers/linked_rails/auth/sessions_controller.rb +55 -0
  20. data/app/controllers/linked_rails/auth/unlocks_controller.rb +44 -0
  21. data/app/forms/linked_rails/auth/access_token_form.rb +20 -0
  22. data/app/forms/linked_rails/auth/confirmation_form.rb +9 -0
  23. data/app/forms/linked_rails/auth/otp_attempt_form.rb +9 -0
  24. data/app/forms/linked_rails/auth/otp_secret_form.rb +12 -0
  25. data/app/forms/linked_rails/auth/password_form.rb +21 -0
  26. data/app/forms/linked_rails/auth/registration_form.rb +21 -0
  27. data/app/forms/linked_rails/auth/session_form.rb +13 -0
  28. data/app/forms/linked_rails/auth/unlock_form.rb +9 -0
  29. data/app/helpers/linked_rails/auth/otp_helper.rb +30 -0
  30. data/app/models/linked_rails/auth/access_token.rb +40 -0
  31. data/app/models/linked_rails/auth/confirmation.rb +70 -0
  32. data/app/models/linked_rails/auth/guest_user.rb +29 -0
  33. data/app/models/linked_rails/auth/otp_attempt.rb +41 -0
  34. data/app/models/linked_rails/auth/otp_base.rb +57 -0
  35. data/app/models/linked_rails/auth/otp_secret.rb +91 -0
  36. data/app/models/linked_rails/auth/password.rb +47 -0
  37. data/app/models/linked_rails/auth/registration.rb +39 -0
  38. data/app/models/linked_rails/auth/session.rb +46 -0
  39. data/app/models/linked_rails/auth/unlock.rb +59 -0
  40. data/app/policies/linked_rails/auth/access_token_policy.rb +17 -0
  41. data/app/policies/linked_rails/auth/confirmation_policy.rb +17 -0
  42. data/app/policies/linked_rails/auth/otp_attempt_policy.rb +17 -0
  43. data/app/policies/linked_rails/auth/otp_secret_policy.rb +37 -0
  44. data/app/policies/linked_rails/auth/password_policy.rb +23 -0
  45. data/app/policies/linked_rails/auth/registration_policy.rb +13 -0
  46. data/app/policies/linked_rails/auth/session_policy.rb +17 -0
  47. data/app/policies/linked_rails/auth/unlock_policy.rb +21 -0
  48. data/app/serializers/linked_rails/auth/access_token_serializer.rb +11 -0
  49. data/app/serializers/linked_rails/auth/confirmation_serializer.rb +10 -0
  50. data/app/serializers/linked_rails/auth/otp_attempt_serializer.rb +12 -0
  51. data/app/serializers/linked_rails/auth/otp_secret_serializer.rb +14 -0
  52. data/app/serializers/linked_rails/auth/password_serializer.rb +18 -0
  53. data/app/serializers/linked_rails/auth/registration_serializer.rb +12 -0
  54. data/app/serializers/linked_rails/auth/session_serializer.rb +10 -0
  55. data/app/serializers/linked_rails/auth/unlock_serializer.rb +9 -0
  56. data/config/routes.rb +4 -0
  57. data/lib/generators/linked_rails/auth/install_generator.rb +155 -0
  58. data/lib/generators/linked_rails/auth/templates/README +2 -0
  59. data/lib/generators/linked_rails/auth/templates/doorkeeper_jwt_initializer.rb +52 -0
  60. data/lib/generators/linked_rails/auth/templates/locales.yml +39 -0
  61. data/lib/generators/linked_rails/auth/templates/migration.rb.erb +20 -0
  62. data/lib/linked_rails/auth/auth_helper.rb +101 -0
  63. data/lib/linked_rails/auth/controller/error_handling.rb +17 -0
  64. data/lib/linked_rails/auth/controller.rb +16 -0
  65. data/lib/linked_rails/auth/engine.rb +8 -0
  66. data/lib/linked_rails/auth/errors/account_locked.rb +10 -0
  67. data/lib/linked_rails/auth/errors/expired.rb +10 -0
  68. data/lib/linked_rails/auth/errors/unauthorized.rb +10 -0
  69. data/lib/linked_rails/auth/errors/unknown_email.rb +14 -0
  70. data/lib/linked_rails/auth/errors/wrong_password.rb +14 -0
  71. data/lib/linked_rails/auth/errors.rb +7 -0
  72. data/lib/linked_rails/auth/routes.rb +86 -0
  73. data/lib/linked_rails/auth/version.rb +7 -0
  74. data/lib/linked_rails/auth.rb +46 -0
  75. data/lib/tasks/linked_rails/auth_tasks.rake +6 -0
  76. 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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Auth
5
+ class ConfirmationForm < LinkedRails.form_parent_class
6
+ field :email, input_field: LinkedRails::Form::Field::EmailInput, min_count: 1
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Auth
5
+ class OtpAttemptForm < LinkedRails.form_parent_class
6
+ field :otp_attempt, description: '', min_count: 1
7
+ end
8
+ end
9
+ 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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Auth
5
+ class UnlockForm < LinkedRails.form_parent_class
6
+ field :email, input_field: LinkedRails::Form::Field::EmailInput, min_count: 1
7
+ end
8
+ end
9
+ 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