From 4edf354f8de83d652ebb7aff86fe8f4cb3d520ae Mon Sep 17 00:00:00 2001 From: simon987 Date: Mon, 11 Feb 2019 20:10:33 -0500 Subject: [PATCH] some bug fixes, some optimizations --- README.md | 4 +-- api/log.go | 13 ++++--- api/project.go | 10 +++++- api/task.go | 17 ++++++--- config.yml | 4 +-- schema.sql | 33 +++++++++++++++++ storage/auth.go | 2 +- storage/project.go | 17 +++++++-- storage/task.go | 36 +++++-------------- test/schema.sql | 33 +++++++++++++++++ updateBadges.sh | 4 --- .../create-project.component.html | 18 ++++------ .../project-dashboard.component.ts | 11 ++++-- 13 files changed, 141 insertions(+), 61 deletions(-) delete mode 100755 updateBadges.sh diff --git a/README.md b/README.md index 36f7880..6072a12 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -![gopherbadger-tag-do-not-edit](https://img.shields.io/badge/Go%20Coverage-93%25-brightgreen.svg?longCache=true&style=flat-square) +![gopherbadger-tag-do-not-edit](https://img.shields.io/badge/Go%20Coverage-78%25-brightgreen.svg?longCache=true&style=flat-square) ### Running tests ```bash cd test/ -go test -bench +go test ``` \ No newline at end of file diff --git a/api/log.go b/api/log.go index 5761420..eee808f 100644 --- a/api/log.go +++ b/api/log.go @@ -30,6 +30,11 @@ type GetLogResponse struct { Logs *[]storage.LogEntry `json:"logs"` } +type LogResponse struct { + Ok bool `json:"ok"` + Message string `json:"message"` +} + func (e *LogRequest) Time() time.Time { t := time.Unix(e.TimeStamp, 0) @@ -89,7 +94,7 @@ func (api *WebAPI) LogTrace(r *Request) { entry, err := api.parseLogEntry(r) if err != nil { - r.Json(GetLogResponse{ + r.Json(LogResponse{ Ok: false, Message: "Could not parse request", }, 400) @@ -106,7 +111,7 @@ func (api *WebAPI) LogInfo(r *Request) { entry, err := api.parseLogEntry(r) if err != nil { - r.Json(GetLogResponse{ + r.Json(LogResponse{ Ok: false, Message: "Could not parse request", }, 400) @@ -123,7 +128,7 @@ func (api *WebAPI) LogWarn(r *Request) { entry, err := api.parseLogEntry(r) if err != nil { - r.Json(GetLogResponse{ + r.Json(LogResponse{ Ok: false, Message: "Could not parse request", }, 400) @@ -140,7 +145,7 @@ func (api *WebAPI) LogError(r *Request) { entry, err := api.parseLogEntry(r) if err != nil { - r.Json(GetLogResponse{ + r.Json(LogResponse{ Ok: false, Message: "Could not parse request", }, 400) diff --git a/api/project.go b/api/project.go index 1294603..0f561ba 100644 --- a/api/project.go +++ b/api/project.go @@ -202,7 +202,15 @@ func (api *WebAPI) ProjectGet(r *Request) { func (api *WebAPI) ProjectGetAllProjects(r *Request) { - projects := api.Database.GetAllProjects() + worker, _ := api.validateSignature(r) + + var id int64 + if worker == nil { + id = 0 + } else { + id = worker.Id + } + projects := api.Database.GetAllProjects(id) r.OkJson(GetAllProjectsResponse{ Ok: true, diff --git a/api/task.go b/api/task.go index 7588a7b..d5bb5b0 100644 --- a/api/task.go +++ b/api/task.go @@ -156,11 +156,20 @@ func (api *WebAPI) TaskGet(r *Request) { } task := api.Database.GetTask(worker) + if task == nil { - r.OkJson(GetTaskResponse{ - Ok: true, - Task: task, - }) + r.OkJson(GetTaskResponse{ + Ok: false, + Message: "No task available", + }) + + } else { + + r.OkJson(GetTaskResponse{ + Ok: true, + Task: task, + }) + } } func (api WebAPI) validateSignature(r *Request) (*storage.Worker, error) { diff --git a/config.yml b/config.yml index 3d86868..56629c3 100755 --- a/config.yml +++ b/config.yml @@ -8,9 +8,9 @@ database: git: webhook_secret: "very_secret_secret" # Github: sha1, Gogs: sha256 - webhook_hash: "sha1" + webhook_hash: "sha256" # Github: 'X-Hub-Signature', Gogs: 'X-Gogs-Signature' - webhook_sig_header: "X-Hub-Signature" + webhook_sig_header: "X-Gogs-Signature" log: # panic, fatal, error, warn, info, debug, trace diff --git a/schema.sql b/schema.sql index 67b124b..85cf48b 100755 --- a/schema.sql +++ b/schema.sql @@ -113,3 +113,36 @@ CREATE TRIGGER on_task_delete ON task FOR EACH ROW EXECUTE PROCEDURE on_task_delete_proc(); + +CREATE OR REPLACE FUNCTION release_task_ok(wid INT, tid INT, ver INT) RETURNS BOOLEAN AS +$$ +DECLARE + res INT = NULL; +BEGIN + DELETE FROM task WHERE id = tid AND assignee = wid AND verification_count < 2 RETURNING project INTO res; + + IF res IS NULL THEN + INSERT INTO worker_verifies_task (worker, verification_hash, task) + SELECT wid, ver, task.id + FROM task + WHERE assignee = wid; + + DELETE + FROM task + WHERE id = tid + AND assignee = wid + AND (SELECT COUNT(*) as vcnt + FROM worker_verifies_task wvt + WHERE task = tid + GROUP BY wvt.verification_hash + ORDER BY vcnt DESC + LIMIT 1) >= task.verification_count RETURNING task.id INTO res; + + IF res IS NULL THEN + UPDATE task SET assignee= NULL WHERE id = tid AND assignee = wid; + end if; + end if; + + RETURN res IS NOT NULL; +END; +$$ LANGUAGE 'plpgsql'; diff --git a/storage/auth.go b/storage/auth.go index 2613415..b8ebcdd 100644 --- a/storage/auth.go +++ b/storage/auth.go @@ -104,8 +104,8 @@ func (database *Database) UpdateManager(manager *Manager) { func (database *Database) UpdateManagerPassword(manager *Manager, newPassword []byte) { hash := crypto.SHA512.New() - hash.Write([]byte(manager.Username)) hash.Write(newPassword) + hash.Write([]byte(manager.Username)) hashedPassword := hash.Sum(nil) db := database.getDB() diff --git a/storage/project.go b/storage/project.go index 42299cb..caf1f25 100644 --- a/storage/project.go +++ b/storage/project.go @@ -131,14 +131,27 @@ func (database *Database) UpdateProject(project *Project) error { return nil } -func (database Database) GetAllProjects() *[]Project { +func (database Database) GetAllProjects(workerId int64) *[]Project { projects := make([]Project, 0) db := database.getDB() - rows, err := db.Query(`SELECT + var rows *sql.Rows + var err error + if workerId == 0 { + rows, err = db.Query(`SELECT Id, priority, name, clone_url, git_repo, version, motd, public FROM project + LEFT JOIN worker_has_access_to_project whatp ON whatp.project = id + WHERE public ORDER BY name`) + } else { + rows, err = db.Query(`SELECT + Id, priority, name, clone_url, git_repo, version, motd, public + FROM project + LEFT JOIN worker_has_access_to_project whatp ON whatp.project = id + WHERE public OR whatp.worker = $1 + ORDER BY name`, workerId) + } handleErr(err) for rows.Next() { diff --git a/storage/task.go b/storage/task.go index 29f66e3..eaf75aa 100644 --- a/storage/task.go +++ b/storage/task.go @@ -134,52 +134,34 @@ func (database Database) ReleaseTask(id int64, workerId int64, result TaskResult db := database.getDB() - var rowsAffected int64 + var taskUpdated bool if result == TR_OK { - var pid int64 - - //If no verification is required - row := db.QueryRow(`DELETE FROM task WHERE id=$1 AND assignee=$2 AND verification_count < 2 - RETURNING project`, id, workerId) - err := row.Scan(&pid) - if err == nil { - rowsAffected = 1 - } else { - //If verification is required - _, err = db.Exec(`INSERT INTO worker_verifies_task (worker, verification_hash, task) - SELECT $1,$2,task.id FROM task WHERE assignee=$1`, workerId, verification) - handleErr(err) - - res, _ := db.Exec(`DELETE FROM task WHERE id=$1 AND assignee=$2 AND - (SELECT COUNT(*) as vcnt FROM worker_verifies_task wvt WHERE task=$1 - GROUP BY wvt.verification_hash ORDER BY vcnt DESC LIMIT 1) >= task.verification_count`, - id, workerId) - rowsAffected, _ = res.RowsAffected() - - _, _ = db.Exec(`UPDATE task SET assignee=NULL WHERE id=$1 AND assignee=$2`, id, workerId) - } + row := db.QueryRow(`SELECT release_task_ok($1,$2,$3)`, workerId, id, verification) + _ = row.Scan(&taskUpdated) } else if result == TR_FAIL { res, err := db.Exec(`UPDATE task SET (status, assignee, retries) = (CASE WHEN retries+1 >= max_retries THEN 2 ELSE 1 END, NULL, retries+1) WHERE id=$1 AND assignee=$2`, id, workerId) handleErr(err) - rowsAffected, _ = res.RowsAffected() + rowsAffected, _ := res.RowsAffected() + taskUpdated = rowsAffected == 1 } else if result == TR_SKIP { res, err := db.Exec(`UPDATE task SET (status, assignee) = (1, NULL) WHERE id=$1 AND assignee=$2`, id, workerId) handleErr(err) - rowsAffected, _ = res.RowsAffected() + rowsAffected, _ := res.RowsAffected() + taskUpdated = rowsAffected == 1 } logrus.WithFields(logrus.Fields{ - "rowsAffected": rowsAffected, + "taskUpdated": taskUpdated, "taskId": id, "workerId": workerId, "verification": verification, }).Trace("Database.ReleaseTask") - return rowsAffected == 1 + return taskUpdated } func (database *Database) GetTaskFromProject(worker *Worker, projectId int64) *Task { diff --git a/test/schema.sql b/test/schema.sql index 67b124b..85cf48b 100755 --- a/test/schema.sql +++ b/test/schema.sql @@ -113,3 +113,36 @@ CREATE TRIGGER on_task_delete ON task FOR EACH ROW EXECUTE PROCEDURE on_task_delete_proc(); + +CREATE OR REPLACE FUNCTION release_task_ok(wid INT, tid INT, ver INT) RETURNS BOOLEAN AS +$$ +DECLARE + res INT = NULL; +BEGIN + DELETE FROM task WHERE id = tid AND assignee = wid AND verification_count < 2 RETURNING project INTO res; + + IF res IS NULL THEN + INSERT INTO worker_verifies_task (worker, verification_hash, task) + SELECT wid, ver, task.id + FROM task + WHERE assignee = wid; + + DELETE + FROM task + WHERE id = tid + AND assignee = wid + AND (SELECT COUNT(*) as vcnt + FROM worker_verifies_task wvt + WHERE task = tid + GROUP BY wvt.verification_hash + ORDER BY vcnt DESC + LIMIT 1) >= task.verification_count RETURNING task.id INTO res; + + IF res IS NULL THEN + UPDATE task SET assignee= NULL WHERE id = tid AND assignee = wid; + end if; + end if; + + RETURN res IS NOT NULL; +END; +$$ LANGUAGE 'plpgsql'; diff --git a/updateBadges.sh b/updateBadges.sh deleted file mode 100755 index 368678b..0000000 --- a/updateBadges.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - -gopherbadger -md="README.md" -png=false -style flat-square -rm coverage.out \ No newline at end of file diff --git a/web/angular/src/app/create-project/create-project.component.html b/web/angular/src/app/create-project/create-project.component.html index dbeb4ef..1757192 100644 --- a/web/angular/src/app/create-project/create-project.component.html +++ b/web/angular/src/app/create-project/create-project.component.html @@ -4,35 +4,31 @@ {{"project.create_subtitle" | translate}} -
{{"project.name" | translate}} - + {{ "project.clone_url" | translate}} - + {{ "project.git_repo" | translate }} - + {{"project.git_repo_hint" | translate}} - + {{"project.public" | translate}} - - -
- + diff --git a/web/angular/src/app/project-dashboard/project-dashboard.component.ts b/web/angular/src/app/project-dashboard/project-dashboard.component.ts index 7dda45f..ef8673f 100644 --- a/web/angular/src/app/project-dashboard/project-dashboard.component.ts +++ b/web/angular/src/app/project-dashboard/project-dashboard.component.ts @@ -71,7 +71,7 @@ export class ProjectDashboardComponent implements OnInit { } this.noTasks = false; - this.timeline.data.labels = this.snapshots.map(s => s.time_stamp as any); + this.timeline.data.labels = this.snapshots.map(s => s.time_stamp * 1000 as any); this.timeline.data.datasets = this.makeTimelineDataset(this.snapshots); this.timeline.update(); this.statusPie.data.datasets = [ @@ -164,7 +164,7 @@ export class ProjectDashboardComponent implements OnInit { this.timeline = new Chart(ctx, { type: "bar", data: { - labels: this.snapshots.map(s => s.time_stamp as any), + labels: this.snapshots.map(s => s.time_stamp * 1000 as any), datasets: this.makeTimelineDataset(this.snapshots), }, options: { @@ -198,11 +198,16 @@ export class ProjectDashboardComponent implements OnInit { private setupStatusPie() { - if (this.lastSnapshot == null || (this.lastSnapshot.awaiting_verification_count == 0 && + if (this.lastSnapshot == undefined || (this.lastSnapshot.awaiting_verification_count == 0 && this.lastSnapshot.closed_task_count == 0 && this.lastSnapshot.new_task_count == 0 && this.lastSnapshot.failed_task_count == 0)) { this.noTasks = true; + + this.lastSnapshot = { + closed_task_count: 0, time_stamp: 0, failed_task_count: 0, + new_task_count: 0, awaiting_verification_count: 0 + } } let elem = document.getElementById("status-pie") as any;