1
+ import { QueryRunner } from "typeorm"
1
2
import { AppDataSource } from "data-source"
2
3
import {
3
4
ApiEndpoint ,
@@ -7,12 +8,15 @@ import {
7
8
Alert ,
8
9
DataField ,
9
10
OpenApiSpec ,
11
+ Attack ,
10
12
} from "models"
11
13
import {
12
14
GetEndpointParams ,
13
15
ApiEndpoint as ApiEndpointResponse ,
14
16
ApiEndpointDetailed as ApiEndpointDetailedResponse ,
15
17
Usage as UsageResponse ,
18
+ GetHostParams ,
19
+ HostResponse ,
16
20
} from "@common/types"
17
21
import Error500InternalServer from "errors/error-500-internal-server"
18
22
import { Test } from "@metlo/testing"
@@ -50,6 +54,137 @@ ORDER BY
50
54
`
51
55
52
56
export class GetEndpointsService {
57
+ static async deleteEndpoint (
58
+ ctx : MetloContext ,
59
+ apiEndpointUuid : string ,
60
+ ) : Promise < void > {
61
+ const queryRunner = AppDataSource . createQueryRunner ( )
62
+ try {
63
+ await queryRunner . connect ( )
64
+ const endpoint = await getEntityManager ( ctx , queryRunner ) . findOneBy (
65
+ ApiEndpoint ,
66
+ { uuid : apiEndpointUuid } ,
67
+ )
68
+ if ( ! endpoint ) {
69
+ throw new Error404NotFound ( "Endpoint not found." )
70
+ }
71
+ await queryRunner . startTransaction ( )
72
+ await getQB ( ctx , queryRunner )
73
+ . delete ( )
74
+ . from ( AggregateTraceDataHourly )
75
+ . andWhere ( `"apiEndpointUuid" = :id` , { id : apiEndpointUuid } )
76
+ . execute ( )
77
+ await getQB ( ctx , queryRunner )
78
+ . delete ( )
79
+ . from ( Alert )
80
+ . andWhere ( `"apiEndpointUuid" = :id` , { id : apiEndpointUuid } )
81
+ . execute ( )
82
+ await getQB ( ctx , queryRunner )
83
+ . delete ( )
84
+ . from ( ApiEndpointTest )
85
+ . andWhere ( `"apiEndpointUuid" = :id` , { id : apiEndpointUuid } )
86
+ . execute ( )
87
+ await getQB ( ctx , queryRunner )
88
+ . delete ( )
89
+ . from ( ApiTrace )
90
+ . andWhere ( `"apiEndpointUuid" = :id` , { id : apiEndpointUuid } )
91
+ . execute ( )
92
+ await getQB ( ctx , queryRunner )
93
+ . delete ( )
94
+ . from ( Attack )
95
+ . andWhere ( `"apiEndpointUuid" = :id` , { id : apiEndpointUuid } )
96
+ . execute ( )
97
+ await getQB ( ctx , queryRunner )
98
+ . delete ( )
99
+ . from ( DataField )
100
+ . andWhere ( `"apiEndpointUuid" = :id` , { id : apiEndpointUuid } )
101
+ . execute ( )
102
+ await getQB ( ctx , queryRunner )
103
+ . delete ( )
104
+ . from ( ApiEndpoint )
105
+ . andWhere ( "uuid = :id" , { id : apiEndpointUuid } )
106
+ . execute ( )
107
+ await queryRunner . commitTransaction ( )
108
+ } catch ( err ) {
109
+ if ( queryRunner . isTransactionActive ) {
110
+ await queryRunner . rollbackTransaction ( )
111
+ }
112
+ throw err
113
+ } finally {
114
+ await queryRunner . release ( )
115
+ }
116
+ }
117
+
118
+ static async deleteEndpointsBatch (
119
+ ctx : MetloContext ,
120
+ apiEndpointUuids : string [ ] ,
121
+ queryRunner : QueryRunner ,
122
+ ) : Promise < void > {
123
+ await getQB ( ctx , queryRunner )
124
+ . delete ( )
125
+ . from ( AggregateTraceDataHourly )
126
+ . andWhere ( `"apiEndpointUuid" IN(:...ids)` , { ids : apiEndpointUuids } )
127
+ . execute ( )
128
+ await getQB ( ctx , queryRunner )
129
+ . delete ( )
130
+ . from ( Alert )
131
+ . andWhere ( `"apiEndpointUuid" IN(:...ids)` , { ids : apiEndpointUuids } )
132
+ . execute ( )
133
+ await getQB ( ctx , queryRunner )
134
+ . delete ( )
135
+ . from ( ApiEndpointTest )
136
+ . andWhere ( `"apiEndpointUuid" IN(:...ids)` , { ids : apiEndpointUuids } )
137
+ . execute ( )
138
+ await getQB ( ctx , queryRunner )
139
+ . delete ( )
140
+ . from ( ApiTrace )
141
+ . andWhere ( `"apiEndpointUuid" IN(:...ids)` , { ids : apiEndpointUuids } )
142
+ . execute ( )
143
+ await getQB ( ctx , queryRunner )
144
+ . delete ( )
145
+ . from ( Attack )
146
+ . andWhere ( `"apiEndpointUuid" IN(:...ids)` , { ids : apiEndpointUuids } )
147
+ . execute ( )
148
+ await getQB ( ctx , queryRunner )
149
+ . delete ( )
150
+ . from ( DataField )
151
+ . andWhere ( `"apiEndpointUuid" IN(:...ids)` , { ids : apiEndpointUuids } )
152
+ . execute ( )
153
+ await getQB ( ctx , queryRunner )
154
+ . delete ( )
155
+ . from ( ApiEndpoint )
156
+ . andWhere ( "uuid IN(:...ids)" , { ids : apiEndpointUuids } )
157
+ . execute ( )
158
+ }
159
+
160
+ static async deleteHost ( ctx : MetloContext , host : string ) : Promise < void > {
161
+ const queryRunner = AppDataSource . createQueryRunner ( )
162
+ try {
163
+ await queryRunner . connect ( )
164
+ const endpoints = await getQB ( ctx , queryRunner )
165
+ . select ( [ "uuid" ] )
166
+ . from ( ApiEndpoint , "endpoint" )
167
+ . andWhere ( "host = :host" , { host } )
168
+ . getRawMany ( )
169
+ if ( endpoints ?. length > 0 ) {
170
+ await queryRunner . startTransaction ( )
171
+ await this . deleteEndpointsBatch (
172
+ ctx ,
173
+ endpoints ?. map ( e => e . uuid ) ,
174
+ queryRunner ,
175
+ )
176
+ await queryRunner . commitTransaction ( )
177
+ }
178
+ } catch ( err ) {
179
+ if ( queryRunner . isTransactionActive ) {
180
+ await queryRunner . rollbackTransaction ( )
181
+ }
182
+ throw err
183
+ } finally {
184
+ await queryRunner . release ( )
185
+ }
186
+ }
187
+
53
188
static async updateIsAuthenticated (
54
189
ctx : MetloContext ,
55
190
apiEndpointUuid : string ,
@@ -134,7 +269,7 @@ export class GetEndpointsService {
134
269
whereFilterString = `WHERE ${ whereFilter . join ( " AND " ) } `
135
270
}
136
271
const limitFilter = `LIMIT ${ getEndpointParams ?. limit ?? 10 } `
137
- const offsetFilter = `OFFSET ${ getEndpointParams ?. offset ?? 10 } `
272
+ const offsetFilter = `OFFSET ${ getEndpointParams ?. offset ?? 0 } `
138
273
139
274
const endpointResults = await queryRunner . query (
140
275
getEndpointsQuery ( ctx , whereFilterString , limitFilter , offsetFilter ) ,
@@ -224,6 +359,47 @@ export class GetEndpointsService {
224
359
}
225
360
}
226
361
362
+ static async getHostsList (
363
+ ctx : MetloContext ,
364
+ getHostsParams : GetHostParams ,
365
+ ) : Promise < [ HostResponse [ ] , any ] > {
366
+ const queryRunner = AppDataSource . createQueryRunner ( )
367
+ try {
368
+ await queryRunner . connect ( )
369
+
370
+ let qb = getQB ( ctx , queryRunner )
371
+ . select ( [ "host" , `COUNT(uuid) as "numEndpoints"` ] )
372
+ . from ( ApiEndpoint , "endpoint" )
373
+ . distinct ( true )
374
+ . groupBy ( "host" )
375
+ let totalHostsQb = await getQB ( ctx , queryRunner )
376
+ . select ( [ `COUNT(DISTINCT(host))::int as "numHosts"` ] )
377
+ . from ( ApiEndpoint , "endpoint" )
378
+
379
+ if ( getHostsParams ?. searchQuery ) {
380
+ qb = qb . andWhere ( "host ILIKE :searchQuery" , {
381
+ searchQuery : `%${ getHostsParams . searchQuery } %` ,
382
+ } )
383
+ totalHostsQb = totalHostsQb . andWhere ( "host ILIKE :searchQuery" , {
384
+ searchQuery : `%${ getHostsParams . searchQuery } %` ,
385
+ } )
386
+ }
387
+
388
+ qb = qb
389
+ . limit ( getHostsParams ?. limit ?? 10 )
390
+ . offset ( getHostsParams ?. offset ?? 0 )
391
+
392
+ const hostsResp = await qb . getRawMany ( )
393
+ const totalHosts = await totalHostsQb . getRawOne ( )
394
+
395
+ return [ hostsResp , totalHosts ?. numHosts ?? 0 ]
396
+ } catch ( err ) {
397
+ throw new Error500InternalServer ( err )
398
+ } finally {
399
+ await queryRunner . release ( )
400
+ }
401
+ }
402
+
227
403
static async getUsage (
228
404
ctx : MetloContext ,
229
405
endpointId : string ,
0 commit comments