securial 0.6.1 → 0.8.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -5
  3. data/app/controllers/concerns/securial/identity.rb +17 -16
  4. data/app/controllers/securial/accounts_controller.rb +2 -2
  5. data/app/controllers/securial/passwords_controller.rb +2 -2
  6. data/app/controllers/securial/role_assignments_controller.rb +5 -7
  7. data/app/controllers/securial/roles_controller.rb +1 -0
  8. data/app/controllers/securial/sessions_controller.rb +6 -8
  9. data/app/controllers/securial/status_controller.rb +1 -1
  10. data/app/controllers/securial/users_controller.rb +8 -7
  11. data/app/mailers/securial/securial_mailer.rb +17 -6
  12. data/app/models/concerns/securial/password_resettable.rb +1 -1
  13. data/app/models/securial/application_record.rb +1 -1
  14. data/app/models/securial/role.rb +1 -1
  15. data/app/models/securial/session.rb +16 -5
  16. data/app/models/securial/user.rb +4 -6
  17. data/app/views/securial/securial_mailer/forgot_password.html.erb +20 -0
  18. data/app/views/securial/securial_mailer/forgot_password.text.erb +14 -0
  19. data/app/views/securial/securial_mailer/sign_in.html.erb +31 -0
  20. data/app/views/securial/securial_mailer/sign_in.text.erb +17 -0
  21. data/app/views/securial/securial_mailer/update_account.html.erb +15 -0
  22. data/app/views/securial/securial_mailer/update_account.text.erb +11 -0
  23. data/app/views/securial/securial_mailer/welcome.html.erb +11 -0
  24. data/app/views/securial/securial_mailer/welcome.text.erb +8 -0
  25. data/app/views/securial/users/_securial_user.json.jbuilder +9 -3
  26. data/config/routes.rb +5 -1
  27. data/db/migrate/{20250515104930_create_securial_roles.rb → 20250603130214_create_securial_roles.rb} +0 -2
  28. data/db/migrate/{20250517155521_create_securial_users.rb → 20250604110520_create_securial_users.rb} +8 -3
  29. data/db/migrate/{20250519075407_create_securial_sessions.rb → 20250604184841_create_securial_sessions.rb} +4 -0
  30. data/lib/generators/securial/install/templates/securial_initializer.erb +2 -2
  31. data/lib/generators/securial/scaffold/templates/controller.erb +1 -0
  32. data/lib/generators/securial/scaffold/templates/routes.erb +1 -1
  33. data/lib/securial/auth/auth_encoder.rb +42 -43
  34. data/lib/securial/auth/session_creator.rb +15 -12
  35. data/lib/securial/auth/token_generator.rb +26 -0
  36. data/lib/securial/auth.rb +12 -0
  37. data/lib/securial/config/configuration.rb +33 -15
  38. data/lib/securial/config/validation/logger_validation.rb +29 -0
  39. data/lib/securial/config/validation/mailer_validation.rb +24 -0
  40. data/lib/securial/config/validation/password_validation.rb +91 -0
  41. data/lib/securial/config/validation/response_validation.rb +37 -0
  42. data/lib/securial/config/validation/roles_validation.rb +32 -0
  43. data/lib/securial/config/validation/security_validation.rb +56 -0
  44. data/lib/securial/config/validation/session_validation.rb +87 -0
  45. data/lib/securial/config/validation.rb +16 -239
  46. data/lib/securial/config.rb +26 -0
  47. data/lib/securial/engine.rb +7 -70
  48. data/lib/securial/engine_initializers.rb +33 -0
  49. data/lib/securial/error/auth.rb +21 -0
  50. data/lib/securial/error/base_securial_error.rb +16 -0
  51. data/lib/securial/error/config.rb +37 -0
  52. data/lib/securial/error.rb +9 -0
  53. data/lib/securial/helpers/normalizing_helper.rb +11 -9
  54. data/lib/securial/helpers/regex_helper.rb +12 -10
  55. data/lib/securial/helpers/roles_helper.rb +17 -0
  56. data/lib/securial/helpers.rb +10 -0
  57. data/lib/securial/logger/broadcaster.rb +60 -0
  58. data/lib/securial/logger/builder.rb +45 -0
  59. data/lib/securial/logger/formatter.rb +35 -0
  60. data/lib/securial/logger.rb +7 -63
  61. data/lib/securial/middleware/request_tag_logger.rb +39 -0
  62. data/lib/securial/middleware.rb +13 -0
  63. data/lib/securial/version.rb +1 -1
  64. data/lib/securial.rb +2 -20
  65. metadata +45 -150
  66. data/app/views/securial/securial_mailer/reset_password.html.erb +0 -5
  67. data/app/views/securial/securial_mailer/reset_password.text.erb +0 -4
  68. data/lib/securial/auth/_index.rb +0 -3
  69. data/lib/securial/auth/errors.rb +0 -15
  70. data/lib/securial/config/_index.rb +0 -3
  71. data/lib/securial/config/errors.rb +0 -20
  72. data/lib/securial/helpers/_index.rb +0 -2
  73. data/lib/securial/inspectors/_index.rb +0 -1
  74. data/lib/securial/inspectors/route_inspector.rb +0 -52
  75. data/lib/securial/key_transformer.rb +0 -32
  76. data/lib/securial/middleware/_index.rb +0 -3
  77. data/lib/securial/middleware/request_logger_tag.rb +0 -18
  78. data/lib/securial/middleware/transform_request_keys.rb +0 -33
  79. data/lib/securial/middleware/transform_response_keys.rb +0 -45
  80. data/lib/securial/rack_attack.rb +0 -48
  81. /data/db/migrate/{20250518122749_create_securial_role_assignments.rb → 20250604123805_create_securial_role_assignments.rb} +0 -0
  82. /data/lib/generators/securial/install/{views_generastor.rb → views_generator.rb} +0 -0
