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 +4 -4
- data/bin/securial +6 -23
- data/lib/generators/securial/install/install_generator.rb +2 -2
- data/lib/generators/securial/install/views_generator.rb +2 -1
- data/lib/generators/securial/jbuilder/jbuilder_generator.rb +2 -0
- data/lib/generators/securial/scaffold/scaffold_generator.rb +2 -0
- data/lib/securial/auth/auth_encoder.rb +3 -3
- data/lib/securial/auth/session_creator.rb +1 -1
- data/lib/securial/auth/token_generator.rb +13 -13
- data/lib/securial/cli.rb +158 -0
- data/lib/securial/config/signature.rb +1 -1
- data/lib/securial/config/validation.rb +44 -45
- data/lib/securial/config.rb +15 -16
- data/lib/securial/error/base_securial_error.rb +5 -3
- data/lib/securial/helpers/key_transformer.rb +1 -1
- data/lib/securial/helpers/normalizing_helper.rb +1 -1
- data/lib/securial/helpers/regex_helper.rb +6 -7
- data/lib/securial/helpers/roles_helper.rb +6 -7
- data/lib/securial/logger.rb +7 -8
- data/lib/securial/security/request_rate_limiter.rb +1 -1
- data/lib/securial/version.rb +1 -1
- data/lib/securial.rb +4 -4
- metadata +14 -11
- data/lib/securial/cli/run.rb +0 -11
- data/lib/securial/cli/securial_new.rb +0 -53
- data/lib/securial/cli/show_help.rb +0 -26
- data/lib/securial/cli/show_version.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 166aa60d38c7fecac2ec442467982af0fb09a7521aa12233b5a57a459aeba328
|
4
|
+
data.tar.gz: b4a27ad795aef20268a7912c0efc4df11c1cf58b62bf5d8814ee583c549f6f35
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
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
|
@@ -4,22 +4,22 @@ require "securerandom"
|
|
4
4
|
module Securial
|
5
5
|
module Auth
|
6
6
|
module TokenGenerator
|
7
|
-
|
8
|
-
def generate_refresh_token
|
9
|
-
secret = Securial.configuration.session_secret
|
10
|
-
algo = "SHA256"
|
7
|
+
extend self
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
def generate_refresh_token
|
10
|
+
secret = Securial.configuration.session_secret
|
11
|
+
algo = "SHA256"
|
15
12
|
|
16
|
-
|
17
|
-
|
13
|
+
random_data = SecureRandom.hex(32)
|
14
|
+
digest = OpenSSL::Digest.new(algo)
|
15
|
+
hmac = OpenSSL::HMAC.hexdigest(digest, secret, random_data)
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
data/lib/securial/cli.rb
ADDED
@@ -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
|
@@ -3,68 +3,67 @@ require "securial/logger"
|
|
3
3
|
module Securial
|
4
4
|
module Config
|
5
5
|
module Validation
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
extend self
|
7
|
+
def validate_all!(securial_config)
|
8
|
+
signature = Securial::Config::Signature.config_signature
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
15
|
+
private
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
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
|
-
|
58
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
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
|
data/lib/securial/config.rb
CHANGED
@@ -4,25 +4,24 @@ require "securial/config/validation"
|
|
4
4
|
|
5
5
|
|
6
6
|
module Securial
|
7
|
-
|
8
|
-
|
7
|
+
extend self
|
8
|
+
attr_accessor :configuration
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
24
|
-
|
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
|
-
|
6
|
-
|
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.
|
12
|
+
super(message || self.class._default_message || "An error occurred in Securial")
|
11
13
|
end
|
12
14
|
|
13
15
|
def backtrace; []; end
|
@@ -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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
extend self
|
9
|
+
def valid_email?(email)
|
10
|
+
email.match?(EMAIL_REGEX)
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
extend self
|
7
|
+
def protected_namespace
|
8
|
+
Securial.configuration.admin_role.to_s.strip.underscore.pluralize
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
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
|
data/lib/securial/logger.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
require_relative "logger/builder"
|
2
2
|
|
3
3
|
module Securial
|
4
|
-
|
5
|
-
|
4
|
+
extend self
|
5
|
+
attr_accessor :logger
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def logger
|
8
|
+
@logger ||= Logger::Builder.build
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
end
|
11
|
+
def logger=(logger)
|
12
|
+
@logger = logger
|
14
13
|
end
|
15
14
|
end
|
data/lib/securial/version.rb
CHANGED
data/lib/securial.rb
CHANGED
@@ -4,8 +4,8 @@ require "securial/engine"
|
|
4
4
|
require "jbuilder"
|
5
5
|
|
6
6
|
module Securial
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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.
|
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-
|
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.
|
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.
|
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
|
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-
|
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
|
data/lib/securial/cli/run.rb
DELETED
@@ -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
|