securial 0.7.0 → 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.
- checksums.yaml +4 -4
- data/README.md +2 -5
- data/app/controllers/concerns/securial/identity.rb +17 -16
- data/app/controllers/securial/accounts_controller.rb +2 -2
- data/app/controllers/securial/passwords_controller.rb +2 -2
- data/app/controllers/securial/role_assignments_controller.rb +5 -7
- data/app/controllers/securial/roles_controller.rb +1 -0
- data/app/controllers/securial/sessions_controller.rb +6 -8
- data/app/controllers/securial/users_controller.rb +8 -7
- data/app/mailers/securial/securial_mailer.rb +17 -6
- data/app/models/concerns/securial/password_resettable.rb +1 -1
- data/app/models/securial/application_record.rb +1 -1
- data/app/models/securial/session.rb +16 -5
- data/app/models/securial/user.rb +1 -3
- data/app/views/securial/securial_mailer/forgot_password.html.erb +20 -0
- data/app/views/securial/securial_mailer/forgot_password.text.erb +14 -0
- data/app/views/securial/securial_mailer/sign_in.html.erb +31 -0
- data/app/views/securial/securial_mailer/sign_in.text.erb +17 -0
- data/app/views/securial/securial_mailer/update_account.html.erb +15 -0
- data/app/views/securial/securial_mailer/update_account.text.erb +11 -0
- data/app/views/securial/securial_mailer/welcome.html.erb +11 -0
- data/app/views/securial/securial_mailer/welcome.text.erb +8 -0
- data/app/views/securial/users/_securial_user.json.jbuilder +9 -3
- data/config/routes.rb +5 -1
- data/db/migrate/{20250515104930_create_securial_roles.rb → 20250603130214_create_securial_roles.rb} +0 -2
- data/db/migrate/{20250517155521_create_securial_users.rb → 20250604110520_create_securial_users.rb} +8 -3
- data/db/migrate/{20250519075407_create_securial_sessions.rb → 20250604184841_create_securial_sessions.rb} +4 -0
- data/lib/generators/securial/install/templates/securial_initializer.erb +1 -1
- data/lib/generators/securial/scaffold/templates/controller.erb +1 -0
- data/lib/generators/securial/scaffold/templates/routes.erb +1 -1
- data/lib/securial/auth/auth_encoder.rb +8 -6
- data/lib/securial/auth/session_creator.rb +6 -3
- data/lib/securial/auth/token_generator.rb +26 -0
- data/lib/securial/auth.rb +7 -5
- data/lib/securial/config/configuration.rb +31 -13
- data/lib/securial/config/validation/logger_validation.rb +29 -0
- data/lib/securial/config/validation/mailer_validation.rb +24 -0
- data/lib/securial/config/validation/password_validation.rb +91 -0
- data/lib/securial/config/validation/response_validation.rb +37 -0
- data/lib/securial/config/validation/roles_validation.rb +32 -0
- data/lib/securial/config/validation/security_validation.rb +56 -0
- data/lib/securial/config/validation/session_validation.rb +87 -0
- data/lib/securial/config/validation.rb +16 -239
- data/lib/securial/config.rb +20 -4
- data/lib/securial/engine.rb +5 -79
- data/lib/securial/engine_initializers.rb +33 -0
- data/lib/securial/error/auth.rb +21 -0
- data/lib/securial/error/base_securial_error.rb +16 -0
- data/lib/securial/error/config.rb +37 -0
- data/lib/securial/error.rb +9 -0
- data/lib/securial/helpers/roles_helper.rb +17 -0
- data/lib/securial/helpers.rb +1 -0
- data/lib/securial/logger/broadcaster.rb +36 -24
- data/lib/securial/logger/builder.rb +29 -44
- data/lib/securial/logger/formatter.rb +35 -0
- data/lib/securial/logger.rb +10 -3
- data/lib/securial/middleware/request_tag_logger.rb +39 -0
- data/lib/securial/middleware.rb +13 -0
- data/lib/securial/version.rb +1 -1
- data/lib/securial.rb +2 -26
- metadata +39 -149
- data/app/views/securial/securial_mailer/reset_password.html.erb +0 -5
- data/app/views/securial/securial_mailer/reset_password.text.erb +0 -4
- data/lib/securial/auth/errors.rb +0 -15
- data/lib/securial/config/errors.rb +0 -20
- data/lib/securial/inspectors/route_inspector.rb +0 -52
- data/lib/securial/inspectors.rb +0 -8
- data/lib/securial/key_transformer.rb +0 -32
- data/lib/securial/logger/colors.rb +0 -14
- data/lib/securial/middlewares/request_logger_tag.rb +0 -19
- data/lib/securial/middlewares/transform_request_keys.rb +0 -33
- data/lib/securial/middlewares/transform_response_keys.rb +0 -52
- data/lib/securial/middlewares.rb +0 -10
- data/lib/securial/security/request_rate_limiter.rb +0 -68
- data/lib/securial/security.rb +0 -8
- data/lib/securial/version_checker.rb +0 -31
- /data/db/migrate/{20250518122749_create_securial_role_assignments.rb → 20250604123805_create_securial_role_assignments.rb} +0 -0
@@ -1,19 +0,0 @@
|
|
1
|
-
module Securial
|
2
|
-
module Middlewares
|
3
|
-
class RequestLoggerTag
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
request_id = env["action_dispatch.request_id"] || env["HTTP_X_REQUEST_ID"]
|
10
|
-
tags = ["Securial"]
|
11
|
-
tags << request_id if request_id
|
12
|
-
|
13
|
-
logger = Securial.logger || Rails.logger || ::Logger.new(IO::NULL)
|
14
|
-
tagged_logger = logger.is_a?(ActiveSupport::TaggedLogging) ? logger : ActiveSupport::TaggedLogging.new(logger)
|
15
|
-
tagged_logger.tagged(*tags) { @app.call(env) }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# lib/securial/middlewares/transform_request_keys.rb
|
2
|
-
require "json"
|
3
|
-
|
4
|
-
module Securial
|
5
|
-
module Middlewares
|
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,52 +0,0 @@
|
|
1
|
-
require "json"
|
2
|
-
|
3
|
-
module Securial
|
4
|
-
module Middlewares
|
5
|
-
class TransformResponseKeys
|
6
|
-
def initialize(app)
|
7
|
-
@app = app
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(env)
|
11
|
-
status, headers, response = @app.call(env)
|
12
|
-
|
13
|
-
if json_response?(headers)
|
14
|
-
body = extract_body(response)
|
15
|
-
|
16
|
-
if body.present?
|
17
|
-
format = Securial.configuration.response_keys_format
|
18
|
-
|
19
|
-
# Only transform if not snake_case
|
20
|
-
if format != :snake_case
|
21
|
-
begin
|
22
|
-
transformed = Securial::KeyTransformer.deep_transform_keys(JSON.parse(body)) do |key|
|
23
|
-
Securial::KeyTransformer.camelize(key, format)
|
24
|
-
end
|
25
|
-
|
26
|
-
new_body = [JSON.generate(transformed)]
|
27
|
-
headers["Content-Length"] = new_body.first.bytesize.to_s
|
28
|
-
return [status, headers, new_body]
|
29
|
-
rescue JSON::ParserError
|
30
|
-
# If not valid JSON, fall through and return original response
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
[status, headers, response]
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def json_response?(headers)
|
42
|
-
headers["Content-Type"]&.include?("application/json")
|
43
|
-
end
|
44
|
-
|
45
|
-
def extract_body(response)
|
46
|
-
response_body = ""
|
47
|
-
response.each { |part| response_body << part }
|
48
|
-
response_body
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
data/lib/securial/middlewares.rb
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
require_relative "middlewares/transform_request_keys"
|
2
|
-
require_relative "middlewares/transform_response_keys"
|
3
|
-
require_relative "middlewares/request_logger_tag"
|
4
|
-
|
5
|
-
module Securial
|
6
|
-
module Middleware
|
7
|
-
# This module serves as a namespace for middlewares.
|
8
|
-
# It requires the necessary middleware files to provide functionality.
|
9
|
-
end
|
10
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require "rack/attack"
|
2
|
-
require "securial/config"
|
3
|
-
require "securial/logger"
|
4
|
-
|
5
|
-
module Securial
|
6
|
-
module Security
|
7
|
-
module RequestRateLimiter
|
8
|
-
module_function
|
9
|
-
|
10
|
-
def apply! # rubocop:disable Metrics/MethodLength
|
11
|
-
resp_status = Securial.configuration.rate_limit_response_status
|
12
|
-
resp_message = Securial.configuration.rate_limit_response_message
|
13
|
-
# Throttle login attempts by IP
|
14
|
-
Rack::Attack.throttle("securial/logins/ip",
|
15
|
-
limit: ->(_req) { Securial.configuration.rate_limit_requests_per_minute },
|
16
|
-
period: 1.minute
|
17
|
-
) do |req|
|
18
|
-
if req.path.include?("sessions/login") && req.post?
|
19
|
-
req.ip
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# Throttle login attempts by username/email
|
24
|
-
Rack::Attack.throttle("securial/logins/email",
|
25
|
-
limit: ->(_req) { Securial.configuration.rate_limit_requests_per_minute },
|
26
|
-
period: 1.minute
|
27
|
-
) do |req|
|
28
|
-
if req.path.include?("sessions/login") && req.post?
|
29
|
-
req.params["email_address"].to_s.downcase.strip
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Throttle password reset requests by IP
|
34
|
-
Rack::Attack.throttle("securial/password_resets/ip",
|
35
|
-
limit: ->(_req) { Securial.configuration.rate_limit_requests_per_minute },
|
36
|
-
period: 1.minute
|
37
|
-
) do |req|
|
38
|
-
if req.path.include?("password/forgot") && req.post?
|
39
|
-
req.ip
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Throttle password reset requests by email
|
44
|
-
Rack::Attack.throttle("securial/password_resets/email",
|
45
|
-
limit: ->(_req) { Securial.configuration.rate_limit_requests_per_minute },
|
46
|
-
period: 1.minute
|
47
|
-
) do |req|
|
48
|
-
if req.path.include?("password/forgot") && req.post?
|
49
|
-
req.params["email_address"].to_s.downcase.strip
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Custom response for throttled requests
|
54
|
-
Rack::Attack.throttled_responder = lambda do |request|
|
55
|
-
retry_after = (request.env["rack.attack.match_data"] || {})[:period]
|
56
|
-
[
|
57
|
-
resp_status,
|
58
|
-
{
|
59
|
-
"Content-Type" => "application/json",
|
60
|
-
"Retry-After" => retry_after.to_s,
|
61
|
-
},
|
62
|
-
[{ error: resp_message }.to_json]
|
63
|
-
]
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/lib/securial/security.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require "net/http"
|
2
|
-
require "json"
|
3
|
-
|
4
|
-
module Securial
|
5
|
-
module VersionChecker
|
6
|
-
module_function
|
7
|
-
|
8
|
-
def check_latest_version
|
9
|
-
begin
|
10
|
-
rubygems_api_url = "https://rubygems.org/api/v1/versions/securial/latest.json"
|
11
|
-
uri = URI(rubygems_api_url)
|
12
|
-
http = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", open_timeout: 5, read_timeout: 5)
|
13
|
-
response = http.request(Net::HTTP::Get.new(uri))
|
14
|
-
latest = JSON.parse(response.body)["version"]
|
15
|
-
|
16
|
-
current = Securial::VERSION
|
17
|
-
if Gem::Version.new(latest) > Gem::Version.new(current)
|
18
|
-
Securial.logger.info "A newer version (#{latest}) of Securial is available. You are using #{current}."
|
19
|
-
Securial.logger.info "Please consider updating!"
|
20
|
-
Securial.logger.debug "You can update Securial by running the following command in your terminal:"
|
21
|
-
Securial.logger.debug "`bundle update securial`"
|
22
|
-
else
|
23
|
-
Securial.logger.info "You are using the latest version of Securial (#{current})."
|
24
|
-
Securial.logger.debug "No updates available at this time."
|
25
|
-
end
|
26
|
-
rescue => e
|
27
|
-
Securial.logger.debug("Version check failed: #{e.message}")
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|