securial 1.0.1 → 1.0.2

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +4 -0
  3. data/README.md +14 -9
  4. data/app/controllers/concerns/securial/identity.rb +91 -2
  5. data/app/controllers/securial/accounts_controller.rb +68 -5
  6. data/app/controllers/securial/application_controller.rb +34 -2
  7. data/app/controllers/securial/passwords_controller.rb +44 -4
  8. data/app/controllers/securial/role_assignments_controller.rb +55 -4
  9. data/app/controllers/securial/roles_controller.rb +54 -0
  10. data/app/controllers/securial/sessions_controller.rb +77 -3
  11. data/app/controllers/securial/status_controller.rb +24 -0
  12. data/app/controllers/securial/users_controller.rb +54 -0
  13. data/app/jobs/securial/application_job.rb +9 -0
  14. data/app/mailers/securial/application_mailer.rb +12 -0
  15. data/app/mailers/securial/securial_mailer.rb +30 -0
  16. data/app/models/concerns/securial/password_resettable.rb +70 -0
  17. data/app/models/securial/application_record.rb +19 -0
  18. data/app/models/securial/current.rb +13 -0
  19. data/app/models/securial/role.rb +17 -0
  20. data/app/models/securial/role_assignment.rb +16 -0
  21. data/app/models/securial/session.rb +79 -1
  22. data/app/models/securial/user.rb +34 -0
  23. data/lib/generators/factory_bot/model/model_generator.rb +1 -0
  24. data/lib/securial/auth.rb +44 -6
  25. data/lib/securial/cli.rb +124 -0
  26. data/lib/securial/config.rb +49 -2
  27. data/lib/securial/engine.rb +41 -0
  28. data/lib/securial/error/auth.rb +52 -0
  29. data/lib/securial/error/base_securial_error.rb +51 -0
  30. data/lib/securial/error/config.rb +33 -0
  31. data/lib/securial/error.rb +33 -3
  32. data/lib/securial/helpers.rb +48 -4
  33. data/lib/securial/logger/broadcaster.rb +89 -1
  34. data/lib/securial/logger/builder.rb +54 -1
  35. data/lib/securial/logger/formatter.rb +73 -0
  36. data/lib/securial/logger.rb +42 -1
  37. data/lib/securial/middleware.rb +40 -9
  38. data/lib/securial/security/request_rate_limiter.rb +47 -1
  39. data/lib/securial/security.rb +37 -6
  40. data/lib/securial/version.rb +8 -1
  41. data/lib/securial.rb +36 -0
  42. metadata +4 -3
@@ -1,11 +1,55 @@
1
+ # @title Securial Helper Utilities
2
+ #
3
+ # Centralized collection of helper modules for the Securial framework.
4
+ #
5
+ # This file serves as the entry point for all helper functionality in Securial,
6
+ # loading specialized utility modules that provide common functions used
7
+ # throughout the framework. These helpers handle tasks such as normalization,
8
+ # pattern matching, role management, and data transformation, making common
9
+ # operations consistent across the codebase.
10
+ #
11
+ # @example Normalizing user input
12
+ # # For normalizing email addresses (converts to lowercase)
13
+ # email = Securial::Helpers::NormalizingHelper.normalize_email("USER@EXAMPLE.COM")
14
+ # # => "user@example.com"
15
+ #
16
+ # @example Validating input format
17
+ # # For validating email format
18
+ # valid = Securial::Helpers::RegexHelper.valid_email?("user@example.com")
19
+ # # => true
20
+ #
21
+ # invalid = Securial::Helpers::RegexHelper.valid_email?("not-an-email")
22
+ # # => false
23
+ #
24
+ # @example Transforming data structure keys
25
+ # # For transforming keys in response data (snake_case to camelCase)
26
+ # data = { user_id: 1, first_name: "John", last_name: "Doe" }
27
+ # json = Securial::Helpers::KeyTransformer.transform(data, :lower_camel_case)
28
+ # # => { userId: 1, firstName: "John", lastName: "Doe" }
29
+ #
1
30
  require "securial/helpers/normalizing_helper"
