linked_rails-auth 0.0.1

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.
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