securial 1.0.0 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d6f0817d44bf16fef31a683152d11e38a0671a92f966df31257f8ab9b867c92
4
- data.tar.gz: ec7aa78f714a20598db55ecf92d69dc17d7dd38a137cce3964d8677ec622a46a
3
+ metadata.gz: 166aa60d38c7fecac2ec442467982af0fb09a7521aa12233b5a57a459aeba328
4
+ data.tar.gz: b4a27ad795aef20268a7912c0efc4df11c1cf58b62bf5d8814ee583c549f6f35
5
5
  SHA512:
6
- metadata.gz: 9435fcba0cb665df4992f193f0a8c0012f3dc676619a20b8824cdd085803337290c2453bf10494ef348d46259d0f1f9da48224abb1e70783c0f67e5e33deff2c
7
- data.tar.gz: 658cca7386b481757396384957d203f35abfb2f72ea56e7c538ea3f355014068e4921f7b4ba03967caa9563b5d3d4d32a1d4bf0257a0676e413bb2a1a394fbfd
6
+ metadata.gz: 3b5e7ebd0df4540a6814df63530ce6af969120ce50a34dbc5e6157103fd14108fcf19dffee65d318e5d31ee9851e3385a3d0069bd96cd3c8124dbd73f2e6db58
7
+ data.tar.gz: 00ac53e81274914b952e609ab57f777c9a4128520cbfff5044caad442f49ef2b89efeb84e6bec09d0f14e127a141b3ce53e9a352ab29082b68b3aee2a50a14f4
data/bin/securial CHANGED
@@ -1,26 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "fileutils"
4
- require_relative "../lib/securial/cli/show_version"
5
- require_relative "../lib/securial/cli/show_help"
6
- require_relative "../lib/securial/cli/run"
7
- require_relative "../lib/securial/cli/securial_new"
3
+ # Set up the load path for local development or gem installation
4
+ lib = File.expand_path("../../lib", __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
8
6
 
9
- case ARGV[0]
10
- when "-v", "--version"
11
- show_version
12
- when "-h", "--help"
13
- show_help
14
- when "new"
15
- if ARGV[1]
16
- app_name = ARGV[1]
17
- rails_options = ARGV[2..] || []
18
- securial_new(app_name, rails_options)
19
- else
20
- show_help
21
- exit(1)
22
- end
23
- else
24
- show_help
25
- exit(1)
26
- end
7
+ require "securial/cli"
8
+
9
+ Securial::CLI.start(ARGV)
@@ -4,10 +4,10 @@ require "rake"
4
4
  module Securial
5
5
  module Generators
6
6
  class InstallGenerator < Rails::Generators::Base
7
- source_root File.expand_path("templates", __dir__)
8
-
9
7
  desc "initializes Securial in your application."
10
8
 
9
+ source_root File.expand_path("templates", __dir__)
10
+
11
11
  def copy_initializer
12
12
  say_status("copying", "Securial Initializers", :green)
13
13
  template "securial_initializer.erb", "config/initializers/securial.rb"
@@ -5,9 +5,10 @@ module Securial
5
5
  module Generators
6
6
  module Install
7
7
  class ViewsGenerator < Rails::Generators::Base
8
- source_root Securial::Engine.root.join("app", "views", "securial").to_s
9
8
  desc "Copies Securial model-related views to your application for customization."
10
9
 
10
+ source_root Securial::Engine.root.join("app", "views", "securial").to_s
11
+
11
12
  def copy_model_views
12
13
  Dir.glob(File.join(self.class.source_root, "**/*")).each do |path|
13
14
  relative_path = Pathname.new(path).relative_path_from(Pathname.new(self.class.source_root))
@@ -1,6 +1,8 @@
1
1
  module Securial
2
2
  module Generators
3
3
  class JbuilderGenerator < Rails::Generators::NamedBase
4
+ desc "Generates Jbuilder view files for a given resource."
5
+
4
6
  source_root File.expand_path("templates", __dir__)
5
7
 
6
8
  argument :attributes, type: :array, default: [], banner: "field:type field:type"
@@ -5,6 +5,8 @@ require "rails/generators/named_base"
5
5
  module Securial
6
6
  module Generators
7
7
  class ScaffoldGenerator < Rails::Generators::NamedBase
8
+ desc "Creates a scaffold for a given resource, including model, controller, views, routes, and tests."
9
+
8
10
  include Rails::Generators::ResourceHelpers
9
11
 
10
12
  allow_incompatible_default_type!
@@ -3,7 +3,7 @@ require "jwt"
3
3
  module Securial
4
4
  module Auth
5
5
  module AuthEncoder
6
- module_function
6
+ extend self
7
7
 
8
8
  def encode(session)
9
9
  return nil unless session && session.class == Securial::Session
@@ -37,6 +37,8 @@ module Securial
37
37
  decoded.first
38
38
  end
39
39
 
40
+ private
41
+
40
42
  def secret
41
43
  Securial.configuration.session_secret
42
44
  end
@@ -48,8 +50,6 @@ module Securial
48
50
  def expiry_duration
49
51
  Securial.configuration.session_expiration_duration
50
52
  end
51
-
52
- private_class_method :secret, :algorithm, :expiry_duration
53
53
  end
54
54
  end
55
55
  end
@@ -1,7 +1,7 @@
1
1
  module Securial
2
2
  module Auth
3
3
  module SessionCreator
4
- module_function
4
+ extend self
5
5
 
6
6
  def create_session!(user, request)
7
7
  valid_user = user && user.is_a?(Securial::User) && user.persisted?
@@ -4,22 +4,22 @@ require "securerandom"
4
4
  module Securial
5
5
  module Auth
6
6
  module TokenGenerator
7
- class << self
8
- def generate_refresh_token
9
- secret = Securial.configuration.session_secret
10
- algo = "SHA256"
7
+ extend self
11
8
 
12
- random_data = SecureRandom.hex(32)
13
- digest = OpenSSL::Digest.new(algo)
14
- hmac = OpenSSL::HMAC.hexdigest(digest, secret, random_data)
9
+ def generate_refresh_token
10
+ secret = Securial.configuration.session_secret
11
+ algo = "SHA256"
15
12
 
16
- "#{hmac}#{random_data}"
17
- end
13
+ random_data = SecureRandom.hex(32)
14
+ digest = OpenSSL::Digest.new(algo)
15
+ hmac = OpenSSL::HMAC.hexdigest(digest, secret, random_data)
18
16
 
19
- def generate_password_reset_token
20
- token = SecureRandom.alphanumeric(12)
21
- "#{token[0, 6]}-#{token[6, 6]}"
22
- end
17
+ "#{hmac}#{random_data}"
18
+ end
19
+
20
+ def generate_password_reset_token
21
+ token = SecureRandom.alphanumeric(12)
22
+ "#{token[0, 6]}-#{token[6, 6]}"
23
23
  end
24
24
  end
25
25
  end
@@ -0,0 +1,158 @@
1
+ require "optparse"
2
+
3
+ # rubocop:disable Rails/Exit, Rails/Output
4
+
5
+ module Securial
6
+ class CLI
7
+ def self.start(argv)
8
+ new.start(argv)
9
+ end
10
+
11
+ def start(argv)
12
+ # Process options and exit if a flag was handled
13
+ result = handle_flags(argv)
14
+ exit(result) if result
15
+
16
+ # Otherwise handle commands
17
+ exit(handle_commands(argv))
18
+ end
19
+
20
+ private
21
+
22
+ def handle_flags(argv)
23
+ parser = create_option_parser
24
+
25
+ begin
26
+ parser.order!(argv)
27
+ nil # Continue to command handling
28
+ rescue OptionParser::InvalidOption => e
29
+ warn "ERROR: Illegal option(s): #{e.args.join(' ')}"
30
+ puts parser
31
+ 1
32
+ end
33
+ end
34
+
35
+ def handle_commands(argv)
36
+ cmd = argv.shift
37
+
38
+ case cmd
39
+ when "new"
40
+ handle_new_command(argv)
41
+ else
42
+ puts create_option_parser
43
+ 1
44
+ end
45
+ end
46
+
47
+ def handle_new_command(argv)
48
+ app_name = argv.shift
49
+
50
+ if app_name.nil?
51
+ puts "ERROR: Please provide an app name."
52
+ puts create_option_parser
53
+ return 1
54
+ end
55
+
56
+ securial_new(app_name, argv)
57
+ 0
58
+ end
59
+
60
+ def create_option_parser
61
+ OptionParser.new do |opts|
62
+ opts.banner = "Usage: securial [options] <command> [command options]\n\n"
63
+
64
+ opts.separator ""
65
+ opts.separator "Commands:"
66
+ opts.separator " new APP_NAME [rails_options...] # Create a new Rails app with Securial pre-installed"
67
+ opts.separator ""
68
+ opts.separator "Options:"
69
+
70
+ opts.on("-v", "--version", "Show Securial version") do
71
+ show_version
72
+ exit(0)
73
+ end
74
+
75
+ opts.on("-h", "--help", "Show this help message") do
76
+ puts opts
77
+ exit(0)
78
+ end
79
+ end
80
+ end
81
+
82
+ def show_version
83
+ require "securial/version"
84
+ puts "Securial v#{Securial::VERSION}"
85
+ rescue LoadError
86
+ puts "Securial version information not available."
87
+ end
88
+
89
+ def securial_new(app_name, rails_options)
90
+ puts "🏗️ Creating new Rails app: #{app_name}"
91
+
92
+ create_rails_app(app_name, rails_options)
93
+ add_securial_gem(app_name)
94
+ install_gems(app_name)
95
+ install_securial(app_name)
96
+ mount_securial_engine(app_name)
97
+ print_final_instructions(app_name)
98
+ end
99
+
100
+ def create_rails_app(app_name, rails_options)
101
+ rails_command = ["rails", "new", app_name, *rails_options]
102
+ run(rails_command)
103
+ end
104
+
105
+ def add_securial_gem(app_name)
106
+ puts "📦 Adding Securial gem to Gemfile"
107
+ gemfile_path = File.join(app_name, "Gemfile")
108
+ File.open(gemfile_path, "a") { |f| f.puts "\ngem 'securial'" }
109
+ end
110
+
111
+ def install_gems(app_name)
112
+ run("bundle install", chdir: app_name)
113
+ end
114
+
115
+ def install_securial(app_name)
116
+ puts "🔧 Installing Securial"
117
+ run("bin/rails generate securial:install", chdir: app_name)
118
+ run("bin/rails db:migrate", chdir: app_name)
119
+ end
120
+
121
+ def mount_securial_engine(app_name)
122
+ puts "🔗 Mounting Securial engine in routes"
123
+ routes_path = File.join(app_name, "config/routes.rb")
124
+ routes = File.read(routes_path)
125
+ updated = routes.sub("Rails.application.routes.draw do") do |match|
126
+ "#{match}\n mount Securial::Engine => '/securial'"
127
+ end
128
+ File.write(routes_path, updated)
129
+ end
130
+
131
+ def print_final_instructions(app_name)
132
+ puts <<~INSTRUCTIONS
133
+ 🎉 Securial has been successfully installed in your Rails app!
134
+ ✅ Your app is ready at: ./#{app_name}
135
+
136
+ ➡️ Next steps:
137
+ cd #{app_name}
138
+ ⚙️ Optional: Configure Securial in config/initializers/securial.rb
139
+ rails server
140
+ INSTRUCTIONS
141
+ end
142
+
143
+ def run(command, chdir: nil)
144
+ puts "→ #{command.inspect}"
145
+ result =
146
+ if chdir
147
+ Dir.chdir(chdir) { system(*command) }
148
+ else
149
+ system(*command)
150
+ end
151
+
152
+ unless result
153
+ abort("❌ Command failed: #{command}")
154
+ end
155
+ 0
156
+ end
157
+ end
158
+ end
@@ -47,7 +47,7 @@ module Securial
47
47
 
48
48
  def roles_signature
49
49
  {
50
- admin_role: { type: String, required: true, default: "admin" },
50
+ admin_role: { type: Symbol, required: true, default: :admin },
51
51
  }
52
52
  end
53
53
 
@@ -3,68 +3,67 @@ require "securial/logger"
3
3
  module Securial
4
4
  module Config
5
5
  module Validation
6
- class << self
7
- def validate_all!(securial_config)
8
- signature = Securial::Config::Signature.config_signature
6
+ extend self
7
+ def validate_all!(securial_config)
8
+ signature = Securial::Config::Signature.config_signature
9
9
 
10
- validate_required_fields!(signature, securial_config)
11
- validate_types_and_values!(signature, securial_config)
12
- validate_password_lengths!(securial_config)
13
- end
10
+ validate_required_fields!(signature, securial_config)
11
+ validate_types_and_values!(signature, securial_config)
12
+ validate_password_lengths!(securial_config)
13
+ end
14
14
 
15
- private
15
+ private
16
16
 
17
- def validate_required_fields!(signature, config)
18
- signature.each do |key, options|
19
- value = config.send(key)
20
- required = options[:required]
21
- if required == true && value.nil?
22
- raise_error("#{key} is required but not provided.")
23
- elsif required.is_a?(String)
24
- dynamic_required = config.send(required)
25
- signature[key][:required] = dynamic_required
26
- if dynamic_required && value.nil?
27
- raise_error("#{key} is required but not provided when #{required} is true.")
28
- end
17
+ def validate_required_fields!(signature, config)
18
+ signature.each do |key, options|
19
+ value = config.send(key)
20
+ required = options[:required]
21
+ if required == true && value.nil?
22
+ raise_error("#{key} is required but not provided.")
23
+ elsif required.is_a?(String)
24
+ dynamic_required = config.send(required)
25
+ signature[key][:required] = dynamic_required
26
+ if dynamic_required && value.nil?
27
+ raise_error("#{key} is required but not provided when #{required} is true.")
29
28
  end
30
29
  end
31
30
  end
31
+ end
32
32
 
33
- def validate_types_and_values!(signature, config)
34
- signature.each do |key, options|
35
- next unless signature[key][:required]
36
- value = config.send(key)
37
- types = Array(options[:type])
33
+ def validate_types_and_values!(signature, config)
34
+ signature.each do |key, options|
35
+ next unless signature[key][:required]
36
+ value = config.send(key)
37
+ types = Array(options[:type])
38
38
 
39
- unless types.any? { |type| value.is_a?(type) }
40
- raise_error("#{key} must be of type(s) #{types.join(', ')}, but got #{value.class}.")
41
- end
42
-
43
- if options[:type] == ActiveSupport::Duration && value <= 0
44
- raise_error("#{key} must be a positive duration, but got #{value}.")
45
- end
39
+ unless types.any? { |type| value.is_a?(type) }
40
+ raise_error("#{key} must be of type(s) #{types.join(', ')}, but got #{value.class}.")
41
+ end
46
42
 
47
- if options[:type] == Numeric && value < 0
48
- raise_error("#{key} must be a non-negative numeric value, but got #{value}.")
49
- end
43
+ if options[:type] == ActiveSupport::Duration && value <= 0
44
+ raise_error("#{key} must be a positive duration, but got #{value}.")
45
+ end
50
46
 
51
- if options[:allowed_values] && options[:allowed_values].exclude?(value)
52
- raise_error("#{key} must be one of #{options[:allowed_values].join(', ')}, but got #{value}.")
53
- end
47
+ if options[:type] == Numeric && value < 0
48
+ raise_error("#{key} must be a non-negative numeric value, but got #{value}.")
54
49
  end
55
- end
56
50
 
57
- def validate_password_lengths!(config)
58
- if config.password_min_length > config.password_max_length
59
- raise_error("password_min_length cannot be greater than password_max_length.")
51
+ if options[:allowed_values] && options[:allowed_values].exclude?(value)
52
+ raise_error("#{key} must be one of #{options[:allowed_values].join(', ')}, but got #{value}.")
60
53
  end
61
54
  end
55
+ end
62
56
 
63
- def raise_error(msg)
64
- Securial.logger.fatal msg
65
- raise Securial::Error::Config::InvalidConfigurationError, msg
57
+ def validate_password_lengths!(config)
58
+ if config.password_min_length > config.password_max_length
59
+ raise_error("password_min_length cannot be greater than password_max_length.")
66
60
  end
67
61
  end
62
+
63
+ def raise_error(msg)
64
+ Securial.logger.fatal msg
65
+ raise Securial::Error::Config::InvalidConfigurationError, msg
66
+ end
68
67
  end
69
68
  end
70
69
  end
@@ -4,25 +4,24 @@ require "securial/config/validation"
4
4
 
5
5
 
6
6
  module Securial
7
- class << self
8
- attr_accessor :configuration
7
+ extend self
8
+ attr_accessor :configuration
9
9
 
10
- def configuration
11
- @configuration ||= Config::Configuration.new
12
- end
13
-
14
- def configuration=(config)
15
- if config.is_a?(Config::Configuration)
16
- @configuration = config
17
- Securial::Config::Validation.validate_all!(configuration)
18
- else
19
- raise ArgumentError, "Expected an instance of Securial::Config::Configuration"
20
- end
21
- end
10
+ def configuration
11
+ @configuration ||= Config::Configuration.new
12
+ end
22
13
 
23
- def configure
24
- yield(configuration) if block_given?
14
+ def configuration=(config)
15
+ if config.is_a?(Config::Configuration)
16
+ @configuration = config
25
17
  Securial::Config::Validation.validate_all!(configuration)
18
+ else
19
+ raise ArgumentError, "Expected an instance of Securial::Config::Configuration"
26
20
  end
27
21
  end
22
+
23
+ def configure
24
+ yield(configuration) if block_given?
25
+ Securial::Config::Validation.validate_all!(configuration)
26
+ end
28
27
  end
@@ -1,13 +1,15 @@
1
1
  module Securial
2
2
  module Error
3
3
  class BaseError < StandardError
4
+ class_attribute :_default_message, instance_writer: false
5
+
4
6
  def self.default_message(message = nil)
5
- @default_message = message if message
6
- @default_message
7
+ self._default_message = message if message
8
+ self._default_message
7
9
  end
8
10
 
9
11
  def initialize(message = nil)
10
- super(message || self.class.default_message || "An error occurred in Securial")
12
+ super(message || self.class._default_message || "An error occurred in Securial")
11
13
  end
12
14
 
13
15
  def backtrace; []; end
@@ -1,7 +1,7 @@
1
1
  module Securial
2
2
  module Helpers
3
3
  module KeyTransformer
4
- module_function
4
+ extend self
5
5
 
6
6
  def camelize(str, format)
7
7
  case format
@@ -1,7 +1,7 @@
1
1
  module Securial
2
2
  module Helpers
3
3
  module NormalizingHelper
4
- module_function
4
+ extend self
5
5
 
6
6
  def normalize_email_address(email)
7
7
  return "" if email.empty?
@@ -5,14 +5,13 @@ module Securial
5
5
  USERNAME_REGEX = /\A(?![0-9])[a-zA-Z](?:[a-zA-Z0-9]|[._](?![._]))*[a-zA-Z0-9]\z/
6
6
  PASSWORD_REGEX = %r{\A(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])[a-zA-Z].*\z}