2
31
  require "securial/helpers/regex_helper"
3
32
  require "securial/helpers/roles_helper"
4
33
  require "securial/helpers/key_transformer"
5
34
 
6
35
  module Securial
7
- module Helpers
8
- # This module acts as a namespace for helper modules.
9
- # It requires all helper modules to make them available for consumers.
10
- end
36
+ # Namespace containing utility modules for common operations.
37
+ #
38
+ # The Helpers module serves as a container for specialized utility modules
39
+ # that provide reusable functionality across the Securial framework:
40
+ #
41
+ # - {NormalizingHelper} - Methods for normalizing user input (emails, usernames, etc.)
42
+ # - {RegexHelper} - Regular expressions and validation methods for input validation
43
+ # - {RolesHelper} - Functions for working with user roles and permissions management
44
+ # - {KeyTransformer} - Tools for transforming data structure keys between formats (snake_case, camelCase)
45
+ #
46
+ # These helpers ensure consistent behavior across the application and reduce
47
+ # code duplication by centralizing common operations.
48
+ #
49
+ # @see Securial::Helpers::NormalizingHelper
50
+ # @see Securial::Helpers::RegexHelper
51
+ # @see Securial::Helpers::RolesHelper
52
+ # @see Securial::Helpers::KeyTransformer
53
+ #
54
+ module Helpers; end
11
55
  end
@@ -1,36 +1,109 @@
1
+ # @title Securial Logger Broadcaster
2
+ #
3
+ # Logger broadcasting utility for the Securial framework.
4
+ #
5
+ # This file defines a broadcaster class that sends logging messages to multiple
6
+ # destination loggers simultaneously. This enables unified logging across different
7
+ # outputs (like console and file) while maintaining appropriate formatting for each.
8
+ #
9
+ # @example Creating a broadcaster with multiple loggers
10
+ # # Create individual loggers
11
+ # file_logger = Logger.new('application.log')
12
+ # stdout_logger = Logger.new(STDOUT)
13
+ #
14
+ # # Combine them into a broadcaster
15
+ # broadcaster = Securial::Logger::Broadcaster.new([file_logger, stdout_logger])
16
+ #
17
+ # # Log messages go to both destinations
18
+ # broadcaster.info("Processing authentication request")
19
+ #
1
20
  module Securial
2
21
  module Logger
22
+ # Broadcasts log messages to multiple logger instances simultaneously.
23
+ #
24
+ # This class implements the Logger interface and forwards all logging calls
25
+ # to a collection of underlying loggers. This allows unified logging to
26
+ # multiple destinations (e.g., file and stdout) while maintaining specific
27
+ # formatting for each destination.
28
+ #
29
+ # @example Using a broadcaster with two loggers
30
+ # file_logger = Logger.new('app.log')
31
+ # console_logger = Logger.new(STDOUT)
32
+ # broadcaster = Broadcaster.new([file_logger, console_logger])
33
+ #
34
+ # # This logs to both destinations
35
+ # broadcaster.info("User logged in")
36
+ #
3
37
  class Broadcaster
38
+ # Initializes a new broadcaster with the provided loggers.
39
+ #
40
+ # @param loggers [Array<Logger>] Collection of logger instances
41
+ # @return [Broadcaster] New broadcaster instance
4
42
  def initialize(loggers)
5
43
  @loggers = loggers
6
44
  end
7
45
 
46
+ # Dynamically define logging methods for each severity level
47
+ # (debug, info, warn, error, fatal, unknown)
8
48
  ::Logger::Severity.constants.each do |severity|
9
49
  define_method(severity.downcase) do |*args, &block|
10
50
  @loggers.each { |logger| logger.public_send(severity.downcase, *args, &block) }
11
51
  end
12
52
  end
13
53
 
