From a39c1aa5eb4031d3302ab1cf817f3c3903aa9412 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 29 May 2022 20:08:21 +0200 Subject: [PATCH] feat(server): added proper filtering the BuildLog API --- src/db/logs.v | 35 ++++++++++++++++++++++++++++------- src/models/logs.v | 3 +-- src/models/models.v | 7 +++++++ src/server/logs.v | 9 ++++----- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/db/logs.v b/src/db/logs.v index 4ec48c7b..806f3d8f 100644 --- a/src/db/logs.v +++ b/src/db/logs.v @@ -16,23 +16,44 @@ pub fn (db &VieterDb) get_build_logs(filter BuildLogFilter) []BuildLog { } if filter.after != time.Time{} { - where_parts << 'start_time < $filter.after.unix_time()' + where_parts << 'start_time > $filter.after.unix_time()' + } + + // NOTE: possible SQL injection + if filter.arch != '' { + where_parts << "arch == '$filter.arch'" + } + + println(filter.exit_codes) + + mut parts := []string{} + + for exp in filter.exit_codes { + if exp[0] == `!` { + code := exp[1..].int() + + parts << 'exit_code != $code' + }else { + code := exp.int() + + parts << 'exit_code == $code' + } + } + + if parts.len > 0 { + where_parts << parts.map('($it)').join(' or ') } mut where_str := '' if where_parts.len > 0 { - where_str = ' where ' + where_parts.map('($it)').join(' and ') + where_str = 'where ' + where_parts.map('($it)').join(' and ') } - query := 'select from BuildLog' + where_str + query := 'select * from BuildLog $where_str limit $filter.limit offset $filter.offset' rows, _ := db.conn.exec(query) res := rows.map(row_into(it)) - // res := sql db.conn { - // select from BuildLog where filter.repo == 0 || repo_id == filter.repo order by id - // } - return res } diff --git a/src/models/logs.v b/src/models/logs.v index 82fc52fe..5ea9dd57 100644 --- a/src/models/logs.v +++ b/src/models/logs.v @@ -35,7 +35,6 @@ pub mut: repo int before time.Time after time.Time - exit_codes_whitelist []u8 - exit_codes_blacklist []u8 arch string + exit_codes []string } diff --git a/src/models/models.v b/src/models/models.v index 924f45ff..0d0395a2 100644 --- a/src/models/models.v +++ b/src/models/models.v @@ -1,5 +1,7 @@ module models +import time + // from_params creates a new instance of T from the given map by parsing all // of its fields from the map. pub fn from_params(params map[string]string) ?T { @@ -23,7 +25,12 @@ pub fn patch_from_params(mut o T, params map[string]string) ? { o.$(field.name) = params[field.name].u64() } $else $if field.typ is []GitRepoArch { o.$(field.name) = params[field.name].split(',').map(GitRepoArch{ value: it }) + } $else $if field.typ is time.Time { + o.$(field.name) = time.unix(params[field.name].int()) + } $else $if field.typ is []string { + o.$(field.name) = params[field.name].split(',') } + } else if field.attrs.contains('nonull') { return error('Missing parameter: ${field.name}.') } diff --git a/src/server/logs.v b/src/server/logs.v index af0b0812..51b364fa 100644 --- a/src/server/logs.v +++ b/src/server/logs.v @@ -8,7 +8,7 @@ import db import time import os import util -import models { BuildLog } +import models { BuildLog, BuildLogFilter } // get_logs returns all build logs in the database. A 'repo' query param can // optionally be added to limit the list of build logs to that repository. @@ -18,11 +18,10 @@ fn (mut app App) get_logs() web.Result { return app.json(http.Status.unauthorized, new_response('Unauthorized.')) } - logs := if 'repo' in app.query { - app.db.get_build_logs_for_repo(app.query['repo'].int()) - } else { - app.db.get_build_logs() + filter := models.from_params(app.query) or { + return app.json(http.Status.bad_request, new_response('Invalid query parameters.')) } + logs := app.db.get_build_logs(filter) return app.json(http.Status.ok, new_data_response(logs)) }