7
7
 
8
- class << self
9
- def valid_email?(email)
10
- email.match?(EMAIL_REGEX)
11
- end
8
+ extend self
9
+ def valid_email?(email)
10
+ email.match?(EMAIL_REGEX)
11
+ end
12
12
 
13
- def valid_username?(username)
14
- username.match?(USERNAME_REGEX)
15
- end
13
+ def valid_username?(username)
14
+ username.match?(USERNAME_REGEX)
16
15
  end
17
16
  end
18
17
  end
@@ -3,14 +3,13 @@ module Securial
3
3
  module RolesHelper
4
4
  # This module provides helper methods related to roles.
5
5
  # It can be extended with additional role-related functionality as needed.
6
- class << self
7
- def protected_namespace
8
- Securial.configuration.admin_role.to_s.strip.underscore.pluralize
9
- end
6
+ extend self
7
+ def protected_namespace
8
+ Securial.configuration.admin_role.to_s.strip.underscore.pluralize
9
+ end
10
10
 
11
- def titleized_admin_role
12
- Securial.configuration.admin_role.to_s.strip.titleize
13
- end
11
+ def titleized_admin_role
12
+ Securial.configuration.admin_role.to_s.strip.titleize
14
13
  end
15
14
  end
16
15
  end
@@ -1,15 +1,14 @@
1
1
  require_relative "logger/builder"