54
+ # Writes a message to each underlying logger.
55
+ #
56
+ # @param msg [String] Message to be written
57
+ # @return [Array] Results from each logger's << method
14
58
  def <<(msg)
15
59
  @loggers.each { |logger| logger << msg }
16
60
  end
17
61
 
62
+ # Closes all underlying loggers.
63
+ #
64
+ # @return [void]
18
65
  def close
19
66
  @loggers.each(&:close)
20
67
  end
21
68
 
69
+ # No-op method to satisfy the Logger interface.
70
+ #
71
+ # Since each underlying logger has its own formatter, setting a
72
+ # formatter on the broadcaster is not supported.
73
+ #
74
+ # @param _formatter [Object] Ignored formatter object
75
+ # @return [void]
22
76
  def formatter=(_formatter)
23
- # Do nothing
77
+ # Do nothing - each logger maintains its own formatter
24
78
  end
25
79
 
80
+ # Returns nil to satisfy the Logger interface.
81
+ #
82
+ # Since each underlying logger has its own formatter, there is
83
+ # no single formatter for the broadcaster.
84
+ #
85
+ # @return [nil] Always returns nil
26
86
  def formatter
27
87
  nil
28
88
  end
29
89
 
90
+ # Returns the collection of managed loggers.
91
+ #
92
+ # @return [Array<Logger>] All loggers managed by this broadcaster
93
+ #
30
94
  def loggers
31
95
  @loggers
32
96
  end
33
97
 
98
+ # Executes a block with the specified tags added to the log.
99
+ #
100
+ # Supports ActiveSupport::TaggedLogging by forwarding tagged blocks
101
+ # to all underlying loggers that support tagging.
102
+ #
103
+ # @param tags [Array<String>] Tags to apply to log messages
104
+ # @yield Block to be executed with the tags applied
105
+ # @return [Object] Result of the block
106
+ #
34
107
  def tagged(*tags, &block)
35
108
  # If all loggers support tagged, nest the calls, otherwise just yield.
36
109
  taggable_loggers = @loggers.select { |logger| logger.respond_to?(:tagged) }
@@ -44,10 +117,25 @@ module Securial
44
117
  end
45
118
  end
46
119
 
120
+ # Checks if the broadcaster responds to the given method.
121
+ #
122
+ # @param method [Symbol] Method name to check
123
+ # @param include_private [Boolean] Whether to include private methods
124
+ # @return [Boolean] True if any of the underlying loggers respond to the method
47
125
  def respond_to_missing?(method, include_private = false)
48
126
  @loggers.any? { |logger| logger.respond_to?(method, include_private) } || super
49
127
  end
50
128
 
129
+ # Delegates missing methods to all underlying loggers.
130
+ #
131
+ # If all loggers respond to the method, it will be called on each logger.
132
+ # Otherwise, raises a NoMethodError.
133
+ #
134
+ # @param method [Symbol] Method name to call
135
+ # @param args [Array] Arguments to pass to the method
136
+ # @param block [Proc] Block to pass to the method
137
+ # @return [Array] Results from each logger's method call
138
+ # @raise [NoMethodError] If any logger doesn't respond to the method
51
139
  def method_missing(method, *args, &block)
52
140
  if @loggers.all? { |logger| logger.respond_to?(method) }
53
141
  @loggers.map { |logger| logger.send(method, *args, &block) }
@@ -1,3 +1,19 @@
1
+ # @title Securial Logger Builder
2
+ #
3
+ # Logger construction utilities for the Securial framework.
4
+ #
5
+ # This file defines a builder class that constructs and configures loggers for the Securial
6
+ # framework based on application configuration. It supports multiple logging destinations
7
+ # (stdout and file) with appropriate formatters for each, and combines them using a
8
+ # broadcaster pattern for unified logging.
9
+ #
10
+ # @example Building a logger with defaults from configuration
11
+ # # Securial.configuration has been set up elsewhere
12
+ # logger = Securial::Logger::Builder.build
13
+ #
14
+ # # Log messages go to both configured destinations
15
+ # logger.info("User authentication successful")
16
+ #
1
17
  require "logger"
