securial 1.0.1 → 1.0.3
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/.yardopts +4 -0
- data/README.md +19 -12
- data/app/controllers/concerns/securial/identity.rb +91 -2
- data/app/controllers/securial/accounts_controller.rb +68 -5
- data/app/controllers/securial/application_controller.rb +34 -2
- data/app/controllers/securial/passwords_controller.rb +44 -4
- data/app/controllers/securial/role_assignments_controller.rb +55 -4
- data/app/controllers/securial/roles_controller.rb +54 -0
- data/app/controllers/securial/sessions_controller.rb +77 -3
- data/app/controllers/securial/status_controller.rb +24 -0
- data/app/controllers/securial/users_controller.rb +54 -0
- data/app/jobs/securial/application_job.rb +9 -0
- data/app/mailers/securial/application_mailer.rb +12 -0
- data/app/mailers/securial/securial_mailer.rb +30 -0
- data/app/models/concerns/securial/password_resettable.rb +70 -0
- data/app/models/securial/application_record.rb +19 -0
- data/app/models/securial/current.rb +13 -0
- data/app/models/securial/role.rb +17 -0
- data/app/models/securial/role_assignment.rb +16 -0
- data/app/models/securial/session.rb +79 -1
- data/app/models/securial/user.rb +34 -0
- data/lib/generators/factory_bot/model/model_generator.rb +1 -0
- data/lib/securial/auth/auth_encoder.rb +78 -0
- data/lib/securial/auth/session_creator.rb +49 -0
- data/lib/securial/auth/token_generator.rb +74 -0
- data/lib/securial/auth.rb +44 -6
- data/lib/securial/cli.rb +124 -0
- data/lib/securial/config/signature.rb +116 -5
- data/lib/securial/config/validation.rb +91 -0
- data/lib/securial/config.rb +49 -2
- data/lib/securial/engine.rb +41 -0
- data/lib/securial/error/auth.rb +52 -0
- data/lib/securial/error/base_securial_error.rb +51 -0
- data/lib/securial/error/config.rb +33 -0
- data/lib/securial/error.rb +33 -3
- data/lib/securial/helpers/key_transformer.rb +106 -0
- data/lib/securial/helpers/normalizing_helper.rb +69 -0
- data/lib/securial/helpers/regex_helper.rb +122 -0
- data/lib/securial/helpers/roles_helper.rb +71 -2
- data/lib/securial/helpers.rb +48 -4
- data/lib/securial/logger/broadcaster.rb +89 -1
- data/lib/securial/logger/builder.rb +54 -1
- data/lib/securial/logger/formatter.rb +73 -0
- data/lib/securial/logger.rb +42 -1
- data/lib/securial/middleware/request_tag_logger.rb +80 -0
- data/lib/securial/middleware/response_headers.rb +51 -3
- data/lib/securial/middleware/transform_request_keys.rb +143 -20
- data/lib/securial/middleware/transform_response_keys.rb +84 -4
- data/lib/securial/middleware.rb +40 -9
- data/lib/securial/security/request_rate_limiter.rb +47 -1
- data/lib/securial/security.rb +37 -6
- data/lib/securial/version.rb +8 -1
- data/lib/securial.rb +36 -0
- metadata +21 -15
@@ -1,14 +1,74 @@
|
|
1
|
+
# @title Securial Configuration Signature
|
2
|
+
#
|
3
|
+
# Configuration schema definition and validation rules for the Securial framework.
|
4
|
+
#
|
5
|
+
# This module defines the complete configuration schema for Securial, including
|
6
|
+
# all available configuration options, their types, default values, and validation
|
7
|
+
# rules. It serves as the single source of truth for what configuration options
|
8
|
+
# are available and how they should be validated.
|
9
|
+
#
|
10
|
+
# @example Getting the complete configuration schema
|
11
|
+
# schema = Securial::Config::Signature.config_signature
|
12
|
+
# # => { app_name: { type: String, required: true, default: "Securial" }, ... }
|
13
|
+
#
|
14
|
+
# @example Getting default configuration values
|
15
|
+
# defaults = Securial::Config::Signature.default_config_attributes
|
16
|
+
# # => { app_name: "Securial", log_to_file: true, ... }
|
17
|
+
#
|
1
18
|
module Securial
|
2
19
|
module Config
|
20
|
+
# Configuration schema definition and validation rules.
|
21
|
+
#
|
22
|
+
# This module provides the complete schema for Securial's configuration system,
|
23
|
+
# defining all available options, their types, validation rules, and default values.
|
24
|
+
# It's used by the configuration system to validate user-provided settings.
|
25
|
+
#
|
3
26
|
module Signature
|
4
|
-
|
27
|
+
# Valid log levels for the logging system.
|
28
|
+
#
|
29
|
+
# @return [Array<Symbol>] Available log levels from least to most severe
|
30
|
+
#
|
31
|
+
LOG_LEVELS = %i[debug info warn error fatal unknown].freeze
|
32
|
+
|
33
|
+
# Supported JWT signing algorithms for session tokens.
|
34
|
+
#
|
35
|
+
# @return [Array<Symbol>] HMAC algorithms supported for JWT signing
|
36
|
+
#
|
5
37
|
SESSION_ALGORITHMS = %i[hs256 hs384 hs512].freeze
|
6
|
-
|
7
|
-
|
38
|
+
|
39
|
+
# Security header configuration options.
|
40
|
+
#
|
41
|
+
# @return [Array<Symbol>] Available security header policies
|
42
|
+
#
|
43
|
+
SECURITY_HEADERS = %i[strict default none].freeze
|
44
|
+
|
45
|
+
# Timestamp inclusion options for API responses.
|
46
|
+
#
|
47
|
+
# @return [Array<Symbol>] Who should see timestamps in responses
|
48
|
+
#
|
49
|
+
TIMESTAMP_OPTIONS = %i[all admins_only none].freeze
|
50
|
+
|
51
|
+
# Available key format transformations for API responses.
|
52
|
+
#
|
53
|
+
# @return [Array<Symbol>] Supported key case formats
|
54
|
+
#
|
8
55
|
RESPONSE_KEYS_FORMATS = %i[snake_case lowerCamelCase UpperCamelCase].freeze
|
9
56
|
|
10
57
|
extend self
|
11
58
|
|
59
|
+
# Returns the complete configuration schema for Securial.
|
60
|
+
#
|
61
|
+
# Combines all configuration sections into a single schema hash that defines
|
62
|
+
# every available configuration option, its type, validation rules, and
|
63
|
+
# default value.
|
64
|
+
#
|
65
|
+
# @return [Hash] Complete configuration schema with validation rules
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# schema = config_signature
|
69
|
+
# app_name_config = schema[:app_name]
|
70
|
+
# # => { type: String, required: true, default: "Securial" }
|
71
|
+
#
|
12
72
|
def config_signature
|
13
73
|
[
|
14
74
|
general_signature,
|
@@ -22,6 +82,18 @@ module Securial
|
|
22
82
|
].reduce({}, :merge)
|
23
83
|
end
|
24
84
|
|
85
|
+
# Extracts default values from the configuration schema.
|
86
|
+
#
|
87
|
+
# Transforms the complete configuration schema to return only the default
|
88
|
+
# values for each configuration option, suitable for initializing a new
|
89
|
+
# configuration instance.
|
90
|
+
#
|
91
|
+
# @return [Hash] Default values for all configuration options
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
# defaults = default_config_attributes
|
95
|
+
# # => { app_name: "Securial", session_expiration_duration: 3.minutes, ... }
|
96
|
+
#
|
25
97
|
def default_config_attributes
|
26
98
|
config_signature.transform_values do |options|
|
27
99
|
options[:default]
|
@@ -30,12 +102,22 @@ module Securial
|
|
30
102
|
|
31
103
|
private
|
32
104
|
|
105
|
+
# General application configuration options.
|
106
|
+
#
|
107
|
+
# @return [Hash] Schema for general application settings
|
108
|
+
# @api private
|
109
|
+
#
|
33
110
|
def general_signature
|
34
111
|
{
|
35
112
|
app_name: { type: String, required: true, default: "Securial" },
|
36
113
|
}
|
37
114
|
end
|
38
115
|
|
116
|
+
# Logging system configuration options.
|
117
|
+
#
|
118
|
+
# @return [Hash] Schema for logging configuration
|
119
|
+
# @api private
|
120
|
+
#
|
39
121
|
def logger_signature
|
40
122
|
{
|
41
123
|
log_to_file: { type: [TrueClass, FalseClass], required: true, default: Rails.env.test? ? false : true },
|
@@ -45,12 +127,22 @@ module Securial
|
|
45
127
|
}
|
46
128
|
end
|
47
129
|
|
130
|
+
# User role and permission configuration options.
|
131
|
+
#
|
132
|
+
# @return [Hash] Schema for role management settings
|
133
|
+
# @api private
|
134
|
+
#
|
48
135
|
def roles_signature
|
49
136
|
{
|
50
137
|
admin_role: { type: Symbol, required: true, default: :admin },
|
51
138
|
}
|
52
139
|
end
|
53
140
|
|
141
|
+
# Session and JWT token configuration options.
|
142
|
+
#
|
143
|
+
# @return [Hash] Schema for session management settings
|
144
|
+
# @api private
|
145
|
+
#
|
54
146
|
def session_signature
|
55
147
|
{
|
56
148
|
session_expiration_duration: { type: ActiveSupport::Duration, required: true, default: 3.minutes },
|
@@ -60,6 +152,11 @@ module Securial
|
|
60
152
|
}
|
61
153
|
end
|
62
154
|
|
155
|
+
# Email and notification configuration options.
|
156
|
+
#
|
157
|
+
# @return [Hash] Schema for mailer settings
|
158
|
+
# @api private
|
159
|
+
#
|
63
160
|
def mailer_signature
|
64
161
|
{
|
65
162
|
mailer_sender: { type: String, required: true, default: "no-reply@example.com" },
|
@@ -73,6 +170,11 @@ module Securial
|
|
73
170
|
}
|
74
171
|
end
|
75
172
|
|
173
|
+
# Password policy and security configuration options.
|
174
|
+
#
|
175
|
+
# @return [Hash] Schema for password management settings
|
176
|
+
# @api private
|
177
|
+
#
|
76
178
|
def password_signature
|
77
179
|
{
|
78
180
|
password_min_length: { type: Numeric, required: true, default: 8 },
|
@@ -85,14 +187,23 @@ module Securial
|
|
85
187
|
}
|
86
188
|
end
|
87
189
|
|
190
|
+
# API response formatting configuration options.
|
191
|
+
#
|
192
|
+
# @return [Hash] Schema for response formatting settings
|
193
|
+
# @api private
|
194
|
+
#
|
88
195
|
def response_signature
|
89
196
|
{
|
90
|
-
response_keys_format: { type: Symbol, required: true, allowed_values:
|
91
|
-
RESPONSE_KEYS_FORMATS, default: :snake_case, },
|
197
|
+
response_keys_format: { type: Symbol, required: true, allowed_values: RESPONSE_KEYS_FORMATS, default: :snake_case },
|
92
198
|
timestamps_in_response: { type: Symbol, required: true, allowed_values: TIMESTAMP_OPTIONS, default: :all },
|
93
199
|
}
|
94
200
|
end
|
95
201
|
|
202
|
+
# Security and rate limiting configuration options.
|
203
|
+
#
|
204
|
+
# @return [Hash] Schema for security settings
|
205
|
+
# @api private
|
206
|
+
#
|
96
207
|
def security_signature
|
97
208
|
{
|
98
209
|
security_headers: { type: Symbol, required: true, allowed_values: SECURITY_HEADERS, default: :strict },
|
@@ -1,9 +1,51 @@
|
|
1
|
+
# @title Securial Configuration Validation
|
2
|
+
#
|
3
|
+
# Configuration validation utilities for the Securial framework.
|
4
|
+
#
|
5
|
+
# This module provides comprehensive validation for Securial configuration settings,
|
6
|
+
# ensuring that all required fields are present, types are correct, values are within
|
7
|
+
# acceptable ranges, and cross-field dependencies are satisfied. It validates against
|
8
|
+
# the schema defined in Securial::Config::Signature.
|
9
|
+
#
|
10
|
+
# @example Validating a configuration object
|
11
|
+
# config = Securial::Configuration.new
|
12
|
+
# begin
|
13
|
+
# Securial::Config::Validation.validate_all!(config)
|
14
|
+
# rescue Securial::Error::Config::InvalidConfigurationError => e
|
15
|
+
# Rails.logger.error("Configuration error: #{e.message}")
|
16
|
+
# end
|
17
|
+
#
|
1
18
|
require "securial/logger"
|
2
19
|
|
3
20
|
module Securial
|
4
21
|
module Config
|
22
|
+
# Configuration validation and verification utilities.
|
23
|
+
#
|
24
|
+
# This module provides methods to validate Securial configuration objects
|
25
|
+
# against the defined schema, ensuring type safety, required field presence,
|
26
|
+
# and business logic constraints are met before the application starts.
|
27
|
+
#
|
5
28
|
module Validation
|
6
29
|
extend self
|
30
|
+
|
31
|
+
# Validates all configuration settings against the schema.
|
32
|
+
#
|
33
|
+
# Performs comprehensive validation of the provided configuration object,
|
34
|
+
# including required field checks, type validation, value constraints,
|
35
|
+
# and cross-field dependency validation.
|
36
|
+
#
|
37
|
+
# @param [Securial::Configuration] securial_config The configuration object to validate
|
38
|
+
# @return [void]
|
39
|
+
# @raise [Securial::Error::Config::InvalidConfigurationError] If any validation fails
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# config = Securial::Configuration.new
|
43
|
+
# config.app_name = "MyApp"
|
44
|
+
# config.session_secret = "my-secret-key"
|
45
|
+
#
|
46
|
+
# Validation.validate_all!(config)
|
47
|
+
# # Configuration is valid and ready to use
|
48
|
+
#
|
7
49
|
def validate_all!(securial_config)
|
8
50
|
signature = Securial::Config::Signature.config_signature
|
9
51
|
|
@@ -14,13 +56,26 @@ module Securial
|
|
14
56
|
|
15
57
|
private
|
16
58
|
|
59
|
+
# Validates that all required configuration fields are present.
|
60
|
+
#
|
61
|
+
# Checks both unconditionally required fields and conditionally required
|
62
|
+
# fields based on other configuration values.
|
63
|
+
#
|
64
|
+
# @param [Hash] signature The configuration schema from Signature
|
65
|
+
# @param [Securial::Configuration] config The configuration object to validate
|
66
|
+
# @return [void]
|
67
|
+
# @raise [Securial::Error::Config::InvalidConfigurationError] If required fields are missing
|
68
|
+
# @api private
|
69
|
+
#
|
17
70
|
def validate_required_fields!(signature, config)
|
18
71
|
signature.each do |key, options|
|
19
72
|
value = config.send(key)
|
20
73
|
required = options[:required]
|
74
|
+
|
21
75
|
if required == true && value.nil?
|
22
76
|
raise_error("#{key} is required but not provided.")
|
23
77
|
elsif required.is_a?(String)
|
78
|
+
# Handle conditional requirements based on other config values
|
24
79
|
dynamic_required = config.send(required)
|
25
80
|
signature[key][:required] = dynamic_required
|
26
81
|
if dynamic_required && value.nil?
|
@@ -30,36 +85,72 @@ module Securial
|
|
30
85
|
end
|
31
86
|
end
|
32
87
|
|
88
|
+
# Validates types and value constraints for configuration fields.
|
89
|
+
#
|
90
|
+
# Ensures that configuration values match their expected types and fall
|
91
|
+
# within acceptable ranges or allowed value sets.
|
92
|
+
#
|
93
|
+
# @param [Hash] signature The configuration schema from Signature
|
94
|
+
# @param [Securial::Configuration] config The configuration object to validate
|
95
|
+
# @return [void]
|
96
|
+
# @raise [Securial::Error::Config::InvalidConfigurationError] If types or values are invalid
|
97
|
+
# @api private
|
98
|
+
#
|
33
99
|
def validate_types_and_values!(signature, config)
|
34
100
|
signature.each do |key, options|
|
35
101
|
next unless signature[key][:required]
|
102
|
+
|
36
103
|
value = config.send(key)
|
37
104
|
types = Array(options[:type])
|
38
105
|
|
106
|
+
# Type validation
|
39
107
|
unless types.any? { |type| value.is_a?(type) }
|
40
108
|
raise_error("#{key} must be of type(s) #{types.join(', ')}, but got #{value.class}.")
|
41
109
|
end
|
42
110
|
|
111
|
+
# Duration-specific validation
|
43
112
|
if options[:type] == ActiveSupport::Duration && value <= 0
|
44
113
|
raise_error("#{key} must be a positive duration, but got #{value}.")
|
45
114
|
end
|
46
115
|
|
116
|
+
# Numeric value validation
|
47
117
|
if options[:type] == Numeric && value < 0
|
48
118
|
raise_error("#{key} must be a non-negative numeric value, but got #{value}.")
|
49
119
|
end
|
50
120
|
|
121
|
+
# Allowed values validation
|
51
122
|
if options[:allowed_values] && options[:allowed_values].exclude?(value)
|
52
123
|
raise_error("#{key} must be one of #{options[:allowed_values].join(', ')}, but got #{value}.")
|
53
124
|
end
|
54
125
|
end
|
55
126
|
end
|
56
127
|
|
128
|
+
# Validates password length configuration constraints.
|
129
|
+
#
|
130
|
+
# Ensures that password minimum length does not exceed maximum length,
|
131
|
+
# which would create an impossible constraint for users.
|
132
|
+
#
|
133
|
+
# @param [Securial::Configuration] config The configuration object to validate
|
134
|
+
# @return [void]
|
135
|
+
# @raise [Securial::Error::Config::InvalidConfigurationError] If password lengths are invalid
|
136
|
+
# @api private
|
137
|
+
#
|
57
138
|
def validate_password_lengths!(config)
|
58
139
|
if config.password_min_length > config.password_max_length
|
59
140
|
raise_error("password_min_length cannot be greater than password_max_length.")
|
60
141
|
end
|
61
142
|
end
|
62
143
|
|
144
|
+
# Logs error message and raises configuration error.
|
145
|
+
#
|
146
|
+
# Provides a consistent way to handle validation failures by logging
|
147
|
+
# the error at fatal level and raising the appropriate exception.
|
148
|
+
#
|
149
|
+
# @param [String] msg The error message to log and include in the exception
|
150
|
+
# @return [void]
|
151
|
+
# @raise [Securial::Error::Config::InvalidConfigurationError] Always raises with the provided message
|
152
|
+
# @api private
|
153
|
+
#
|
63
154
|
def raise_error(msg)
|
64
155
|
Securial.logger.fatal msg
|
65
156
|
raise Securial::Error::Config::InvalidConfigurationError, msg
|
data/lib/securial/config.rb
CHANGED
@@ -1,16 +1,52 @@
|
|
1
|
+
# @title Securial Configuration System
|
2
|
+
#
|
3
|
+
# Configuration management for the Securial framework.
|
4
|
+
#
|
5
|
+
# This file defines the configuration system for Securial, providing mechanisms
|
6
|
+
# to set, retrieve, and validate configuration options. It uses a conventional
|
7
|
+
# Ruby configuration block pattern to allow applications to customize Securial's
|
8
|
+
# behavior through an easy-to-use interface.
|
9
|
+
#
|
10
|
+
# @example Basic configuration
|
11
|
+
# # In config/initializers/securial.rb
|
12
|
+
# Securial.configure do |config|
|
13
|
+
# config.jwt_secret = ENV["JWT_SECRET"]
|
14
|
+
# config.token_expiry = 2.hours
|
15
|
+
# config.refresh_token_expiry = 7.days
|
16
|
+
# config.session_timeout = 1.hour
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# @example Accessing configuration values
|
20
|
+
# # Get the configured token expiry
|
21
|
+
# expiry = Securial.configuration.token_expiry
|
22
|
+
#
|
1
23
|
require "securial/config/configuration"
|
2
24
|
require "securial/config/signature"
|
3
25
|
require "securial/config/validation"
|
4
26
|
|
5
|
-
|
6
27
|
module Securial
|
7
28
|
extend self
|
8
|
-
attr_accessor :configuration
|
9
29
|
|
30
|
+
# Gets the current configuration instance.
|
31
|
+
#
|
32
|
+
# Returns the existing configuration or creates a new default configuration
|
33
|
+
# if one hasn't been set yet.
|
34
|
+
#
|
35
|
+
# @return [Securial::Config::Configuration] the current configuration instance
|
10
36
|
def configuration
|
11
37
|
@configuration ||= Config::Configuration.new
|
12
38
|
end
|
13
39
|
|
40
|
+
# Sets the configuration instance.
|
41
|
+
#
|
42
|
+
# Validates the provided configuration to ensure all required settings
|
43
|
+
# are present and have valid values.
|
44
|
+
#
|
45
|
+
# @param config [Securial::Config::Configuration] the configuration instance to use
|
46
|
+
# @raise [ArgumentError] if the provided object is not a Configuration instance
|
47
|
+
# @raise [Securial::Error::Config::ValidationError] if the configuration is invalid
|
48
|
+
# @return [Securial::Config::Configuration] the newly set configuration
|
49
|
+
#
|
14
50
|
def configuration=(config)
|
15
51
|
if config.is_a?(Config::Configuration)
|
16
52
|
@configuration = config
|
@@ -20,8 +56,19 @@ module Securial
|
|
20
56
|
end
|
21
57
|
end
|
22
58
|
|
59
|
+
# Configures the Securial framework using a block.
|
60
|
+
#
|
61
|
+
# This method provides the conventional Ruby configuration block pattern,
|
62
|
+
# yielding the current configuration instance to the provided block for
|
63
|
+
# modification. After the block executes, the configuration is validated.
|
64
|
+
#
|
65
|
+
# @yield [config] Yields the configuration instance to the block
|
66
|
+
# @yieldparam config [Securial::Config::Configuration] the configuration instance
|
67
|
+
# @raise [Securial::Error::Config::ValidationError] if the configuration is invalid
|
68
|
+
# @return [Securial::Config::Configuration] the updated configuration
|
23
69
|
def configure
|
24
70
|
yield(configuration) if block_given?
|
25
71
|
Securial::Config::Validation.validate_all!(configuration)
|
72
|
+
configuration
|
26
73
|
end
|
27
74
|
end
|
data/lib/securial/engine.rb
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
# @title Securial Rails Engine
|
2
|
+
#
|
3
|
+
# Rails engine configuration for the Securial framework.
|
4
|
+
#
|
5
|
+
# This file defines the core Rails engine that powers Securial, setting up
|
6
|
+
# namespace isolation, generator defaults, and loading all required components.
|
7
|
+
# The engine configuration establishes how Securial integrates with host Rails
|
8
|
+
# applications and defines the conventions used throughout the codebase.
|
9
|
+
#
|
10
|
+
# @example Mounting the engine in a Rails application
|
11
|
+
# # In config/routes.rb
|
12
|
+
# Rails.application.routes.draw do
|
13
|
+
# mount Securial::Engine => '/securial'
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# @example Accessing engine routes in views or controllers
|
17
|
+
# # Generate path to Securial login
|
18
|
+
# securial.login_path
|
19
|
+
#
|
20
|
+
# # Generate URL to Securial user profile
|
21
|
+
# securial.user_url(@user)
|
22
|
+
#
|
1
23
|
require "securial/auth"
|
2
24
|
require "securial/config"
|
3
25
|
require "securial/error"
|
@@ -7,11 +29,29 @@ require "securial/middleware"
|
|
7
29
|
require "securial/security"
|
8
30
|
|
9
31
|
module Securial
|
32
|
+
# Rails engine implementation for the Securial framework.
|
33
|
+
#
|
34
|
+
# This class defines the core engine that powers Securial's integration with
|
35
|
+
# Rails applications. It isolates all Securial components within their own
|
36
|
+
# namespace to prevent conflicts with host application code and configures
|
37
|
+
# generator defaults to ensure consistent code generation.
|
38
|
+
#
|
39
|
+
# The engine handles:
|
40
|
+
# - Namespace isolation to prevent conflicts
|
41
|
+
# - Configuration of generators for consistent code generation
|
42
|
+
# - Setting up Securial's API-only mode for JSON responses
|
43
|
+
# - Loading initializers for various framework components
|
44
|
+
#
|
45
|
+
# @see https://guides.rubyonrails.org/engines.html Rails Engines Guide
|
46
|
+
#
|
10
47
|
class Engine < ::Rails::Engine
|
48
|
+
# Isolates the Securial namespace to prevent conflicts with host applications
|
11
49
|
isolate_namespace Securial
|
12
50
|
|
51
|
+
# Configures the engine for API-only mode by default
|
13
52
|
config.generators.api_only = true
|
14
53
|
|
54
|
+
# Sets up standard generator configurations for consistent code generation
|
15
55
|
config.generators do |g|
|
16
56
|
g.orm :active_record, primary_key_type: :string
|
17
57
|
g.test_framework :rspec,
|
@@ -28,4 +68,5 @@ module Securial
|
|
28
68
|
end
|
29
69
|
end
|
30
70
|
|
71
|
+
# Load engine initializers that configure various aspects of the framework
|
31
72
|
require_relative "engine_initializers"
|
data/lib/securial/error/auth.rb
CHANGED
@@ -1,18 +1,70 @@
|
|
1
|
+
# @title Securial Authentication Errors
|
2
|
+
#
|
3
|
+
# Authentication-related errors for the Securial framework.
|
4
|
+
#
|
5
|
+
# This file defines error classes for authentication-related issues in the
|
6
|
+
# Securial framework, such as token encoding/decoding failures, expired tokens,
|
7
|
+
# and revoked sessions. These errors help identify and troubleshoot problems
|
8
|
+
# with the authentication system during runtime.
|
9
|
+
#
|
10
|
+
# @example Handling authentication errors
|
11
|
+
# begin
|
12
|
+
# decoded_token = Securial::Auth::AuthEncoder.decode(token)
|
13
|
+
# rescue Securial::Error::Auth::TokenDecodeError => e
|
14
|
+
# # Handle invalid token format
|
15
|
+
# logger.warn("Invalid token format: #{e.message}")
|
16
|
+
# rescue Securial::Error::Auth::TokenExpiredError => e
|
17
|
+
# # Handle expired token
|
18
|
+
# render json: { error: "Your session has expired. Please log in again." }, status: :unauthorized
|
19
|
+
# rescue Securial::Error::Auth::TokenRevokedError => e
|
20
|
+
# # Handle revoked token
|
21
|
+
# render json: { error: "Your session has been revoked." }, status: :unauthorized
|
22
|
+
# end
|
23
|
+
#
|
1
24
|
module Securial
|
2
25
|
module Error
|
26
|
+
# Namespace for authentication-related errors in the Securial framework.
|
27
|
+
#
|
28
|
+
# These errors are raised during authentication operations such as
|
29
|
+
# token encoding/decoding, session validation, and access control checks.
|
30
|
+
#
|
3
31
|
module Auth
|
32
|
+
# Error raised when a JWT token cannot be encoded properly.
|
33
|
+
#
|
34
|
+
# This may occur due to invalid payload data, missing required claims,
|
35
|
+
# or issues with the signing key.
|
36
|
+
#
|
37
|
+
# @see Securial::Auth::AuthEncoder#encode
|
38
|
+
#
|
4
39
|
class TokenEncodeError < BaseError
|
5
40
|
default_message "Error while encoding session token"
|
6
41
|
end
|
7
42
|
|
43
|
+
# Error raised when a JWT token cannot be decoded or validated.
|
44
|
+
#
|
45
|
+
# This may occur due to malformed tokens, invalid signatures,
|
46
|
+
# or tokens that don't match the expected format.
|
47
|
+
#
|
48
|
+
# @see Securial::Auth::AuthEncoder#decode
|
49
|
+
#
|
8
50
|
class TokenDecodeError < BaseError
|
9
51
|
default_message "Error while decoding session token"
|
10
52
|
end
|
11
53
|
|
54
|
+
# Error raised when attempting to use a token from a revoked session.
|
55
|
+
#
|
56
|
+
# This occurs when a token references a session that has been
|
57
|
+
# explicitly revoked, such as after a user logout or account suspension.
|
58
|
+
#
|
12
59
|
class TokenRevokedError < BaseError
|
13
60
|
default_message "Session token is revoked"
|
14
61
|
end
|
15
62
|
|
63
|
+
# Error raised when attempting to use an expired token.
|
64
|
+
#
|
65
|
+
# This occurs when a token's expiration time (exp claim) has passed,
|
66
|
+
# indicating that the token is no longer valid for authentication.
|
67
|
+
#
|
16
68
|
class TokenExpiredError < BaseError
|
17
69
|
default_message "Session token is expired"
|
18
70
|
end
|
@@ -1,17 +1,68 @@
|
|
1
|
+
# @title Securial Base Error
|
2
|
+
#
|
3
|
+
# Base error class for the Securial framework.
|
4
|
+
#
|
5
|
+
# This file defines the base error class that all other specialized Securial
|
6
|
+
# errors inherit from. It provides functionality for default error messages
|
7
|
+
# and customized backtrace handling.
|
8
|
+
#
|
1
9
|
module Securial
|
2
10
|
module Error
|
11
|
+
# Base error class for all Securial-specific exceptions.
|
12
|
+
#
|
13
|
+
# This class serves as the foundation for Securial's error hierarchy, providing
|
14
|
+
# common functionality like default messages and backtrace customization.
|
15
|
+
# All specialized error types in Securial should inherit from this class.
|
16
|
+
#
|
17
|
+
# @example Defining a custom error class
|
18
|
+
# module Securial
|
19
|
+
# module Error
|
20
|
+
# class AuthError < BaseError
|
21
|
+
# default_message "Authentication failed"
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# @example Raising a custom error
|
27
|
+
# raise Securial::Error::AuthError
|
28
|
+
# # => Authentication failed (Securial::Error::AuthError)
|
29
|
+
#
|
30
|
+
# raise Securial::Error::AuthError, "Invalid token provided"
|
31
|
+
# # => Invalid token provided (Securial::Error::AuthError)
|
32
|
+
#
|
3
33
|
class BaseError < StandardError
|
4
34
|
class_attribute :_default_message, instance_writer: false
|
5
35
|
|
36
|
+
# Sets or gets the default message for this error class.
|
37
|
+
#
|
38
|
+
# This class method allows error classes to define a standard message
|
39
|
+
# that will be used when no explicit message is provided at instantiation.
|
40
|
+
#
|
41
|
+
# @param message [String, nil] The default message to set for this error class
|
42
|
+
# @return [String, nil] The current default message for this error class
|
43
|
+
#
|
6
44
|
def self.default_message(message = nil)
|
7
45
|
self._default_message = message if message
|
8
46
|
self._default_message
|
9
47
|
end
|
10
48
|
|
49
|
+
# Initializes a new error instance with the provided message or default.
|
50
|
+
#
|
51
|
+
# @param message [String, nil] The error message or nil to use default
|
52
|
+
# @return [BaseError] New error instance
|
53
|
+
#
|
11
54
|
def initialize(message = nil)
|
12
55
|
super(message || self.class._default_message || "An error occurred in Securial")
|
13
56
|
end
|
14
57
|
|
58
|
+
# Returns an empty backtrace.
|
59
|
+
#
|
60
|
+
# This method overrides the standard backtrace behavior to return an empty array,
|
61
|
+
# which helps keep error responses clean without showing internal implementation
|
62
|
+
# details in production environments.
|
63
|
+
#
|
64
|
+
# @return [Array] An empty array
|
65
|
+
#
|
15
66
|
def backtrace; []; end
|
16
67
|
end
|
17
68
|
end
|
@@ -1,6 +1,39 @@
|
|
1
|
+
# @title Securial Configuration Errors
|
2
|
+
#
|
3
|
+
# Configuration-related errors for the Securial framework.
|
4
|
+
#
|
5
|
+
# This file defines error classes for configuration-related issues in the
|
6
|
+
# Securial framework, such as missing or invalid configuration options.
|
7
|
+
# These errors help identify and troubleshoot problems with application setup.
|
8
|
+
#
|
1
9
|
module Securial
|
2
10
|
module Error
|
11
|
+
# Namespace for configuration-related errors in the Securial framework.
|
12
|
+
#
|
13
|
+
# These errors are raised when the Securial configuration is invalid,
|
14
|
+
# missing required values, or contains values that don't meet validation
|
15
|
+
# requirements.
|
16
|
+
#
|
17
|
+
# @example Handling configuration errors
|
18
|
+
# begin
|
19
|
+
# Securial.configure do |config|
|
20
|
+
# # Configure Securial settings
|
21
|
+
# end
|
22
|
+
# rescue Securial::Error::Config::InvalidConfigurationError => e
|
23
|
+
# Rails.logger.error("Securial configuration error: #{e.message}")
|
24
|
+
# # Handle configuration error
|
25
|
+
# end
|
26
|
+
#
|
3
27
|
module Config
|
28
|
+
# Error raised when Securial configuration is invalid.
|
29
|
+
#
|
30
|
+
# This error is typically raised during application initialization when
|
31
|
+
# the provided configuration doesn't meet requirements, such as missing
|
32
|
+
# required settings or having values that fail validation.
|
33
|
+
#
|
34
|
+
# @example Raising a configuration error
|
35
|
+
# raise InvalidConfigurationError, "JWT secret is missing"
|
36
|
+
#
|
4
37
|
class InvalidConfigurationError < Securial::Error::BaseError
|
5
38
|
default_message "Invalid configuration for Securial"
|
6
39
|
end
|