@@ -1,18 +0,0 @@
1
- module Securial
2
- module Middleware
3
- class RequestLoggerTag
4
- def initialize(app)
5
- @app = app
6
- end
7
-
8
- def call(env)
9
- request = ActionDispatch::Request.new(env)
10
- request_id = request.request_id || SecureRandom.uuid
11
-
12
- Securial::ENGINE_LOGGER.tagged("Securial", "RequestID:#{request_id}") do
13
- @app.call(env)
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,33 +0,0 @@
1
- # lib/securial/middleware/transform_request_keys.rb
2
- require "json"
3
-
4
- module Securial
5
- module Middleware
6
- class TransformRequestKeys
7
- def initialize(app)
8
- @app = app
9
- end
10
-
11
- def call(env)
12
- if env["CONTENT_TYPE"]&.include?("application/json") && Securial.configuration.response_keys_format != :snake_case
13
- req = Rack::Request.new(env)
14
- if (req.body&.size || 0) > 0
15
- raw = req.body.read
16
- req.body.rewind
17
- begin
18
- parsed = JSON.parse(raw)
19
- transformed = Securial::KeyTransformer.deep_transform_keys(parsed) do |key|
20
- Securial::KeyTransformer.underscore(key)
21
- end
22
- env["rack.input"] = StringIO.new(JSON.dump(transformed))
23
- env["rack.input"].rewind
24
- rescue JSON::ParserError
25
- # noop
26
- end
27
- end
28
- end
29
- @app.call(env)
30
- end
31
- end
32
- end
33
- end
@@ -1,45 +0,0 @@
1
- # lib/securial/middleware/transform_response_keys.rb
2
- require "json"
3
-
4
- module Securial
5
- module Middleware
6
- class TransformResponseKeys
7
- def initialize(app)
8
- @app = app
9
- end
10
-
11
- def call(env)
12
- status, headers, response = @app.call(env)
13
-
14
- if json_response?(headers)
15
- body = extract_body(response)
16
-
17
- if body.present?
18
- format = Securial.configuration.response_keys_format
19
- transformed = KeyTransformer.deep_transform_keys(JSON.parse(body)) do |key|
20
- KeyTransformer.camelize(key, format)
21
- end
22
-
23
- new_body = [JSON.generate(transformed)]
24
- headers["Content-Length"] = new_body.first.bytesize.to_s
25
- return [status, headers, new_body]
26
- end
27
- end
28
-
29
- [status, headers, response]
30
- end
31
-
32
- private
33
-
34
- def json_response?(headers)
35
- headers["Content-Type"]&.include?("application/json")
36
- end
37
-
38
- def extract_body(response)
39
- response_body = ""
40
- response.each { |part| response_body << part }
41
- response_body
42
- end
43
- end
44
- end
45
- end
@@ -1,48 +0,0 @@
1
- Rails.application.config.to_prepare do
2
- class Rack::Attack
3
- limit = Securial.configuration.rate_limit_requests_per_minute
4
- resp_status = Securial.configuration.rate_limit_response_status
5
- resp_message = Securial.configuration.rate_limit_response_message
6
-
7
- ### Throttle login attempts by IP ###
8
- throttle("securial/logins/ip", limit: limit, period: 1.minute) do |req|
9
- if req.path.include?("sessions/login") && req.post?
10
- req.ip
11
- end
12
- end
13
-
14
- ### Throttle login attempts by username ###
15
- throttle("securial/logins/email", limit: 5, period: 1.minute) do |req|
16
- if req.path.include?("sessions/login") && req.post?
17
- req.params["email_address"].to_s.downcase.strip
18
- end
19
- end
20
-
21
- ### TODO: Add throttling for other endpoints as needed ###
22
- # Example: Throttle password reset requests by email
23
- throttle("securial/password_resets/ip", limit: 5, period: 1.minute) do |req|
24
- if req.path.include?("password/forgot") && req.post?
25
- req.ip
26
- end
27
- end
28
-
29
- throttle("securial/password_resets/email", limit: 5, period: 1.minute) do |req|
30
- if req.path.include?("password/forgot") && req.post?
31
- req.params["email_address"].to_s.downcase.strip
32
- end
33
- end
34
-
35
- ### Custom response ###
36
- self.throttled_responder = lambda do |request|
37
- retry_after = (request.env["rack.attack.match_data"] || {})[:period]
38
- [
39
- resp_status,
40
- {
41
- "Content-Type" => "application/json",
42
- "Retry-After" => retry_after.to_s,
43
- },
44
- [{ error: resp_message }.to_json]
45
- ]
46
- end
47
- end
48
- end