2
18
  require "active_support/logger"
3
19
  require "active_support/tagged_logging"
@@ -7,7 +23,22 @@ require "securial/logger/formatter"
7
23
 
8
24
  module Securial
9
25
  module Logger
26
+ # Builder for constructing Securial's logging system.
27
+ #
28
+ # This class provides factory methods to create properly configured logger instances
29
+ # based on the application's configuration settings. It supports multiple logging
30
+ # destinations and handles the setup of formatters, log levels, and tagging.
31
+ #
10
32
  class Builder
33
+ # Builds a complete logger system based on configuration settings.
34
+ #
35
+ # Creates file and/or stdout loggers as specified in configuration and
36
+ # combines them using a Broadcaster to provide unified logging to multiple
37
+ # destinations with appropriate formatting for each.
38
+ #
39
+ # @return [Securial::Logger::Broadcaster] A broadcaster containing all configured loggers
40
+ # @see Securial::Logger::Broadcaster
41
+ #
11
42
  def self.build
12
43
  loggers = []
13
44
  progname = "Securial"
@@ -23,6 +54,17 @@ module Securial
23
54
  Broadcaster.new(loggers)
24
55
  end
25
56
 
57
+ # Creates and configures a file logger.
58
+ #
59
+ # Sets up a logger that writes to a Rails environment-specific log file
60
+ # with plain text formatting and adds it to the provided loggers array.
61
+ #
62
+ # @param progname [String] The program name to include in log entries
63
+ # @param level [Integer, Symbol] The log level (e.g., :info, :debug)
64
+ # @param loggers [Array<Logger>] Array to which the new logger will be added
65
+ # @return [ActiveSupport::TaggedLogging] The configured file logger
66
+ # @see Securial::Logger::Formatter::PlainFormatter
67
+ #
26
68
  def self.create_file_logger(progname, level, loggers)
27
69
  file_logger = ::Logger.new(Rails.root.join("log", "securial-#{Rails.env}.log"))
28
70
  file_logger.level = level
@@ -32,12 +74,23 @@ module Securial
32
74
  loggers << tagged_file_logger
33
75
  end
34
76
 
77
+ # Creates and configures a stdout logger.
78
+ #
79
+ # Sets up a logger that writes to standard output with colorful formatting
80
+ # and adds it to the provided loggers array.
81
+ #
82
+ # @param progname [String] The program name to include in log entries
83
+ # @param level [Integer, Symbol] The log level (e.g., :info, :debug)
84
+ # @param loggers [Array<Logger>] Array to which the new logger will be added
85
+ # @return [ActiveSupport::TaggedLogging] The configured stdout logger
86
+ # @see Securial::Logger::Formatter::ColorfulFormatter
87
+ #
35
88
  def self.create_stdout_logger(progname, level, loggers)
36
89
  stdout_logger = ::Logger.new($stdout)
37
90
  stdout_logger.level = level
38
91
  stdout_logger.progname = progname
39
92
  stdout_logger.formatter = Formatter::ColorfulFormatter.new
40
- tagged_stdout_logger = ActiveSupport::TaggedLogging.new(stdout_logger)
93
+ tagged_stdout_logger = ActiveSupport::TaggedLogging.new(stdout_logger)
41
94
  loggers << tagged_stdout_logger
42
95
  end
43
96
  end
@@ -1,6 +1,33 @@
1
+ # @title Securial Logger Formatters
2
+ #
3
+ # Log formatting utilities for the Securial framework's logging system.
4
+ #
5
+ # This file defines formatter classes that determine how log messages are displayed,
6
+ # providing both colorful terminal-friendly output and plain text output options.
7
+ # These formatters are used by the Securial::Logger system to ensure consistent
8
+ # and readable log formats across different environments.
9
+ #
10
+ # @example Using a formatter with a standard Ruby logger
11
+ # require 'logger'
12
+ # logger = Logger.new(STDOUT)
13
+ # logger.formatter = Securial::Logger::Formatter::ColorfulFormatter.new
14
+ #
15
+ # logger.info("Application started")
16
+ # # Output: [2023-11-15 14:30:22] INFO -- Application started (in green color)
17
+ #
1
18
  module Securial
