console1984 0.1.8 → 0.1.12
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/config/protections.yml +13 -12
- data/lib/console1984/command_executor.rb +15 -3
- data/lib/console1984/command_validator/.command_parser.rb +69 -0
- data/lib/console1984/command_validator/forbidden_constant_reference_validation.rb +2 -2
- data/lib/console1984/command_validator/forbidden_reopening_validation.rb +2 -2
- data/lib/console1984/command_validator/parsed_command.rb +3 -69
- data/lib/console1984/command_validator/suspicious_terms_validation.rb +1 -1
- data/lib/console1984/command_validator.rb +1 -1
- data/lib/console1984/errors.rb +6 -2
- data/lib/console1984/ext/active_record/protected_auditable_tables.rb +1 -1
- data/lib/console1984/ext/core/module.rb +18 -1
- data/lib/console1984/ext/core/object.rb +1 -1
- data/lib/console1984/freezeable.rb +1 -1
- data/lib/console1984/protections_config.rb +2 -2
- data/lib/console1984/refrigerator.rb +6 -7
- data/lib/console1984/shield/method_invocation_shell.rb +6 -12
- data/lib/console1984/supervisor.rb +9 -0
- data/lib/console1984/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3bfdacf3954fbc30c23046c89f7951d061c419533685fb5ecc2db6a6cf41a1d
|
4
|
+
data.tar.gz: 0b26c9effb7ffdd1df5ca51c344c53c3d9260bef1b02c4c2d9e6c8949dceb032
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b24bf1fbfc353fdd8b5ac2194f4f30588281269748ea192def291cdedc19697b1bd75bff71baec0761e45ff08ec78aca78ff41d0b78c8ca6ae1cea4bdb43512e
|
7
|
+
data.tar.gz: 43628c0bd4f76662b65f1c343885618a4c54e2b8b40d536720f8c3eecd696ae51c03c78329810387598e68042622b6c6c15f6b015caf3b93d6fb3779bf349f95
|
data/config/protections.yml
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
-
|
1
|
+
validations:
|
2
2
|
forbidden_reopening:
|
3
3
|
- ActiveRecord
|
4
4
|
- Console1984
|
5
5
|
- PG
|
6
6
|
- Mysql2
|
7
|
+
- IRB
|
7
8
|
forbidden_constant_reference:
|
8
9
|
always:
|
9
10
|
- Console1984
|
11
|
+
- IRB
|
10
12
|
protected:
|
11
13
|
- PG
|
12
14
|
- Mysql2
|
@@ -16,15 +18,14 @@ static_validations:
|
|
16
18
|
- Console1984
|
17
19
|
- secret
|
18
20
|
- credentials
|
21
|
+
- irb
|
19
22
|
forbidden_methods:
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
Module:
|
30
|
-
- class_eval
|
23
|
+
Kernel:
|
24
|
+
- eval
|
25
|
+
Object:
|
26
|
+
- eval
|
27
|
+
BasicObject:
|
28
|
+
- eval
|
29
|
+
- instance_eval
|
30
|
+
Module:
|
31
|
+
- class_eval
|
@@ -19,11 +19,15 @@ class Console1984::CommandExecutor
|
|
19
19
|
run_as_system { session_logger.before_executing commands }
|
20
20
|
validate_command commands
|
21
21
|
execute_in_protected_mode(&block)
|
22
|
-
rescue Console1984::Errors::
|
22
|
+
rescue Console1984::Errors::ForbiddenCommandAttempted, FrozenError
|
23
23
|
flag_suspicious(commands)
|
24
|
-
rescue Console1984::Errors::
|
24
|
+
rescue Console1984::Errors::SuspiciousCommandAttempted
|
25
25
|
flag_suspicious(commands)
|
26
26
|
execute_in_protected_mode(&block)
|
27
|
+
rescue Console1984::Errors::ForbiddenCommandExecuted
|
28
|
+
# We detected that a forbidden command was executed. We exit IRB right away.
|
29
|
+
flag_suspicious(commands)
|
30
|
+
Console1984.supervisor.exit_irb
|
27
31
|
ensure
|
28
32
|
run_as_system { session_logger.after_executing commands }
|
29
33
|
end
|
@@ -65,13 +69,21 @@ class Console1984::CommandExecutor
|
|
65
69
|
command_validator.validate(command)
|
66
70
|
end
|
67
71
|
|
72
|
+
def from_irb?(backtrace)
|
73
|
+
executing_user_command? && backtrace.find do |line|
|
74
|
+
line_from_irb = line =~ /^[^\/]/
|
75
|
+
break if !(line =~ /console1984\/lib/ || line_from_irb)
|
76
|
+
line_from_irb
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
68
80
|
private
|
69
81
|
def command_validator
|
70
82
|
@command_validator ||= build_command_validator
|
71
83
|
end
|
72
84
|
|
73
85
|
def build_command_validator
|
74
|
-
Console1984::CommandValidator.from_config(Console1984.protections_config.
|
86
|
+
Console1984::CommandValidator.from_config(Console1984.protections_config.validations)
|
75
87
|
end
|
76
88
|
|
77
89
|
def flag_suspicious(commands)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Naming class with dot so that it doesn't get loaded eagerly by Zeitwork. We want to load
|
2
|
+
# only when a console session is started, when +parser+ is loaded.
|
3
|
+
#
|
4
|
+
# See +Console1984::Supervisor#require_dependencies+
|
5
|
+
class Console1984::CommandValidator::CommandParser < ::Parser::AST::Processor
|
6
|
+
include AST::Processor::Mixin
|
7
|
+
include Console1984::Freezeable
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@constants = []
|
11
|
+
@declared_classes_or_modules = []
|
12
|
+
@constant_assignments = []
|
13
|
+
end
|
14
|
+
|
15
|
+
# We define accessors to define lists without duplicates. We are not using a +SortedSet+ because we want
|
16
|
+
# to mutate strings in the list while the processing is happening. And we don't use metapgroamming to define the
|
17
|
+
# accessors to prevent having problems with freezable and its instance_variable* protection.
|
18
|
+
|
19
|
+
def constants
|
20
|
+
@constants.uniq
|
21
|
+
end
|
22
|
+
|
23
|
+
def declared_classes_or_modules
|
24
|
+
@declared_classes_or_modules.uniq
|
25
|
+
end
|
26
|
+
|
27
|
+
def constant_assignments
|
28
|
+
@constant_assignments.uniq
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_class(node)
|
32
|
+
super
|
33
|
+
const_declaration, _, _ = *node
|
34
|
+
constant = extract_constants(const_declaration).first
|
35
|
+
@declared_classes_or_modules << constant if constant.present?
|
36
|
+
end
|
37
|
+
|
38
|
+
alias_method :on_module, :on_class
|
39
|
+
|
40
|
+
def on_const(node)
|
41
|
+
super
|
42
|
+
name, const_name = *node
|
43
|
+
const_name = const_name.to_s
|
44
|
+
last_constant = @constants.last
|
45
|
+
|
46
|
+
if name.nil? || (name && name.type == :cbase) # cbase = leading ::
|
47
|
+
if last_constant&.end_with?("::")
|
48
|
+
last_constant << const_name
|
49
|
+
else
|
50
|
+
@constants << const_name
|
51
|
+
end
|
52
|
+
elsif last_constant
|
53
|
+
last_constant << "::#{const_name}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def on_casgn(node)
|
58
|
+
super
|
59
|
+
scope_node, name, value_node = *node
|
60
|
+
@constant_assignments.push(*extract_constants(value_node))
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def extract_constants(node)
|
65
|
+
self.class.new.tap do |processor|
|
66
|
+
processor.process(node)
|
67
|
+
end.constants
|
68
|
+
end
|
69
|
+
end
|
@@ -14,11 +14,11 @@ class Console1984::CommandValidator::ForbiddenConstantReferenceValidation
|
|
14
14
|
@constant_names_forbidden_in_protected_mode = config[:protected] || []
|
15
15
|
end
|
16
16
|
|
17
|
-
# Raises a Console1984::Errors::
|
17
|
+
# Raises a Console1984::Errors::ForbiddenCommandAttempted if a banned constant is referenced.
|
18
18
|
def validate(parsed_command)
|
19
19
|
if contains_invalid_const_reference?(parsed_command, @forbidden_constants_names) ||
|
20
20
|
(@shield.protected_mode? && contains_invalid_const_reference?(parsed_command, @constant_names_forbidden_in_protected_mode))
|
21
|
-
raise Console1984::Errors::
|
21
|
+
raise Console1984::Errors::ForbiddenCommandAttempted
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -8,11 +8,11 @@ class Console1984::CommandValidator::ForbiddenReopeningValidation
|
|
8
8
|
@banned_class_or_module_names = banned_classes_or_modules.collect(&:to_s)
|
9
9
|
end
|
10
10
|
|
11
|
-
# Raises a Console1984::Errors::
|
11
|
+
# Raises a Console1984::Errors::ForbiddenCommandAttempted if an banned class or module reopening
|
12
12
|
# is detected.
|
13
13
|
def validate(parsed_command)
|
14
14
|
if contains_invalid_class_or_module_declaration?(parsed_command)
|
15
|
-
raise Console1984::Errors::
|
15
|
+
raise Console1984::Errors::ForbiddenCommandAttempted
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -6,85 +6,19 @@ class Console1984::CommandValidator::ParsedCommand
|
|
6
6
|
|
7
7
|
attr_reader :raw_command
|
8
8
|
|
9
|
-
delegate :declared_classes_or_modules, :constants, :constant_assignments, to: :
|
9
|
+
delegate :declared_classes_or_modules, :constants, :constant_assignments, to: :command_parser
|
10
10
|
|
11
11
|
def initialize(raw_command)
|
12
12
|
@raw_command = Array(raw_command).join("\n")
|
13
13
|
end
|
14
14
|
|
15
15
|
private
|
16
|
-
def
|
17
|
-
@
|
16
|
+
def command_parser
|
17
|
+
@command_parser ||= Console1984::CommandValidator::CommandParser.new.tap do |processor|
|
18
18
|
ast = Parser::CurrentRuby.parse(raw_command)
|
19
19
|
processor.process(ast)
|
20
20
|
rescue Parser::SyntaxError
|
21
21
|
# Fail open with syntax errors
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
25
|
-
class CommandProcessor < ::Parser::AST::Processor
|
26
|
-
include AST::Processor::Mixin
|
27
|
-
include Console1984::Freezeable
|
28
|
-
|
29
|
-
def initialize
|
30
|
-
@constants = []
|
31
|
-
@declared_classes_or_modules = []
|
32
|
-
@constant_assignments = []
|
33
|
-
end
|
34
|
-
|
35
|
-
# We define accessors to define lists without duplicates. We are not using a +SortedSet+ because we want
|
36
|
-
# to mutate strings in the list while the processing is happening. And we don't use metapgroamming to define the
|
37
|
-
# accessors to prevent having problems with freezable and its instance_variable* protection.
|
38
|
-
|
39
|
-
def constants
|
40
|
-
@constants.uniq
|
41
|
-
end
|
42
|
-
|
43
|
-
def declared_classes_or_modules
|
44
|
-
@declared_classes_or_modules.uniq
|
45
|
-
end
|
46
|
-
|
47
|
-
def constant_assignments
|
48
|
-
@constant_assignments.uniq
|
49
|
-
end
|
50
|
-
|
51
|
-
def on_class(node)
|
52
|
-
super
|
53
|
-
const_declaration, _, _ = *node
|
54
|
-
constant = extract_constants(const_declaration).first
|
55
|
-
@declared_classes_or_modules << constant if constant.present?
|
56
|
-
end
|
57
|
-
|
58
|
-
alias_method :on_module, :on_class
|
59
|
-
|
60
|
-
def on_const(node)
|
61
|
-
super
|
62
|
-
name, const_name = *node
|
63
|
-
const_name = const_name.to_s
|
64
|
-
last_constant = @constants.last
|
65
|
-
|
66
|
-
if name.nil? || (name && name.type == :cbase) # cbase = leading ::
|
67
|
-
if last_constant&.end_with?("::")
|
68
|
-
last_constant << const_name
|
69
|
-
else
|
70
|
-
@constants << const_name
|
71
|
-
end
|
72
|
-
elsif last_constant
|
73
|
-
last_constant << "::#{const_name}"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def on_casgn(node)
|
78
|
-
super
|
79
|
-
scope_node, name, value_node = *node
|
80
|
-
@constant_assignments.push(*extract_constants(value_node))
|
81
|
-
end
|
82
|
-
|
83
|
-
private
|
84
|
-
def extract_constants(node)
|
85
|
-
self.class.new.tap do |processor|
|
86
|
-
processor.process(node)
|
87
|
-
end.constants
|
88
|
-
end
|
89
|
-
end
|
90
24
|
end
|
@@ -9,7 +9,7 @@ class Console1984::CommandValidator::SuspiciousTermsValidation
|
|
9
9
|
# Raises a Console1984::Errors::SuspiciousCommand if the term is referenced.
|
10
10
|
def validate(parsed_command)
|
11
11
|
if contains_suspicious_term?(parsed_command)
|
12
|
-
raise Console1984::Errors::
|
12
|
+
raise Console1984::Errors::SuspiciousCommandAttempted
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -5,7 +5,7 @@
|
|
5
5
|
#
|
6
6
|
# The validation itself happens as a chain of validation objects. The system will invoke
|
7
7
|
# each validation in order. Validations will raise an error if the validation fails (typically
|
8
|
-
# a Console1984::Errors::
|
8
|
+
# a Console1984::Errors::ForbiddenCommandAttempted or Console1984::Errors::SuspiciousCommands).
|
9
9
|
#
|
10
10
|
# Internally, validations will receive a Console1984::CommandValidator::ParsedCommand object. This
|
11
11
|
# exposes parsed constructs in addition to the raw strings so that validations can use those.
|
data/lib/console1984/errors.rb
CHANGED
@@ -10,11 +10,15 @@ module Console1984
|
|
10
10
|
|
11
11
|
# Attempt to execute a command that is not allowed. The system won't
|
12
12
|
# execute such commands and will flag them as sensitive.
|
13
|
-
class
|
13
|
+
class ForbiddenCommandAttempted < StandardError; end
|
14
14
|
|
15
15
|
# A suspicious command was executed. The command will be flagged but the system
|
16
16
|
# will let it run.
|
17
|
-
class
|
17
|
+
class SuspiciousCommandAttempted < StandardError; end
|
18
|
+
|
19
|
+
# A forbidden command was executed. The system will flag the command
|
20
|
+
# and exit.
|
21
|
+
class ForbiddenCommandExecuted < StandardError; end
|
18
22
|
|
19
23
|
# Attempt to incinerate a session ahead of time as determined by
|
20
24
|
# +config.console1984.incinerate_after+.
|
@@ -6,7 +6,7 @@ module Console1984::Ext::ActiveRecord::ProtectedAuditableTables
|
|
6
6
|
define_method method do |*args, **kwargs|
|
7
7
|
sql = args.first
|
8
8
|
if Console1984.command_executor.executing_user_command? && sql =~ auditable_tables_regexp
|
9
|
-
raise Console1984::Errors::
|
9
|
+
raise Console1984::Errors::ForbiddenCommandAttempted, "#{sql}"
|
10
10
|
else
|
11
11
|
super(*args, **kwargs)
|
12
12
|
end
|
@@ -7,9 +7,26 @@ module Console1984::Ext::Core::Module
|
|
7
7
|
|
8
8
|
def instance_eval(*)
|
9
9
|
if Console1984.command_executor.executing_user_command?
|
10
|
-
raise Console1984::Errors::
|
10
|
+
raise Console1984::Errors::ForbiddenCommandAttempted
|
11
11
|
else
|
12
12
|
super
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
def method_added(method)
|
17
|
+
if Console1984.command_executor.from_irb?(caller) && banned_for_reopening?
|
18
|
+
raise Console1984::Errors::ForbiddenCommandExecuted, "Trying to add method `#{method}` to #{self.name}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def banned_for_reopening?
|
24
|
+
classes_and_modules_banned_for_reopening.find do |banned_class_or_module_name|
|
25
|
+
"#{self.name}::".start_with?("#{banned_class_or_module_name}::")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def classes_and_modules_banned_for_reopening
|
30
|
+
@classes_and_modules_banned_for_reopening ||= Console1984.protections_config.validations[:forbidden_reopening]
|
31
|
+
end
|
15
32
|
end
|
@@ -25,7 +25,7 @@ module Console1984::Ext::Core::Object
|
|
25
25
|
# See the list +forbidden_reopening+ in +config/command_protections.yml+.
|
26
26
|
Console1984.command_executor.validate_command("class #{arguments.first}; end")
|
27
27
|
super
|
28
|
-
rescue Console1984::Errors::
|
28
|
+
rescue Console1984::Errors::ForbiddenCommandAttempted
|
29
29
|
raise
|
30
30
|
rescue StandardError
|
31
31
|
super
|
@@ -39,7 +39,7 @@ module Console1984::Freezeable
|
|
39
39
|
private
|
40
40
|
def prevent_sensitive_method(method_name)
|
41
41
|
define_method method_name do |*arguments|
|
42
|
-
raise Console1984::Errors::
|
42
|
+
raise Console1984::Errors::ForbiddenCommandAttempted, "You can't invoke #{method_name} on #{self}"
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Console1984::ProtectionsConfig
|
2
2
|
include Console1984::Freezeable
|
3
3
|
|
4
|
-
delegate :
|
4
|
+
delegate :validations, to: :instance
|
5
5
|
|
6
6
|
attr_reader :config
|
7
7
|
|
@@ -9,7 +9,7 @@ class Console1984::ProtectionsConfig
|
|
9
9
|
@config = config
|
10
10
|
end
|
11
11
|
|
12
|
-
%i[
|
12
|
+
%i[ validations forbidden_methods ].each do |method_name|
|
13
13
|
define_method method_name do
|
14
14
|
config[method_name].symbolize_keys
|
15
15
|
end
|
@@ -11,14 +11,17 @@ class Console1984::Refrigerator
|
|
11
11
|
end
|
12
12
|
|
13
13
|
private
|
14
|
-
EXTERNAL_MODULES_AND_CLASSES_TO_FREEZE = [Parser::CurrentRuby]
|
15
|
-
|
16
14
|
def freeze_internal_instances
|
17
15
|
Console1984.config.freeze unless Console1984.config.test_mode
|
18
16
|
end
|
19
17
|
|
20
18
|
def freeze_external_modules_and_classes
|
21
|
-
|
19
|
+
external_modules_and_classes_to_freeze.each { |klass| klass.include(Console1984::Freezeable) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def external_modules_and_classes_to_freeze
|
23
|
+
# Not using a constant because we want this to run lazily (console-dependant dependencies might not be loaded).
|
24
|
+
[Parser::CurrentRuby]
|
22
25
|
end
|
23
26
|
|
24
27
|
def eager_load_all_classes
|
@@ -26,7 +29,3 @@ class Console1984::Refrigerator
|
|
26
29
|
Console1984.class_loader.eager_load
|
27
30
|
end
|
28
31
|
end
|
29
|
-
|
30
|
-
class Parser::Ruby27
|
31
|
-
include Console1984::Freezeable
|
32
|
-
end
|
@@ -3,22 +3,20 @@ class Console1984::Shield::MethodInvocationShell
|
|
3
3
|
include Console1984::Freezeable
|
4
4
|
|
5
5
|
class << self
|
6
|
-
def install_for(
|
7
|
-
Array(
|
8
|
-
Array(config[:system]).each { |invocation| self.new(invocation, only_for_user_commands: false).prevent_methods_invocation }
|
6
|
+
def install_for(invocations)
|
7
|
+
Array(invocations).each { |invocation| self.new(invocation).prevent_methods_invocation }
|
9
8
|
end
|
10
9
|
end
|
11
10
|
|
12
11
|
attr_reader :class_name, :methods, :only_for_user_commands
|
13
12
|
|
14
|
-
def initialize(invocation
|
13
|
+
def initialize(invocation)
|
15
14
|
@class_name, methods = invocation.to_a
|
16
15
|
@methods = Array(methods)
|
17
|
-
@only_for_user_commands = only_for_user_commands
|
18
16
|
end
|
19
17
|
|
20
18
|
def prevent_methods_invocation
|
21
|
-
class_name.constantize.prepend build_protection_module
|
19
|
+
class_name.to_s.constantize.prepend build_protection_module
|
22
20
|
end
|
23
21
|
|
24
22
|
def build_protection_module
|
@@ -37,12 +35,8 @@ class Console1984::Shield::MethodInvocationShell
|
|
37
35
|
def protected_method_invocation_source_for(method)
|
38
36
|
<<~RUBY
|
39
37
|
def #{method}(*args)
|
40
|
-
if
|
41
|
-
|
42
|
-
break if !(line =~ /console1984\\/lib/ || line_from_irb)
|
43
|
-
line_from_irb
|
44
|
-
end
|
45
|
-
raise Console1984::Errors::ForbiddenCommand
|
38
|
+
if Console1984.command_executor.from_irb?(caller)
|
39
|
+
raise Console1984::Errors::ForbiddenCommandAttempted
|
46
40
|
else
|
47
41
|
super
|
48
42
|
end
|
@@ -30,12 +30,21 @@ class Console1984::Supervisor
|
|
30
30
|
stop_session
|
31
31
|
end
|
32
32
|
|
33
|
+
def exit_irb
|
34
|
+
stop
|
35
|
+
IRB.CurrentContext.exit
|
36
|
+
end
|
37
|
+
|
33
38
|
private
|
34
39
|
def require_dependencies
|
35
40
|
Kernel.silence_warnings do
|
36
41
|
require 'parser/current'
|
37
42
|
end
|
38
43
|
require 'colorized_string'
|
44
|
+
|
45
|
+
# Explicit lazy loading because it depends on +parser+, which we want to only load
|
46
|
+
# in console sessions.
|
47
|
+
require_relative "./command_validator/.command_parser"
|
39
48
|
end
|
40
49
|
|
41
50
|
def start_session
|
data/lib/console1984/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: console1984
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jorge Manrubia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -200,6 +200,7 @@ files:
|
|
200
200
|
- lib/console1984.rb
|
201
201
|
- lib/console1984/command_executor.rb
|
202
202
|
- lib/console1984/command_validator.rb
|
203
|
+
- lib/console1984/command_validator/.command_parser.rb
|
203
204
|
- lib/console1984/command_validator/forbidden_constant_reference_validation.rb
|
204
205
|
- lib/console1984/command_validator/forbidden_reopening_validation.rb
|
205
206
|
- lib/console1984/command_validator/parsed_command.rb
|