2
2
 
3
3
  module Securial
4
- class << self
5
- attr_accessor :logger
4
+ extend self
5
+ attr_accessor :logger
6
6
 
7
- def logger
8
- @logger ||= Logger::Builder.build
9
- end
7
+ def logger
8
+ @logger ||= Logger::Builder.build
9
+ end
10
10
 
11
- def logger=(logger)
12
- @logger = logger
13
- end
11
+ def logger=(logger)
12
+ @logger = logger
14
13
  end
15
14
  end
@@ -4,7 +4,7 @@ require "securial/config"
4
4
  module Securial
5
5
  module Security
6
6
  module RequestRateLimiter
7
- module_function
7
+ extend self
8
8
 
9
9
  def apply! # rubocop:disable Metrics/MethodLength
10
10
  resp_status = Securial.configuration.rate_limit_response_status
@@ -1,3 +1,3 @@
1
1
  module Securial
2
- VERSION = "1.0.0".freeze
2
+ VERSION = "1.0.1".freeze
3
3
  end
data/lib/securial.rb CHANGED
@@ -4,8 +4,8 @@ require "securial/engine"
4
4
  require "jbuilder"
5
5
 
6
6
  module Securial
7
- class << self
8
- delegate :protected_namespace, to: Securial::Helpers::RolesHelper
9
- delegate :titleized_admin_role, to: Securial::Helpers::RolesHelper
10
- end
7
+ extend self
8
+
9
+ delegate :protected_namespace, to: Securial::Helpers::RolesHelper
10
+ delegate :titleized_admin_role, to: Securial::Helpers::RolesHelper
11
11
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: securial
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aly Badawy
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-06-18 00:00:00.000000000 Z
10
+ date: 2025-06-24 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -55,16 +55,22 @@ dependencies:
55
55
  name: jwt
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
61
+ - - "<"
59
62
  - !ruby/object:Gem::Version
