6
6
"net"
7
7
"net/http"
8
8
"net/netip"
9
+ "net/url"
10
+ "strings"
9
11
"time"
10
12
11
13
"github.com/google/uuid"
@@ -30,9 +32,21 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) {
30
32
return
31
33
}
32
34
35
+ queryStr := r .URL .Query ().Get ("q" )
36
+ filter , errs := auditSearchQuery (queryStr )
37
+ if len (errs ) > 0 {
38
+ httpapi .Write (rw , http .StatusBadRequest , codersdk.Response {
39
+ Message : "Invalid audit search query." ,
40
+ Validations : errs ,
41
+ })
42
+ return
43
+ }
44
+
33
45
dblogs , err := api .Database .GetAuditLogsOffset (ctx , database.GetAuditLogsOffsetParams {
34
- Offset : int32 (page .Offset ),
35
- Limit : int32 (page .Limit ),
46
+ Offset : int32 (page .Offset ),
47
+ Limit : int32 (page .Limit ),
48
+ ResourceType : filter .ResourceType ,
49
+ Action : filter .Action ,
36
50
})
37
51
if err != nil {
38
52
httpapi .InternalServerError (rw , err )
@@ -97,16 +111,27 @@ func (api *API) generateFakeAuditLog(rw http.ResponseWriter, r *http.Request) {
97
111
}
98
112
}
99
113
114
+ var params codersdk.CreateTestAuditLogRequest
115
+ if ! httpapi .Read (rw , r , & params ) {
116
+ return
117
+ }
118
+ if params .Action == "" {
119
+ params .Action = codersdk .AuditActionWrite
120
+ }
121
+ if params .ResourceType == "" {
122
+ params .ResourceType = codersdk .ResourceTypeUser
123
+ }
124
+
100
125
_ , err = api .Database .InsertAuditLog (ctx , database.InsertAuditLogParams {
101
126
ID : uuid .New (),
102
127
Time : time .Now (),
103
128
UserID : user .ID ,
104
129
Ip : ipNet ,
105
130
UserAgent : r .UserAgent (),
106
- ResourceType : database .ResourceTypeUser ,
131
+ ResourceType : database .ResourceType ( params . ResourceType ) ,
107
132
ResourceID : user .ID ,
108
133
ResourceTarget : user .Username ,
109
- Action : database .AuditActionWrite ,
134
+ Action : database .AuditAction ( params . Action ) ,
110
135
Diff : diff ,
111
136
StatusCode : http .StatusOK ,
112
137
AdditionalFields : []byte ("{}" ),
@@ -179,3 +204,42 @@ func auditLogDescription(alog database.GetAuditLogsOffsetRow) string {
179
204
codersdk .ResourceType (alog .ResourceType ).FriendlyString (),
180
205
)
181
206
}
207
+
208
+ // auditSearchQuery takes a query string and returns the auditLog filter.
209
+ // It also can return the list of validation errors to return to the api.
210
+ func auditSearchQuery (query string ) (database.GetAuditLogsOffsetParams , []codersdk.ValidationError ) {
211
+ searchParams := make (url.Values )
212
+ if query == "" {
213
+ // No filter
214
+ return database.GetAuditLogsOffsetParams {}, nil
215
+ }
216
+ query = strings .ToLower (query )
217
+ // Because we do this in 2 passes, we want to maintain quotes on the first
218
+ // pass.Further splitting occurs on the second pass and quotes will be
219
+ // dropped.
220
+ elements := splitQueryParameterByDelimiter (query , ' ' , true )
221
+ for _ , element := range elements {
222
+ parts := splitQueryParameterByDelimiter (element , ':' , false )
223
+ switch len (parts ) {
224
+ case 1 :
225
+ // No key:value pair.
226
+ searchParams .Set ("resource_type" , parts [0 ])
227
+ case 2 :
228
+ searchParams .Set (parts [0 ], parts [1 ])
229
+ default :
230
+ return database.GetAuditLogsOffsetParams {}, []codersdk.ValidationError {
231
+ {Field : "q" , Detail : fmt .Sprintf ("Query element %q can only contain 1 ':'" , element )},
232
+ }
233
+ }
234
+ }
235
+
236
+ // Using the query param parser here just returns consistent errors with
237
+ // other parsing.
238
+ parser := httpapi .NewQueryParamParser ()
239
+ filter := database.GetAuditLogsOffsetParams {
240
+ ResourceType : parser .String (searchParams , "" , "resource_type" ),
241
+ Action : parser .String (searchParams , "" , "action" ),
242
+ }
243
+
244
+ return filter , parser .Errors
245
+ }
0 commit comments