2
19
  module Logger
20
+ # Formatting utilities for Securial's logging system.
21
+ #
22
+ # This module contains formatter classes and constants that determine
23
+ # how log messages are presented. It provides both colored output for
24
+ # terminal environments and plain text output for file logging.
25
+ #
3
26
  module Formatter
27
+ # Terminal color codes for different log severity levels.
28
+ #
29
+ # @return [Hash{String => String}] Mapping of severity names to ANSI color codes
30
+ #
4
31
  COLORS = {
5
32
  "DEBUG" => "\e[36m", # cyan
6
33
  "INFO" => "\e[32m", # green
@@ -9,10 +36,38 @@ module Securial
9
36
  "FATAL" => "\e[35m", # magenta
10
37
  "UNKNOWN" => "\e[37m", # white
11
38
  }.freeze
39
+
40
+ # ANSI code to reset terminal colors.
41
+ #
42
+ # @return [String] Terminal color reset sequence
43
+ #
12
44
  CLEAR = "\e[0m"
45
+
46
+ # Width used for severity level padding in log output.
47
+ #
48
+ # @return [Integer] Number of characters to use for severity field
49
+ #
13
50
  SEVERITY_WIDTH = 5
14
51
 
52
+ # Formatter that adds color to log output for terminal display.
53
+ #
54
+ # This formatter colorizes log messages based on their severity level,
55
+ # making them easier to distinguish in terminal output. It follows the
56
+ # standard Ruby Logger formatter interface.
57
+ #
58
+ # @example
59
+ # logger = Logger.new(STDOUT)
60
+ # logger.formatter = Securial::Logger::Formatter::ColorfulFormatter.new
61
+ #
15
62
  class ColorfulFormatter
63
+ # Formats a log message with color based on severity.
64
+ #
65
+ # @param severity [String] Log severity level (DEBUG, INFO, etc.)
66
+ # @param timestamp [Time] Time when the log event occurred
67
+ # @param progname [String] Program name or context for the log message
68
+ # @param msg [String] The log message itself
69
+ # @return [String] Formatted log message with appropriate ANSI color codes
70
+ #
16
71
  def call(severity, timestamp, progname, msg)
17
72
  color = COLORS[severity] || CLEAR
18
73
  padded_severity = severity.ljust(SEVERITY_WIDTH)
@@ -22,7 +77,25 @@ module Securial
22
77
  end
23
78
  end
24
79
 
80
+ # Formatter that produces plain text log output without colors.
81
+ #
82
+ # This formatter is suitable for file logging or environments where
83
+ # terminal colors are not supported. It follows the standard Ruby
84
+ # Logger formatter interface.
85
+ #
86
+ # @example
87
+ # logger = Logger.new('application.log')
88
+ # logger.formatter = Securial::Logger::Formatter::PlainFormatter.new
89
+ #
25
90
  class PlainFormatter
91
+ # Formats a log message in plain text without color codes.
92
+ #
93
+ # @param severity [String] Log severity level (DEBUG, INFO, etc.)
94
+ # @param timestamp [Time] Time when the log event occurred
95
+ # @param progname [String] Program name or context for the log message
96
+ # @param msg [String] The log message itself
97
+ # @return [String] Formatted log message as plain text
98
+ #
26
99
  def call(severity, timestamp, progname, msg)
27
100
  padded_severity = severity.ljust(SEVERITY_WIDTH)
28
101
  formatted = "[#{timestamp.strftime("%Y-%m-%d %H:%M:%S")}] #{padded_severity} -- #{msg}\n"
