• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ninoseki / mihari / 7237373114

17 Dec 2023 08:31AM UTC coverage: 94.681% (+0.03%) from 94.655%
7237373114

push

github

web-flow
Merge pull request #872 from ninoseki/renew-search

refactor: renew search features including schemas

61 of 65 new or added lines in 15 files covered. (93.85%)

1 existing line in 1 file now uncovered.

3329 of 3516 relevant lines covered (94.68%)

85.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.87
/lib/mihari/web/endpoints/artifacts.rb
1
# frozen_string_literal: true
2

3
module Mihari
4✔
4
  module Web
4✔
5
    module Endpoints
4✔
6
      #
7
      # Artifact API endpoint
8
      #
9
      class Artifacts < Grape::API
4✔
10
        class ArtifactGetter < Service
4✔
11
          #
12
          # @param [Integer] id
13
          #
14
          # @return [Mihari::Models::Artifact]
15
          #
16
          def call(id)
4✔
17
            Mihari::Models::Artifact.includes(
16✔
18
              :autonomous_system,
19
              :geolocation,
20
              :whois_record,
21
              :dns_records,
22
              :reverse_dns_names
23
            ).find(id)
24
          end
25
        end
26

27
        class ArtifactEnricher < Service
4✔
28
          #
29
          # @param [String] id
30
          #
31
          def call(id)
4✔
32
            artifact = Mihari::Models::Artifact.includes(
4✔
33
              :autonomous_system,
34
              :geolocation,
35
              :whois_record,
36
              :dns_records,
37
              :reverse_dns_names,
38
              :cpes,
39
              :ports
40
            ).find(id)
41

42
            artifact.enrich_all
4✔
43
            artifact.save
4✔
44
          end
45
        end
46

47
        class ArtifactDestroyer < Service
4✔
48
          #
49
          # @param [Integer] id
50
          #
51
          def call(id)
4✔
52
            Mihari::Models::Artifact.find(id).destroy
8✔
53
          end
54
        end
55

56
        class ArtifactSearcher < Mihari::Service
4✔
57
          class ResultValue
4✔
58
            # @return [Array<Mihari::Models::Artifacts>]
59
            attr_reader :artifacts
4✔
60

61
            # @return [Integer]
62
            attr_reader :total
4✔
63

64
            # @return [Mihari::Structs::Filters::Artifact::SearchFilterWithPagination]
65
            attr_reader :filter
4✔
66

67
            #
68
            # @param [Array<Mihari::Models::Artifact>] artifacts
69
            # @param [Integer] total
70
            # @param [Mihari::Structs::Filters::Artifacts::SearchFilterWithPagination] filter
71
            #
72
            def initialize(artifacts:, total:, filter:)
4✔
73
              @artifacts = artifacts
×
74
              @total = total
×
75
              @filter = filter
×
76
            end
77
          end
78

79
          #
80
          # @param [Hash] params
81
          #
82
          # @return [ResultValue]
83
          #
84
          def call(params)
4✔
NEW
85
            normalized = params.to_h.to_snake_keys.symbolize_keys
×
NEW
86
            filter = Structs::Filters::Search.new(**normalized)
×
NEW
87
            artifacts = Mihari::Models::Artifact.search_by_filter(filter)
×
NEW
88
            total = Mihari::Models::Artifact.count_by_filter(filter)
×
UNCOV
89
            ResultValue.new(artifacts: artifacts, total: total, filter: filter)
×
90
          end
91
        end
92

93
        namespace :artifacts do
4✔
94
          desc "Search artifacts", {
8✔
95
            is_array: true,
96
            success: Entities::ArtifactsWithPagination,
97
            summary: "Search artifacts"
98
          }
99
          params do
8✔
100
            optional :q, type: String, default: ""
8✔
101
            optional :page, type: Integer, default: 1
8✔
102
            optional :limit, type: Integer, default: 10
8✔
103
          end
104
          get "/" do
8✔
105
            value = ArtifactSearcher.call(params.to_h)
×
106
            present(
×
107
              {
108
                artifacts: value.artifacts,
109
                total: value.total,
110
                current_page: value.filter[:page].to_i,
111
                page_size: value.filter[:limit].to_i
112
              },
113
              with: Entities::ArtifactsWithPagination
114
            )
115
          end
116

117
          desc "Get an artifact", {
8✔
118
            success: Entities::Artifact,
119
            failure: [{ code: 404, model: Entities::Message }],
120
            summary: "Get an artifact"
121
          }
122
          params do
8✔
123
            requires :id, type: Integer
8✔
124
          end
125
          get "/:id" do
8✔
126
            id = params[:id].to_i
16✔
127
            result = ArtifactGetter.result(id)
16✔
128
            return present(result.value!, with: Entities::Artifact) if result.success?
16✔
129

130
            case result.failure
4✔
131
            when ActiveRecord::RecordNotFound
132
              error!({ message: "ID:#{id} is not found" }, 404)
4✔
133
            end
134
            raise result.failure
×
135
          end
136

137
          desc "Enrich an artifact", {
8✔
138
            success: { code: 201, model: Entities::Message },
139
            failure: [{ code: 404, model: Entities::Message }],
140
            summary: "Enrich an artifact"
141
          }
142
          params do
8✔
143
            requires :id, type: Integer
8✔
144
          end
145
          get "/:id/enrich" do
8✔
146
            status 201
4✔
147

148
            id = params["id"].to_i
4✔
149
            result = ArtifactEnricher.result(id)
4✔
150
            return present({ message: "#{id} has been enriched" }, with: Entities::Message) if result.success?
4✔
151

152
            case result.failure
×
153
            when ActiveRecord::RecordNotFound
154
              error!({ message: "ID:#{id} is not found" }, 404)
×
155
            end
156
            raise result.failure
×
157
          end
158

159
          desc "Delete an artifact", {
8✔
160
            success: { code: 204, model: Entities::Message },
161
            failure: [{ code: 404, model: Entities::Message }],
162
            summary: "Delete an artifact"
163
          }
164
          params do
8✔
165
            requires :id, type: Integer
8✔
166
          end
167
          delete "/:id" do
8✔
168
            status 204
8✔
169

170
            id = params["id"].to_i
8✔
171
            result = ArtifactDestroyer.result(id)
8✔
172
            return present({ message: "" }, with: Entities::Message) if result.success?
8✔
173

174
            case result.failure
4✔
175
            when ActiveRecord::RecordNotFound
176
              error!({ message: "ID:#{id} is not found" }, 404)
4✔
177
            end
178
            raise result.failure
×
179
          end
180
        end
181
      end
182
    end
183
  end
184
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc