Skip to content

Commit

Permalink
refactor: split validation and formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
ninoseki committed Jul 14, 2024
1 parent e3d6910 commit ba029a3
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 11 deletions.
5 changes: 3 additions & 2 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,14 @@ See [Database](./emitters/database.md) for detailed database configuration.
$ mihari rule
Commands:
mihari rule delete ID # Delete a rule
mihari rule format PATH # format a rule
mihari rule get ID # Get a rule
mihari rule help [COMMAND] # Describe subcommands or one specific subcommand
mihari rule init PATH # Initialize a new rule file
mihari rule init PATH # Initialize a new rule
mihari rule list QUERY # List/search rules
mihari rule list-transform QUERY -t, --template=TEMPLATE # List/search rules with transformation
mihari rule search PATH_OR_ID # Search by a rule
mihari rule validate PATH # Validate a rule file
mihari rule validate PATH # Validate rule(s)
```

### `mihari search`
Expand Down
31 changes: 27 additions & 4 deletions lib/mihari/commands/rule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,37 @@ def _search(q, page: 1, limit: 10)
end
end

desc "validate PATH", "Validate a rule"
desc "validate PATH", "Validate rule(s)"
#
# Validate format of a rule
# Validate rule(s)
#
# @param [Array<String>] paths
#
def validate(*paths)
# @type [Array<Mihari::ValidationError>]
errors = paths.flat_map { |path| Dir.glob(path) }.map do |path|
Dry::Monads::Try[ValidationError] { Mihari::Rule.from_file(path) }
end.filter_map do |result|
result.exception if result.error?
end
return if errors.empty?

errors.each do |error|
data = Entities::ErrorMessage.represent(message: error.message, detail: error.detail)
warn JSON.pretty_generate(data.as_json)
end

exit 1
end

desc "format PATH", "format a rule"
#
# Format a rule file
#
# @param [String] path
#
def validate(path)
rule = Dry::Monads::Try[ValidationError] { Mihari::Rule.from_yaml File.read(path) }.value!
def format(path)
rule = Dry::Monads::Try[ValidationError] { Mihari::Rule.from_file(path) }.value!
puts rule.data.to_yaml
end

Expand Down
28 changes: 23 additions & 5 deletions lib/mihari/rule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ class Rule < Service
include Concerns::FalsePositiveNormalizable
include Concerns::FalsePositiveValidatable

# @return [String, nil]
attr_reader :path_or_id

# @return [Hash]
attr_reader :data

Expand All @@ -19,9 +22,11 @@ class Rule < Service
#
# @param [Hash] data
#
def initialize(**data)
# @param [Object] path_or_id
def initialize(path_or_id: nil, **data)
super()

@path_or_id = path_or_id
@data = data.deep_symbolize_keys
@errors = nil
@base_time = Time.now.utc
Expand Down Expand Up @@ -251,16 +256,29 @@ def update_or_create
end

class << self
#
# Load rule from YAML file
#
# @param [String] path
#
# @return [Mihari::Rule]
#
def from_file(path)
yaml = File.read(path)
from_yaml(yaml, path: path)
end

#
# Load rule from YAML string
#
# @param [String] yaml
# @param [String, nil] path
#
# @return [Mihari::Rule]
#
def from_yaml(yaml)
def from_yaml(yaml, path: nil)
data = YAML.safe_load(ERB.new(yaml).result, permitted_classes: [Date, Symbol])
new(**data)
new(path_or_id: path, **data)
end

#
Expand All @@ -269,7 +287,7 @@ def from_yaml(yaml)
# @return [Mihari::Rule]
#
def from_model(model)
new(**model.data)
new(path_or_id: model.id, **model.data)
end
end

Expand Down Expand Up @@ -409,7 +427,7 @@ def validate!
@data = result.to_h
@errors = result.errors

raise ValidationError.new("Validation failed", errors) if errors?
raise ValidationError.new("#{path_or_id}: validation failed", errors) if errors?
end
end
end

0 comments on commit ba029a3

Please sign in to comment.