@@ -1,13 +1,54 @@
1
+ # @title Securial Logger Configuration
2
+ #
3
+ # Defines the logging interface for the Securial framework.
4
+ #
5
+ # This file establishes the logging system for Securial, providing methods
6
+ # to access and configure the application's logger instance. By default,
7
+ # it initializes a logger using the Securial::Logger::Builder class, which
8
+ # configures appropriate log levels and formatters based on the current environment.
9
+ #
10
+ # @example Basic logging usage
11
+ # # Log messages at different levels
12
+ # Securial.logger.debug("Detailed debugging information")
13
+ # Securial.logger.info("General information about system operation")
14
+ # Securial.logger.warn("Warning about potential issue")
15
+ # Securial.logger.error("Error condition")
16
+ #
17
+ # @example Setting a custom logger
18
+ # # Configure a custom logger
19
+ # custom_logger = Logger.new(STDOUT)
20
+ # custom_logger.level = :info
21
+ # Securial.logger = custom_logger
22
+ #
1
23
  require_relative "logger/builder"
2
24
 
3
25
  module Securial
4
26
  extend self
5
27
  attr_accessor :logger
6
28
 
29
+ # Returns the logger instance used by Securial.
30
+ #
31
+ # If no logger has been set, initializes a new logger instance using
32
+ # the Securial::Logger::Builder class, which configures the logger
33
+ # based on the current environment settings.
34
+ #
35
+ # @return [Securial::Logger::Builder] the configured logger instance
36
+ # @see Securial::Logger::Builder
7
37
  def logger
8
- @logger ||= Logger::Builder.build
38
+ @logger ||= Securial::Logger::Builder.build
9
39
  end
10
40
 
41
+ # Sets the logger instance for Securial.
42
+ #
43
+ # This allows applications to provide their own custom logger
44
+ # implementation that may have specialized formatting or output
45
+ # destinations.
46
+ #
47
+ # @param logger [Logger] a Logger-compatible object that responds to standard
48
+ # logging methods (debug, info, warn, error, fatal)
49
+ # @return [Logger] the newly set logger instance
50
+ # @example
51
+ # Securial.logger = Rails.logger
11
52
  def logger=(logger)
12
53
  @logger = logger
13
54
  end
@@ -1,16 +1,47 @@
1
+ # @title Securial Middleware Components
2
+ #
3
+ # Rack middleware components for the Securial framework.
4
+ #
5
+ # This file serves as the entry point for middleware-related functionality in Securial,
6
+ # loading specialized middleware classes that provide features like request/response
7
+ # processing, logging enhancements, and security header management.
8
+ #
1
9
  require "securial/middleware/request_tag_logger"
2
10
  require "securial/middleware/transform_request_keys"
3
11
  require "securial/middleware/transform_response_keys"
4
12
  require "securial/middleware/response_headers"
5
13
 
6
14
  module Securial
7
- module Middleware
8
- # This module serves as a namespace for all middleware components in the Securial gem.
9
- # It currently includes the RequestTagLogger middleware, which tags logs with request IDs.
10
- #
11
- # Additional middleware can be added here as the gem evolves.
12
- #
13
- # Example usage:
14
- # use Securial::Middleware::RequestTagLogger
15
- end
15
+ # Namespace for Rack middleware components in the Securial framework.
16
+ #
17
+ # This module contains several middleware components that enhance Rails applications:
18
+ #
19
+ # - {RequestTagLogger} - Tags logs with request IDs for better traceability
20
+ # - {TransformRequestKeys} - Transforms incoming request parameter keys to a consistent format
21
+ # - {TransformResponseKeys} - Transforms outgoing response JSON keys to match client conventions
22
+ # - {ResponseHeaders} - Adds security headers to responses based on configuration
23
+ #
24
+ # @example Using middleware in a Rails application (config/application.rb)
25
+ # module YourApp
26
+ # class Application < Rails::Application
27
+ # # Add request logging with unique IDs
28
+ # config.middleware.use Securial::Middleware::RequestTagLogger
29
+ #
30
+ # # Transform request keys from camelCase to snake_case
31
+ # config.middleware.use Securial::Middleware::TransformRequestKeys
32
+ #
33
+ # # Transform response keys from snake_case to camelCase
34
+ # config.middleware.use Securial::Middleware::TransformResponseKeys
35
+ #
36
+ # # Add security headers to all responses
37
+ # config.middleware.use Securial::Middleware::ResponseHeaders
38
+ # end
39
+ # end
40
+ #
41
+ # @see Securial::Middleware::RequestTagLogger
42
+ # @see Securial::Middleware::TransformRequestKeys
43
+ # @see Securial::Middleware::TransformResponseKeys
44
+ # @see Securial::Middleware::ResponseHeaders
45
+ #
46
+ module Middleware; end
16
47
  end
