mihari 5.2.4 → 5.3.0
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/.gitignore +4 -1
- data/README.md +0 -10
- data/Rakefile +7 -1
- data/build_frontend.sh +1 -1
- data/frontend/.eslintrc.cjs +22 -0
- data/frontend/.gitignore +18 -12
- data/frontend/.prettierrc.json +8 -0
- data/frontend/env.d.ts +5 -0
- data/frontend/package-lock.json +5095 -9661
- data/frontend/package.json +34 -24
- data/frontend/src/App.vue +5 -5
- data/frontend/src/api-helper.ts +38 -40
- data/frontend/src/api.ts +40 -40
- data/frontend/src/components/ErrorMessage.vue +8 -8
- data/frontend/src/components/Loading.vue +3 -3
- data/frontend/src/components/Navbar.vue +10 -27
- data/frontend/src/components/Pagination.vue +35 -42
- data/frontend/src/components/alert/Alert.vue +21 -26
- data/frontend/src/components/alert/Alerts.vue +23 -25
- data/frontend/src/components/alert/AlertsWithPagination.vue +34 -34
- data/frontend/src/components/alert/AlertsWrapper.vue +42 -49
- data/frontend/src/components/alert/Form.vue +39 -40
- data/frontend/src/components/artifact/AS.vue +7 -7
- data/frontend/src/components/artifact/Artifact.vue +66 -83
- data/frontend/src/components/artifact/ArtifactTag.vue +21 -27
- data/frontend/src/components/artifact/ArtifactTags.vue +8 -8
- data/frontend/src/components/artifact/ArtifactWrapper.vue +22 -25
- data/frontend/src/components/artifact/CPEs.vue +6 -6
- data/frontend/src/components/artifact/DnsRecords.vue +9 -9
- data/frontend/src/components/artifact/Ports.vue +6 -6
- data/frontend/src/components/artifact/ReverseDnsNames.vue +7 -7
- data/frontend/src/components/artifact/Tags.vue +6 -6
- data/frontend/src/components/artifact/WhoisRecord.vue +7 -9
- data/frontend/src/components/config/Configs.vue +7 -10
- data/frontend/src/components/config/ConfigsWrapper.vue +14 -20
- data/frontend/src/components/link/Link.vue +7 -7
- data/frontend/src/components/link/Links.vue +16 -21
- data/frontend/src/components/rule/EditRule.vue +22 -22
- data/frontend/src/components/rule/EditRuleWrapper.vue +22 -28
- data/frontend/src/components/rule/Form.vue +28 -28
- data/frontend/src/components/rule/InputForm.vue +31 -25
- data/frontend/src/components/rule/NewRule.vue +18 -18
- data/frontend/src/components/rule/Rule.vue +25 -27
- data/frontend/src/components/rule/RuleWrapper.vue +24 -31
- data/frontend/src/components/rule/Rules.vue +26 -30
- data/frontend/src/components/rule/RulesWrapper.vue +39 -42
- data/frontend/src/components/rule/YAML.vue +19 -22
- data/frontend/src/components/tag/Tag.vue +24 -32
- data/frontend/src/components/tag/Tags.vue +11 -11
- data/frontend/src/countries.ts +23 -23
- data/frontend/src/index.ts +9 -12
- data/frontend/src/links/anyrun.ts +10 -10
- data/frontend/src/links/base.ts +3 -3
- data/frontend/src/links/censys.ts +10 -10
- data/frontend/src/links/crtsh.ts +10 -10
- data/frontend/src/links/dnslytics.ts +18 -18
- data/frontend/src/links/greynoise.ts +10 -10
- data/frontend/src/links/index.ts +15 -15
- data/frontend/src/links/intezer.ts +10 -10
- data/frontend/src/links/otx.ts +14 -14
- data/frontend/src/links/securitytrails.ts +15 -15
- data/frontend/src/links/shodan.ts +10 -10
- data/frontend/src/links/urlscan.ts +19 -19
- data/frontend/src/links/virustotal.ts +27 -27
- data/frontend/src/main.ts +8 -8
- data/frontend/src/router/index.ts +20 -20
- data/frontend/src/rule.ts +6 -6
- data/frontend/src/shims-vue.d.ts +2 -2
- data/frontend/src/types.ts +91 -91
- data/frontend/src/utils.ts +23 -29
- data/frontend/src/views/Alerts.vue +7 -7
- data/frontend/src/views/Artifact.vue +17 -17
- data/frontend/src/views/Configs.vue +7 -7
- data/frontend/src/views/EditRule.vue +17 -17
- data/frontend/src/views/NewRule.vue +10 -10
- data/frontend/src/views/Rule.vue +17 -17
- data/frontend/src/views/Rules.vue +7 -7
- data/frontend/tests/utils.spec.ts +9 -0
- data/frontend/tsconfig.app.json +21 -0
- data/frontend/tsconfig.json +10 -36
- data/frontend/tsconfig.node.json +13 -0
- data/frontend/tsconfig.vitest.json +12 -0
- data/frontend/vite.config.ts +24 -0
- data/frontend/vitest.config.ts +21 -0
- data/lefthook.yml +4 -2
- data/lib/mihari/analyzers/base.rb +48 -14
- data/lib/mihari/analyzers/binaryedge.rb +10 -15
- data/lib/mihari/analyzers/censys.rb +12 -15
- data/lib/mihari/analyzers/circl.rb +10 -10
- data/lib/mihari/analyzers/crtsh.rb +10 -6
- data/lib/mihari/analyzers/dnstwister.rb +6 -8
- data/lib/mihari/analyzers/feed.rb +21 -10
- data/lib/mihari/analyzers/greynoise.rb +10 -20
- data/lib/mihari/analyzers/onyphe.rb +9 -14
- data/lib/mihari/analyzers/otx.rb +8 -9
- data/lib/mihari/analyzers/passivetotal.rb +10 -10
- data/lib/mihari/analyzers/pulsedive.rb +21 -31
- data/lib/mihari/analyzers/securitytrails.rb +8 -6
- data/lib/mihari/analyzers/shodan.rb +8 -13
- data/lib/mihari/analyzers/urlscan.rb +15 -20
- data/lib/mihari/analyzers/virustotal.rb +16 -26
- data/lib/mihari/analyzers/virustotal_intelligence.rb +11 -17
- data/lib/mihari/analyzers/zoomeye.rb +12 -17
- data/lib/mihari/config.rb +133 -0
- data/lib/mihari/constants.rb +3 -0
- data/lib/mihari/emitters/slack.rb +13 -3
- data/lib/mihari/errors.rb +1 -1
- data/lib/mihari/http.rb +2 -3
- data/lib/mihari/schemas/analyzer.rb +2 -0
- data/lib/mihari/type_checker.rb +6 -6
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/endpoints/configs.rb +5 -1
- data/lib/mihari/web/public/assets/{index-eed1bcd8.css → index-2ba8f0a6.css} +1 -1
- data/lib/mihari/web/public/assets/{index-ac4e5ffa.js → index-71285b15.js} +16 -16
- data/lib/mihari/web/public/index.html +2 -2
- data/lib/mihari/web/public/redoc-static.html +388 -2193
- data/lib/mihari.rb +9 -59
- data/mihari.gemspec +8 -8
- metadata +24 -62
- data/frontend/.browserslistrc +0 -3
- data/frontend/.eslintrc.js +0 -33
- data/frontend/babel.config.js +0 -3
- data/frontend/jest.config.js +0 -9
- data/frontend/tests/unit/utils.spec.ts +0 -7
- data/frontend/vite.config.js +0 -24
data/frontend/package.json
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "mihari
|
|
2
|
+
"name": "mihari",
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
|
-
"
|
|
7
|
-
"build": "npx
|
|
8
|
-
"
|
|
9
|
-
"
|
|
6
|
+
"build-only": "vite build",
|
|
7
|
+
"build-redoc": "npx @redocly/cli build-docs src/swagger.yaml -o public/redoc-static.html",
|
|
8
|
+
"build": "run-p type-check build-only build-redoc",
|
|
9
|
+
"dev": "vite",
|
|
10
|
+
"format": "prettier --write src/",
|
|
11
|
+
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
|
12
|
+
"preview": "vite preview",
|
|
13
|
+
"test:unit": "vitest",
|
|
14
|
+
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false"
|
|
10
15
|
},
|
|
11
16
|
"dependencies": {
|
|
12
17
|
"@fortawesome/fontawesome-free": "^6.4.0",
|
|
13
|
-
"@vueuse/core": "^10.2.
|
|
14
|
-
"@vueuse/router": "^10.2.
|
|
18
|
+
"@vueuse/core": "^10.2.1",
|
|
19
|
+
"@vueuse/router": "^10.2.1",
|
|
15
20
|
"axios": "^1.4.0",
|
|
16
21
|
"bulma": "^0.9.4",
|
|
17
22
|
"bulma-helpers": "^0.4.3",
|
|
18
|
-
"dayjs": "^1.11.
|
|
23
|
+
"dayjs": "^1.11.9",
|
|
19
24
|
"js-sha256": "^0.9.0",
|
|
20
25
|
"truncate": "^3.0.0",
|
|
21
26
|
"ts-dedent": "^2.2.0",
|
|
@@ -25,30 +30,35 @@
|
|
|
25
30
|
"vue-concurrency": "4.0.1",
|
|
26
31
|
"vue-json-pretty": "^2.2.4",
|
|
27
32
|
"vue-prism-editor": "^2.0.0-alpha.2",
|
|
28
|
-
"vue-router": "^4.2.
|
|
33
|
+
"vue-router": "^4.2.4"
|
|
29
34
|
},
|
|
30
35
|
"devDependencies": {
|
|
31
|
-
"@
|
|
36
|
+
"@redocly/cli": "^1.0.0-beta.131",
|
|
37
|
+
"@rushstack/eslint-patch": "^1.3.2",
|
|
38
|
+
"@tsconfig/node20": "^1.0.2",
|
|
39
|
+
"@types/jsdom": "^21.1.1",
|
|
40
|
+
"@types/node": "^20.4.2",
|
|
32
41
|
"@types/prismjs": "^1.26.0",
|
|
33
42
|
"@types/url-parse": "^1.4.8",
|
|
34
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
35
|
-
"@typescript-eslint/parser": "^
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
44
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
36
45
|
"@vitejs/plugin-vue": "^4.2.3",
|
|
46
|
+
"@vue/eslint-config-prettier": "^7.1.0",
|
|
37
47
|
"@vue/eslint-config-typescript": "^11.0.3",
|
|
38
|
-
"@vue/test-utils": "2.
|
|
39
|
-
"@vue/
|
|
40
|
-
"eslint": "^8.
|
|
48
|
+
"@vue/test-utils": "2.4.0",
|
|
49
|
+
"@vue/tsconfig": "^0.4.0",
|
|
50
|
+
"eslint": "^8.45.0",
|
|
41
51
|
"eslint-config-prettier": "^8.8.0",
|
|
42
|
-
"eslint-plugin-prettier": "^
|
|
52
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
43
53
|
"eslint-plugin-simple-import-sort": "^10.0.0",
|
|
44
|
-
"eslint-plugin-vue": "^9.
|
|
45
|
-
"handlebars": "^4.7.7",
|
|
54
|
+
"eslint-plugin-vue": "^9.15.1",
|
|
46
55
|
"husky": "^8.0.3",
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
56
|
+
"jsdom": "^22.1.0",
|
|
57
|
+
"npm-run-all": "^4.1.5",
|
|
58
|
+
"prettier": "^3.0.0",
|
|
59
|
+
"typescript": "~5.1.6",
|
|
60
|
+
"vite": "^4.4.4",
|
|
61
|
+
"vitest": "^0.33.0",
|
|
62
|
+
"vue-tsc": "^1.8.5"
|
|
53
63
|
}
|
|
54
64
|
}
|
data/frontend/src/App.vue
CHANGED
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
10
|
<script lang="ts">
|
|
11
|
-
import { defineComponent } from "vue"
|
|
11
|
+
import { defineComponent } from "vue"
|
|
12
12
|
|
|
13
|
-
import Navbar from "@/components/Navbar.vue"
|
|
13
|
+
import Navbar from "@/components/Navbar.vue"
|
|
14
14
|
|
|
15
15
|
export default defineComponent({
|
|
16
16
|
name: "App",
|
|
17
17
|
components: {
|
|
18
|
-
Navbar
|
|
19
|
-
}
|
|
20
|
-
})
|
|
18
|
+
Navbar
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
21
|
</script>
|
|
22
22
|
|
|
23
23
|
<style>
|
data/frontend/src/api-helper.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Task, useAsyncTask } from "vue-concurrency"
|
|
1
|
+
import { type Task, useAsyncTask } from "vue-concurrency"
|
|
2
2
|
|
|
3
|
-
import { API } from "@/api"
|
|
4
|
-
import {
|
|
3
|
+
import { API } from "@/api"
|
|
4
|
+
import type {
|
|
5
5
|
Alerts,
|
|
6
6
|
AlertSearchParams,
|
|
7
7
|
ArtifactWithTags,
|
|
@@ -11,103 +11,101 @@ import {
|
|
|
11
11
|
Rule,
|
|
12
12
|
Rules,
|
|
13
13
|
RuleSearchParams,
|
|
14
|
-
UpdateRule
|
|
15
|
-
} from "@/types"
|
|
14
|
+
UpdateRule
|
|
15
|
+
} from "@/types"
|
|
16
16
|
|
|
17
17
|
export function generateGetAlertsTask(): Task<Alerts, [AlertSearchParams]> {
|
|
18
18
|
return useAsyncTask<Alerts, [AlertSearchParams]>(async (_signal, params) => {
|
|
19
|
-
return await API.getAlerts(params)
|
|
20
|
-
})
|
|
19
|
+
return await API.getAlerts(params)
|
|
20
|
+
})
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function generateDeleteAlertTask(): Task<void, [string]> {
|
|
24
24
|
return useAsyncTask<void, [string]>(async (_signal, id) => {
|
|
25
|
-
return await API.deleteAlert(id)
|
|
26
|
-
})
|
|
25
|
+
return await API.deleteAlert(id)
|
|
26
|
+
})
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export function generateGetTagsTask(): Task<string[], []> {
|
|
30
30
|
return useAsyncTask<string[], []>(async () => {
|
|
31
|
-
return await API.getTags()
|
|
32
|
-
})
|
|
31
|
+
return await API.getTags()
|
|
32
|
+
})
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export function generateDeleteTagTask(): Task<void, [string]> {
|
|
36
36
|
return useAsyncTask<void, [string]>(async (_signal, tag) => {
|
|
37
|
-
return await API.deleteTag(tag)
|
|
38
|
-
})
|
|
37
|
+
return await API.deleteTag(tag)
|
|
38
|
+
})
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export function generateGetRuleSetTask(): Task<string[], []> {
|
|
42
42
|
return useAsyncTask<string[], []>(async () => {
|
|
43
|
-
return await API.getRuleSet()
|
|
44
|
-
})
|
|
43
|
+
return await API.getRuleSet()
|
|
44
|
+
})
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export function generateGetArtifactTask(): Task<ArtifactWithTags, [string]> {
|
|
48
48
|
return useAsyncTask<ArtifactWithTags, [string]>(async (_signal, id) => {
|
|
49
|
-
return await API.getArtifact(id)
|
|
50
|
-
})
|
|
49
|
+
return await API.getArtifact(id)
|
|
50
|
+
})
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export function generateDeleteArtifactTask(): Task<void, [string]> {
|
|
54
54
|
return useAsyncTask<void, [string]>(async (_signal, id) => {
|
|
55
|
-
return await API.deleteArtifact(id)
|
|
56
|
-
})
|
|
55
|
+
return await API.deleteArtifact(id)
|
|
56
|
+
})
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
export function generateEnrichArtifactTask(): Task<void, [string]> {
|
|
60
60
|
return useAsyncTask<void, [string]>(async (_signal, id) => {
|
|
61
|
-
return await API.enrichArtifact(id)
|
|
62
|
-
})
|
|
61
|
+
return await API.enrichArtifact(id)
|
|
62
|
+
})
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
export function generateGetConfigsTask(): Task<Config[], []> {
|
|
66
66
|
return useAsyncTask<Config[], []>(async () => {
|
|
67
|
-
return await API.getConfigs()
|
|
68
|
-
})
|
|
67
|
+
return await API.getConfigs()
|
|
68
|
+
})
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
export function generateGetIPTask(): Task<IPInfo, [string]> {
|
|
72
72
|
return useAsyncTask<IPInfo, [string]>(async (_signal, ipAddress: string) => {
|
|
73
|
-
return await API.getIPInfo(ipAddress)
|
|
74
|
-
})
|
|
73
|
+
return await API.getIPInfo(ipAddress)
|
|
74
|
+
})
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
export function generateGetRulesTask(): Task<Rules, [RuleSearchParams]> {
|
|
78
|
-
return useAsyncTask<Rules, [RuleSearchParams]>(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
);
|
|
78
|
+
return useAsyncTask<Rules, [RuleSearchParams]>(async (_signal, params: RuleSearchParams) => {
|
|
79
|
+
return await API.getRules(params)
|
|
80
|
+
})
|
|
83
81
|
}
|
|
84
82
|
|
|
85
83
|
export function generateGetRuleTask(): Task<Rule, [string]> {
|
|
86
84
|
return useAsyncTask<Rule, [string]>(async (_signal, id: string) => {
|
|
87
|
-
return await API.getRule(id)
|
|
88
|
-
})
|
|
85
|
+
return await API.getRule(id)
|
|
86
|
+
})
|
|
89
87
|
}
|
|
90
88
|
|
|
91
89
|
export function generateDeleteRuleTask(): Task<void, [string]> {
|
|
92
90
|
return useAsyncTask<void, [string]>(async (_signal, id: string) => {
|
|
93
|
-
return await API.deleteRule(id)
|
|
94
|
-
})
|
|
91
|
+
return await API.deleteRule(id)
|
|
92
|
+
})
|
|
95
93
|
}
|
|
96
94
|
|
|
97
95
|
export function generateRunRuleTask(): Task<void, [string]> {
|
|
98
96
|
return useAsyncTask<void, [string]>(async (_signal, id) => {
|
|
99
|
-
return await API.runRule(id)
|
|
100
|
-
})
|
|
97
|
+
return await API.runRule(id)
|
|
98
|
+
})
|
|
101
99
|
}
|
|
102
100
|
|
|
103
101
|
export function generateCreateRuleTask(): Task<Rule, [CreateRule]> {
|
|
104
102
|
return useAsyncTask<Rule, [CreateRule]>(async (_signal, payload) => {
|
|
105
|
-
return await API.createRule(payload)
|
|
106
|
-
})
|
|
103
|
+
return await API.createRule(payload)
|
|
104
|
+
})
|
|
107
105
|
}
|
|
108
106
|
|
|
109
107
|
export function generateUpdateRuleTask(): Task<Rule, [UpdateRule]> {
|
|
110
108
|
return useAsyncTask<Rule, [UpdateRule]>(async (_signal, payload) => {
|
|
111
|
-
return await API.updateRule(payload)
|
|
112
|
-
})
|
|
109
|
+
return await API.updateRule(payload)
|
|
110
|
+
})
|
|
113
111
|
}
|
data/frontend/src/api.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import axios from "axios"
|
|
1
|
+
import axios from "axios"
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import type {
|
|
4
4
|
Alerts,
|
|
5
5
|
AlertSearchParams,
|
|
6
6
|
ArtifactWithTags,
|
|
@@ -12,94 +12,94 @@ import {
|
|
|
12
12
|
RuleSearchParams,
|
|
13
13
|
RuleSet,
|
|
14
14
|
Tags,
|
|
15
|
-
UpdateRule
|
|
16
|
-
} from "@/types"
|
|
15
|
+
UpdateRule
|
|
16
|
+
} from "@/types"
|
|
17
17
|
|
|
18
18
|
const client = axios.create({
|
|
19
19
|
headers: {
|
|
20
|
-
Accept: "application/json"
|
|
21
|
-
}
|
|
22
|
-
})
|
|
20
|
+
Accept: "application/json"
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
23
|
|
|
24
24
|
export const API = {
|
|
25
25
|
async getConfigs(): Promise<Config[]> {
|
|
26
|
-
const res = await client.get<Config[]>("/api/configs")
|
|
27
|
-
return res.data
|
|
26
|
+
const res = await client.get<Config[]>("/api/configs")
|
|
27
|
+
return res.data
|
|
28
28
|
},
|
|
29
29
|
|
|
30
30
|
async getAlerts(params: AlertSearchParams): Promise<Alerts> {
|
|
31
|
-
params.page = params.page || 1
|
|
31
|
+
params.page = params.page || 1
|
|
32
32
|
const res = await client.get<Alerts>("/api/alerts", {
|
|
33
|
-
params: params
|
|
34
|
-
})
|
|
35
|
-
return res.data
|
|
33
|
+
params: params
|
|
34
|
+
})
|
|
35
|
+
return res.data
|
|
36
36
|
},
|
|
37
37
|
|
|
38
38
|
async getTags(): Promise<string[]> {
|
|
39
|
-
const res = await client.get<Tags>("/api/tags")
|
|
40
|
-
return res.data.tags
|
|
39
|
+
const res = await client.get<Tags>("/api/tags")
|
|
40
|
+
return res.data.tags
|
|
41
41
|
},
|
|
42
42
|
|
|
43
43
|
async getRuleSet(): Promise<string[]> {
|
|
44
|
-
const res = await client.get<RuleSet>("/api/rules/ids")
|
|
45
|
-
return res.data.ruleIds
|
|
44
|
+
const res = await client.get<RuleSet>("/api/rules/ids")
|
|
45
|
+
return res.data.ruleIds
|
|
46
46
|
},
|
|
47
47
|
|
|
48
48
|
async deleteAlert(id: string): Promise<void> {
|
|
49
|
-
await client.delete(`/api/alerts/${id}`)
|
|
49
|
+
await client.delete(`/api/alerts/${id}`)
|
|
50
50
|
},
|
|
51
51
|
|
|
52
52
|
async getArtifact(id: string): Promise<ArtifactWithTags> {
|
|
53
|
-
const res = await client.get(`/api/artifacts/${id}`)
|
|
54
|
-
return res.data
|
|
53
|
+
const res = await client.get(`/api/artifacts/${id}`)
|
|
54
|
+
return res.data
|
|
55
55
|
},
|
|
56
56
|
|
|
57
57
|
async enrichArtifact(id: string): Promise<void> {
|
|
58
|
-
await client.get(`/api/artifacts/${id}/enrich`)
|
|
59
|
-
return
|
|
58
|
+
await client.get(`/api/artifacts/${id}/enrich`)
|
|
59
|
+
return
|
|
60
60
|
},
|
|
61
61
|
|
|
62
62
|
async deleteArtifact(id: string): Promise<void> {
|
|
63
|
-
await client.delete(`/api/artifacts/${id}`)
|
|
63
|
+
await client.delete(`/api/artifacts/${id}`)
|
|
64
64
|
},
|
|
65
65
|
|
|
66
66
|
async getRules(params: RuleSearchParams): Promise<Rules> {
|
|
67
|
-
params.page = params.page || 1
|
|
67
|
+
params.page = params.page || 1
|
|
68
68
|
const res = await client.get<Rules>("/api/rules", {
|
|
69
|
-
params: params
|
|
70
|
-
})
|
|
71
|
-
return res.data
|
|
69
|
+
params: params
|
|
70
|
+
})
|
|
71
|
+
return res.data
|
|
72
72
|
},
|
|
73
73
|
|
|
74
74
|
async getRule(id: string): Promise<Rule> {
|
|
75
|
-
const res = await client.get<Rule>(`/api/rules/${id}`)
|
|
76
|
-
return res.data
|
|
75
|
+
const res = await client.get<Rule>(`/api/rules/${id}`)
|
|
76
|
+
return res.data
|
|
77
77
|
},
|
|
78
78
|
|
|
79
79
|
async runRule(id: string): Promise<void> {
|
|
80
|
-
await client.get<void>(`/api/rules/${id}/run`)
|
|
80
|
+
await client.get<void>(`/api/rules/${id}/run`)
|
|
81
81
|
},
|
|
82
82
|
|
|
83
83
|
async createRule(payload: CreateRule): Promise<Rule> {
|
|
84
|
-
const res = await client.post<Rule>("/api/rules/", payload)
|
|
85
|
-
return res.data
|
|
84
|
+
const res = await client.post<Rule>("/api/rules/", payload)
|
|
85
|
+
return res.data
|
|
86
86
|
},
|
|
87
87
|
|
|
88
88
|
async updateRule(payload: UpdateRule): Promise<Rule> {
|
|
89
|
-
const res = await client.put<Rule>("/api/rules/", payload)
|
|
90
|
-
return res.data
|
|
89
|
+
const res = await client.put<Rule>("/api/rules/", payload)
|
|
90
|
+
return res.data
|
|
91
91
|
},
|
|
92
92
|
|
|
93
93
|
async deleteRule(id: string): Promise<void> {
|
|
94
|
-
await client.delete<void>(`/api/rules/${id}`)
|
|
94
|
+
await client.delete<void>(`/api/rules/${id}`)
|
|
95
95
|
},
|
|
96
96
|
|
|
97
97
|
async deleteTag(name: string): Promise<void> {
|
|
98
|
-
await client.delete(`/api/tags/${name}`)
|
|
98
|
+
await client.delete(`/api/tags/${name}`)
|
|
99
99
|
},
|
|
100
100
|
|
|
101
101
|
async getIPInfo(ipAddress: string): Promise<IPInfo> {
|
|
102
|
-
const res = await client.get<IPInfo>(`/api/ip_addresses/${ipAddress}`)
|
|
103
|
-
return res.data
|
|
104
|
-
}
|
|
105
|
-
}
|
|
102
|
+
const res = await client.get<IPInfo>(`/api/ip_addresses/${ipAddress}`)
|
|
103
|
+
return res.data
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -12,21 +12,21 @@
|
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
14
|
<script lang="ts">
|
|
15
|
-
import "vue-json-pretty/lib/styles.css"
|
|
15
|
+
import "vue-json-pretty/lib/styles.css"
|
|
16
16
|
|
|
17
|
-
import { defineComponent } from "vue"
|
|
18
|
-
import VueJsonPretty from "vue-json-pretty"
|
|
17
|
+
import { defineComponent } from "vue"
|
|
18
|
+
import VueJsonPretty from "vue-json-pretty"
|
|
19
19
|
|
|
20
20
|
export default defineComponent({
|
|
21
21
|
name: "ErrorItem",
|
|
22
22
|
props: {
|
|
23
23
|
error: {
|
|
24
24
|
type: Object,
|
|
25
|
-
required: true
|
|
26
|
-
}
|
|
25
|
+
required: true
|
|
26
|
+
}
|
|
27
27
|
},
|
|
28
28
|
components: {
|
|
29
|
-
VueJsonPretty
|
|
30
|
-
}
|
|
31
|
-
})
|
|
29
|
+
VueJsonPretty
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
32
|
</script>
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<nav
|
|
3
|
-
role="navigation"
|
|
4
|
-
aria-label="main navigation"
|
|
5
|
-
class="navbar is-fixed-top"
|
|
6
|
-
>
|
|
2
|
+
<nav role="navigation" aria-label="main navigation" class="navbar is-fixed-top">
|
|
7
3
|
<div class="navbar-brand">
|
|
8
4
|
<a class="navbar-item"><h1 class="title">Mihari</h1></a
|
|
9
5
|
><a role="button" aria-label="menu" class="navbar-burger burger"
|
|
@@ -14,28 +10,15 @@
|
|
|
14
10
|
<div class="navbar-menu">
|
|
15
11
|
<div class="navbar-start"></div>
|
|
16
12
|
<div class="navbar-end">
|
|
17
|
-
<router-link class="navbar-item" :to="{ name: 'Alerts' }"
|
|
18
|
-
|
|
19
|
-
>
|
|
20
|
-
<router-link class="navbar-item" :to="{ name: '
|
|
21
|
-
>New rule</router-link
|
|
22
|
-
>
|
|
23
|
-
<router-link class="navbar-item" :to="{ name: 'Rules' }"
|
|
24
|
-
>Rules</router-link
|
|
25
|
-
>
|
|
26
|
-
<router-link class="navbar-item" :to="{ name: 'Configs' }"
|
|
27
|
-
>Configs</router-link
|
|
28
|
-
>
|
|
13
|
+
<router-link class="navbar-item" :to="{ name: 'Alerts' }">Alerts</router-link>
|
|
14
|
+
<router-link class="navbar-item" :to="{ name: 'NewRule' }">New rule</router-link>
|
|
15
|
+
<router-link class="navbar-item" :to="{ name: 'Rules' }">Rules</router-link>
|
|
16
|
+
<router-link class="navbar-item" :to="{ name: 'Configs' }">Configs</router-link>
|
|
29
17
|
<a class="navbar-item"
|
|
30
|
-
><a href="/redoc-static.html" target="_blank" class="navbar-item"
|
|
31
|
-
>API</a
|
|
32
|
-
></a
|
|
18
|
+
><a href="/redoc-static.html" target="_blank" class="navbar-item">API</a></a
|
|
33
19
|
>
|
|
34
20
|
<a class="navbar-item"
|
|
35
|
-
><a
|
|
36
|
-
href="https://github.com/ninoseki/mihari"
|
|
37
|
-
target="_blank"
|
|
38
|
-
class="navbar-item"
|
|
21
|
+
><a href="https://github.com/ninoseki/mihari" target="_blank" class="navbar-item"
|
|
39
22
|
>GitHub</a
|
|
40
23
|
></a
|
|
41
24
|
>
|
|
@@ -45,11 +28,11 @@
|
|
|
45
28
|
</template>
|
|
46
29
|
|
|
47
30
|
<script lang="ts">
|
|
48
|
-
import { defineComponent } from "vue"
|
|
31
|
+
import { defineComponent } from "vue"
|
|
49
32
|
|
|
50
33
|
export default defineComponent({
|
|
51
|
-
name: "NavbarItem"
|
|
52
|
-
})
|
|
34
|
+
name: "NavbarItem"
|
|
35
|
+
})
|
|
53
36
|
</script>
|
|
54
37
|
|
|
55
38
|
<style scoped>
|
|
@@ -21,10 +21,7 @@
|
|
|
21
21
|
>
|
|
22
22
|
</li>
|
|
23
23
|
<li>
|
|
24
|
-
<a
|
|
25
|
-
class="pagination-link mt-2 is-current"
|
|
26
|
-
@click="updatePage(currentPage)"
|
|
27
|
-
>
|
|
24
|
+
<a class="pagination-link mt-2 is-current" @click="updatePage(currentPage)">
|
|
28
25
|
{{ currentPage }}</a
|
|
29
26
|
>
|
|
30
27
|
</li>
|
|
@@ -37,80 +34,76 @@
|
|
|
37
34
|
<span class="pagination-ellipsis">…</span>
|
|
38
35
|
</li>
|
|
39
36
|
<li v-if="hasNextPage && isNextPageNotLast">
|
|
40
|
-
<a class="pagination-link mt-2" @click="updatePage(totalPageCount)">{{
|
|
41
|
-
totalPageCount
|
|
42
|
-
}}</a>
|
|
37
|
+
<a class="pagination-link mt-2" @click="updatePage(totalPageCount)">{{ totalPageCount }}</a>
|
|
43
38
|
</li>
|
|
44
39
|
</ul>
|
|
45
40
|
</nav>
|
|
46
41
|
</template>
|
|
47
42
|
|
|
48
43
|
<script lang="ts">
|
|
49
|
-
import { useRouteQuery } from "@vueuse/router"
|
|
50
|
-
import { computed, defineComponent, onMounted, Ref } from "vue"
|
|
51
|
-
import { useRoute, useRouter } from "vue-router"
|
|
44
|
+
import { useRouteQuery } from "@vueuse/router"
|
|
45
|
+
import { computed, defineComponent, onMounted, type Ref } from "vue"
|
|
46
|
+
import { useRoute, useRouter } from "vue-router"
|
|
52
47
|
|
|
53
48
|
export default defineComponent({
|
|
54
49
|
name: "AlertsPagination",
|
|
55
50
|
props: {
|
|
56
51
|
currentPage: {
|
|
57
52
|
type: Number,
|
|
58
|
-
required: true
|
|
53
|
+
required: true
|
|
59
54
|
},
|
|
60
55
|
pageSize: {
|
|
61
56
|
type: Number,
|
|
62
|
-
required: true
|
|
57
|
+
required: true
|
|
63
58
|
},
|
|
64
59
|
total: {
|
|
65
60
|
type: Number,
|
|
66
|
-
required: true
|
|
67
|
-
}
|
|
61
|
+
required: true
|
|
62
|
+
}
|
|
68
63
|
},
|
|
69
64
|
emits: ["update-page"],
|
|
70
65
|
setup(props, context) {
|
|
71
|
-
const route = useRoute()
|
|
72
|
-
const router = useRouter()
|
|
73
|
-
const options = { route, router }
|
|
66
|
+
const route = useRoute()
|
|
67
|
+
const router = useRouter()
|
|
68
|
+
const options = { route, router }
|
|
74
69
|
|
|
75
70
|
const totalPageCount = computed(() => {
|
|
76
|
-
return Math.ceil(props.total / props.pageSize)
|
|
77
|
-
})
|
|
71
|
+
return Math.ceil(props.total / props.pageSize)
|
|
72
|
+
})
|
|
78
73
|
|
|
79
74
|
const hasOnlyOnePage = computed(() => {
|
|
80
|
-
return totalPageCount.value === 1
|
|
81
|
-
})
|
|
75
|
+
return totalPageCount.value === 1
|
|
76
|
+
})
|
|
82
77
|
|
|
83
78
|
const hasPreviousPage = computed(() => {
|
|
84
|
-
return props.currentPage > 1
|
|
85
|
-
})
|
|
79
|
+
return props.currentPage > 1
|
|
80
|
+
})
|
|
86
81
|
|
|
87
82
|
const isPreviousPageNotFirst = computed(() => {
|
|
88
|
-
return props.currentPage - 1 !== 1
|
|
89
|
-
})
|
|
83
|
+
return props.currentPage - 1 !== 1
|
|
84
|
+
})
|
|
90
85
|
|
|
91
86
|
const hasNextPage = computed(() => {
|
|
92
|
-
return props.currentPage < totalPageCount.value
|
|
93
|
-
})
|
|
87
|
+
return props.currentPage < totalPageCount.value
|
|
88
|
+
})
|
|
94
89
|
|
|
95
90
|
const isNextPageNotLast = computed(() => {
|
|
96
|
-
return props.currentPage + 1 !== totalPageCount.value
|
|
97
|
-
})
|
|
91
|
+
return props.currentPage + 1 !== totalPageCount.value
|
|
92
|
+
})
|
|
98
93
|
|
|
99
94
|
const updatePage = (page: number) => {
|
|
100
|
-
const pageQuery = useRouteQuery("page", page.toString(), options)
|
|
101
|
-
pageQuery.value = page.toString()
|
|
95
|
+
const pageQuery = useRouteQuery("page", page.toString(), options)
|
|
96
|
+
pageQuery.value = page.toString()
|
|
102
97
|
|
|
103
|
-
context.emit("update-page", page)
|
|
104
|
-
}
|
|
98
|
+
context.emit("update-page", page)
|
|
99
|
+
}
|
|
105
100
|
|
|
106
101
|
onMounted(() => {
|
|
107
|
-
const pageQuery = useRouteQuery("page", null, options) as Ref<
|
|
108
|
-
string | null
|
|
109
|
-
>;
|
|
102
|
+
const pageQuery = useRouteQuery("page", null, options) as Ref<string | null>
|
|
110
103
|
if (pageQuery.value && parseInt(pageQuery.value) !== props.currentPage) {
|
|
111
|
-
updatePage(parseInt(pageQuery.value))
|
|
104
|
+
updatePage(parseInt(pageQuery.value))
|
|
112
105
|
}
|
|
113
|
-
})
|
|
106
|
+
})
|
|
114
107
|
|
|
115
108
|
return {
|
|
116
109
|
updatePage,
|
|
@@ -119,8 +112,8 @@ export default defineComponent({
|
|
|
119
112
|
hasPreviousPage,
|
|
120
113
|
isNextPageNotLast,
|
|
121
114
|
isPreviousPageNotFirst,
|
|
122
|
-
totalPageCount
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
})
|
|
115
|
+
totalPageCount
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
})
|
|
126
119
|
</script>
|