60
- version: 3.0.0
63
+ version: '3.2'
61
64
  type: :runtime
62
65
  prerelease: false
63
66
  version_requirements: !ruby/object:Gem::Requirement
64
67
  requirements:
65
- - - "~>"
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '3.0'
71
+ - - "<"
66
72
  - !ruby/object:Gem::Version
67
- version: 3.0.0
73
+ version: '3.2'
68
74
  - !ruby/object:Gem::Dependency
69
75
  name: rack-attack
70
76
  requirement: !ruby/object:Gem::Requirement
@@ -161,10 +167,7 @@ files:
161
167
  - lib/securial/auth/auth_encoder.rb
162
168
  - lib/securial/auth/session_creator.rb
163
169
  - lib/securial/auth/token_generator.rb
164
- - lib/securial/cli/run.rb
165
- - lib/securial/cli/securial_new.rb
166
- - lib/securial/cli/show_help.rb
167
- - lib/securial/cli/show_version.rb
170
+ - lib/securial/cli.rb
168
171
  - lib/securial/config.rb
169
172
  - lib/securial/config/configuration.rb
170
173
  - lib/securial/config/signature.rb
@@ -202,7 +205,7 @@ homepage: https://github.com/AlyBadawy/Securial/wiki
202
205
  licenses:
203
206
  - MIT
204
207
  metadata:
205
- release_date: '2025-06-18'
208
+ release_date: '2025-06-24'
206
209
  allowed_push_host: https://rubygems.org
207
210
  homepage_uri: https://github.com/AlyBadawy/Securial/wiki
208
211
  source_code_uri: https://github.com/AlyBadawy/Securial
@@ -1,11 +0,0 @@
1
- # rubocop:disable Rails/Output
2
- def run(command, chdir: nil)
3
- puts "→ #{command}"
4
- if chdir
5
- Dir.chdir(chdir) do
6
- system(command) || abort("❌ Command failed: #{command}")
7
- end
8
- else
9
- system(command) || abort("❌ Command failed: #{command}")
10
- end
11
- end
@@ -1,53 +0,0 @@
1
- # rubocop:disable Rails/Output
2
- require_relative "run"
3
-
4
- def securial_new(app_name, rails_options)
5
- puts "🏗️ Creating new Rails app: #{app_name}"
6
- create_rails_app(app_name, rails_options)
7
- add_securial_gem(app_name)
8
- install_gems(app_name)
9
- install_securial(app_name)
10
- mount_securial_engine(app_name)
11
- print_final_instructions(app_name)
12
- end
13
-
14
- def create_rails_app(app_name, rails_options)
15
- rails_command = ["rails", "new", app_name, *rails_options].join(" ")
16
- run(rails_command)
17
- end
18
-
19
- def add_securial_gem(app_name)
20
- puts "📦 Adding Securial gem to Gemfile"
21
- gemfile_path = File.join(app_name, "Gemfile")
22
- File.open(gemfile_path, "a") { |f| f.puts "\ngem 'securial'" }
23
- end
24
-
25
- def install_gems(app_name)
26
- run("bundle install", chdir: app_name)
27
- end
28
-
29
- def install_securial(app_name)
30
- puts "🔧 Installing Securial"
31
- run("bin/rails generate securial:install", chdir: app_name)
32
- run("bin/rails db:migrate", chdir: app_name)
33
- end
34
-
35
- def mount_securial_engine(app_name)
36
- puts "🔗 Mounting Securial engine in routes"
37
- routes_path = File.join(app_name, "config/routes.rb")
38
- routes = File.read(routes_path)
39
- updated = routes.sub("Rails.application.routes.draw do") do |match|
40
- "#{match}\n mount Securial::Engine => '/securial'"
41
- end
42
- File.write(routes_path, updated)
43
- end
44
-
45
- def print_final_instructions(app_name)
46
- puts "🎉 Securial has been successfully installed in your Rails app!"
47
- puts "✅ Your app is ready at: ./#{app_name}"
48
- puts ""
49
- puts "➡️ Next steps:"
50
- puts " cd #{app_name}"
51
- puts "⚙️ Optional: Configure Securial in config/initializers/securial.rb"
52
- puts " rails server"
53
- end
@@ -1,26 +0,0 @@
1
- # rubocop:disable Rails/Output
2
- def show_help
3
- puts <<~HELP
4
- Securial CLI
5
-
6
- Securial is a mountable Rails engine that provides robust, extensible
7
- authentication and access control for Rails applications. It supports JWT,
8
- API tokens, session-based auth, and is designed for easy integration with
9
- modern web and mobile apps.
10
-
11
- Usage:
12
- securial new APP_NAME [rails_options...] # Create a new Rails app with Securial pre-installed
13
- securial -v, --version # Show the Securial gem version
14
- securial -h, --help # Show this help message
15
-
16
- Example:
17
- securial new myapp --api --database=postgresql -T
18
-
19
- More Info:
20
- review the [Changelog] and [WIKI] for more info on the latest
21
- changes and how to use this gem/engine:
22
- [Changelog]: https://github.com/AlyBadawy/Securial/blob/main/CHANGELOG.md
23
- [WIKI]: https://github.com/AlyBadawy/Securial/wiki
24
-
25
- HELP
26
- end
@@ -1,9 +0,0 @@
1
- # rubocop:disable Rails/Output
2
- def show_version
3
- begin
4
- require "securial/version"
5
- puts "Securial v#{Securial::VERSION}"
6
- rescue LoadError
7
- puts "Securial version information not available."
8
- end
9
- end