@@ -1,11 +1,57 @@
1
+ # @title Securial Request Rate Limiter
2
+ #
3
+ # Rate limiting middleware for protecting authentication endpoints in the Securial framework.
4
+ #
5
+ # This file implements rate limiting for sensitive endpoints like login and password reset,
6
+ # protecting them from brute force attacks, credential stuffing, and denial of service attempts.
7
+ # It uses the Rack::Attack middleware to track and limit request rates based on IP address
8
+ # and provided credentials.
9
+ #
10
+ # @example Basic configuration in a Rails initializer
11
+ # # In config/initializers/securial.rb
12
+ # Securial.configure do |config|
13
+ # config.rate_limit_requests_per_minute = 5
14
+ # config.rate_limit_response_status = 429
15
+ # config.rate_limit_response_message = "Too many requests. Please try again later."
16
+ # end
17
+ #
18
+ # # Apply rate limiting
19
+ # Securial::Security::RequestRateLimiter.apply!
20
+ #
1
21
  require "rack/attack"
2
22
  require "securial/config"
3
23
 
4
24
  module Securial
5
25
  module Security
26
+ # Protects authentication endpoints with configurable rate limiting.
27
+ #
28
+ # This module provides Rack::Attack-based rate limiting for sensitive Securial
29
+ # endpoints, preventing brute force attacks and abuse. It limits requests based
30
+ # on both IP address and credential values (like email address), providing
31
+ # multi-dimensional protection against different attack vectors.
32
+ #
33
+ # Protected endpoints include:
34
+ # - Login attempts (/sessions/login)
35
+ # - Password reset requests (/password/forgot)
36
+ #
6
37
  module RequestRateLimiter
7
38
  extend self
8
39
 
40
+ # Applies rate limiting rules to the Rack::Attack middleware.
41
+ #
42
+ # This method configures Rack::Attack with throttling rules for sensitive endpoints
43
+ # and sets up a custom JSON response format for throttled requests. It should be
44
+ # called during application initialization, typically in a Rails initializer.
45
+ #
46
+ # Rate limits are defined using settings from the Securial configuration:
47
+ # - rate_limit_requests_per_minute: Maximum requests allowed per minute
48
+ # - rate_limit_response_status: HTTP status code to return (typically 429)
49
+ # - rate_limit_response_message: Message to include in throttled responses
50
+ #
51
+ # @return [void]
52
+ # @see Securial::Config::Configuration
53
+ # @see Rack::Attack
54
+ #
9
55
  def apply! # rubocop:disable Metrics/MethodLength
10
56
  resp_status = Securial.configuration.rate_limit_response_status
11
57
  resp_message = Securial.configuration.rate_limit_response_message
@@ -36,7 +82,7 @@ module Securial
36
82
  "Content-Type" => "application/json",
37
83
  "Retry-After" => retry_after.to_s,
38
84
  },
39
- [{ error: resp_message }.to_json],
85
+ [{ errors: [resp_message] }.to_json],
40
86
  ]
41
87
  end
42
88
  end
@@ -1,8 +1,39 @@
1
+ # @title Securial Security Components
2
+ #
3
+ # Security components and protections for the Securial framework.
4
+ #
5
+ # This file serves as the entry point for security-related functionality in Securial,
6
+ # loading specialized security modules that provide protection mechanisms including
7
+ # rate limiting, CSRF protection, and other security measures to safeguard
8
+ # Securial-powered applications.
9
+ #
10
+ # @example Using the rate limiter
11
+ # # Set up a rate limiter for login attempts
12
+ # limiter = Securial::Security::RequestRateLimiter.new(
13
+ # max_requests: 5,
14
+ # period: 1.minute,
15
+ # block_duration: 15.minutes
16
+ # )
17
+ #
18
+ # # Check if a request is allowed
19
+ # if limiter.allowed?(request.ip)
20
+ # # Process login attempt
21
+ # else
22
+ # # Return rate limit exceeded response
23
+ # end
24
+ #
1
25
  require "securial/security/request_rate_limiter"
2
26
 
3
- module Securial
4
- module Security
5
- # This module serves as a namespace for security-related functionality.
6
- # It can be extended with additional security features in the future.
7
- end
8
- end
27
+ module Securial
28
+ # Namespace for security-related functionality in the Securial framework.
29
+ #
30
+ # The Security module contains components that implement various security
31
+ # measures to protect applications from common attacks and threats:
32
+ #
33
+ # - {RequestRateLimiter} - Protection against brute force and DoS attacks
34
+ # - Additional security components may be added in future versions
35
+ #
36
+ # @see Securial::Security::RequestRateLimiter
37
+ #
38
+ module Security; end
39
+ end
@@ -1,3 +1,10 @@
1
1
  module Securial
2
- VERSION = "1.0.1".freeze
2
+ # Current version of the Securial gem.
3
+ #
4
+ # This constant is used by the gem specification to determine the version of the gem
5
+ # when it is built and published to RubyGems. It follows Semantic Versioning 2.0.0.
6
+ #
7
+ # @see https://semver.org/ Semantic Versioning 2.0.0
8
+ # @return [String] the current version in the format "major.minor.patch"
9
+ VERSION = "1.0.2".freeze
3
10
  end
data/lib/securial.rb CHANGED
@@ -1,11 +1,47 @@
1
+ # Main entry point for the Securial gem.
2
+ #
3
+ # This file serves as the primary entry point for the Securial gem,
4
+ # requiring necessary dependencies, setting up the module structure,
5
+ # and establishing method delegation.
6
+ #
7
+ # The Securial gem is a mountable Rails engine that provides authentication
8
+ # and authorization capabilities for Rails applications, supporting JWT,
9
+ # API tokens, and session-based authentication.
10
+ #
11
+ # @example Basic usage in a Rails application
12
+ # # In Gemfile
13
+ # gem 'securial'
14
+ #
15
+ # # In routes.rb
16
+ # Rails.application.routes.draw do
17
+ # mount Securial::Engine => '/securial'
18
+ # end
19
+ #
20
+ # @see Securial::Engine
21
+ # @see Securial::VERSION
22
+ #
1
23
  require "securial/version"
2
24
  require "securial/engine"
3
25
 
4
26
  require "jbuilder"
5
27
 
28
+ # Main namespace for the Securial authentication and authorization framework.
29
+ #
30
+ # This module provides access to core functionality of the Securial gem
31
+ # by exposing key helper methods and serving as the root namespace for
32
+ # all Securial components.
33
+ #
6
34
  module Securial
7
35
  extend self
8
36
 
37
+ # @!method protected_namespace
38
+ # Returns the namespace used for protected resources in the application.
39
+ # @return [String] the protected namespace designation
40
+
41
+ # @!method titleized_admin_role
42
+ # Returns the admin role name with proper title-case formatting.
43
+ # @return [String] the admin role title
44
+
9
45
  delegate :protected_namespace, to: Securial::Helpers::RolesHelper
10
46
  delegate :titleized_admin_role, to: Securial::Helpers::RolesHelper
11
47
  end