Database refactor and test coverage

This commit is contained in:
Imbus 2024-03-14 13:39:56 +01:00
parent 327f90e448
commit 6c8abf1f53
4 changed files with 84 additions and 16 deletions

View file

@ -20,8 +20,8 @@ type Database interface {
GetUserId(username string) (int, error) GetUserId(username string) (int, error)
AddProject(name string, description string, username string) error AddProject(name string, description string, username string) error
Migrate(dirname string) error Migrate(dirname string) error
// AddTimeReport(projectname string, start time.Time, end time.Time) error AddTimeReport(projectName string, userName string, start time.Time, end time.Time) error
// AddUserToProject(username string, projectname string) error AddUserToProject(username string, projectname string, role string) error
// ChangeUserRole(username string, projectname string, role string) error // ChangeUserRole(username string, projectname string, role string) error
// AddTimeReport(projectname string, start time.Time, end time.Time) error // AddTimeReport(projectname string, start time.Time, end time.Time) error
// AddUserToProject(username string, projectname string) error // AddUserToProject(username string, projectname string) error
@ -37,12 +37,16 @@ type Db struct {
//go:embed migrations //go:embed migrations
var scripts embed.FS var scripts embed.FS
// TODO: Possibly break these out into separate files bundled with the embed package?
const userInsert = "INSERT INTO users (username, password) VALUES (?, ?)" const userInsert = "INSERT INTO users (username, password) VALUES (?, ?)"
const projectInsert = "INSERT INTO projects (name, description, owner_user_id) SELECT ?, ?, id FROM users WHERE username = ?" const projectInsert = "INSERT INTO projects (name, description, owner_user_id) SELECT ?, ?, id FROM users WHERE username = ?"
const promoteToAdmin = "INSERT INTO site_admin (admin_id) SELECT id FROM users WHERE username = ?" const promoteToAdmin = "INSERT INTO site_admin (admin_id) SELECT id FROM users WHERE username = ?"
const addTimeReport = "INSERT INTO activity (report_id, activity_nbr, start_time, end_time, break, comment) VALUES (?, ?, ?, ?, ?, ?)" // WIP const addTimeReport = `WITH UserLookup AS (SELECT id FROM users WHERE username = ?),
const addUserToProject = "INSERT INTO project_member (project_id, user_id, role) VALUES (?, ?, ?)" // WIP ProjectLookup AS (SELECT id FROM projects WHERE name = ?)
// const changeUserRole = "" INSERT INTO time_reports (project_id, user_id, start, end)
VALUES ((SELECT id FROM ProjectLookup), (SELECT id FROM UserLookup), ?, ?);`
const addUserToProject = "INSERT INTO user_roles (user_id, project_id, p_role) VALUES (?, ?, ?)" // WIP
const changeUserRole = "UPDATE project_member SET role = ? WHERE user_id = ? AND project_id = ?"
// DbConnect connects to the database // DbConnect connects to the database
func DbConnect(dbpath string) Database { func DbConnect(dbpath string) Database {
@ -61,8 +65,8 @@ func DbConnect(dbpath string) Database {
return &Db{db} return &Db{db}
} }
func (d *Db) AddTimeReport(projectname string, start time.Time, end time.Time, breakTime uint32) error { // WIP func (d *Db) AddTimeReport(projectName string, userName string, start time.Time, end time.Time) error { // WIP
_, err := d.Exec(addTimeReport, projectname, 0, start, end, breakTime, false) _, err := d.Exec(addTimeReport, userName, projectName, start, end)
return err return err
} }
@ -79,13 +83,26 @@ func (d *Db) AddUserToProject(username string, projectname string, role string)
panic(err2) panic(err2)
} }
_, err3 := d.Exec(addUserToProject, projectid, userid, role) _, err3 := d.Exec(addUserToProject, userid, projectid, role)
return err3 return err3
} }
// func (d *Db) ChangeUserRole(username string, projectname string, role string) error { func (d *Db) ChangeUserRole(username string, projectname string, role string) error {
var userid int
userid, err := d.GetUserId(username)
if err != nil {
panic(err)
}
// } var projectid int
projectid, err2 := d.GetProjectId(projectname)
if err2 != nil {
panic(err2)
}
_, err3 := d.Exec(changeUserRole, role, userid, projectid)
return err3
}
// AddUser adds a user to the database // AddUser adds a user to the database
func (d *Db) AddUser(username string, password string) error { func (d *Db) AddUser(username string, password string) error {
@ -112,7 +129,7 @@ func (d *Db) GetUserId(username string) (int, error) {
func (d *Db) GetProjectId(projectname string) (int, error) { // WIP, denna kan vara goof func (d *Db) GetProjectId(projectname string) (int, error) { // WIP, denna kan vara goof
var id int var id int
err := d.Get(&id, "SELECT id FROM project WHERE project_name = ?", projectname) err := d.Get(&id, "SELECT id FROM projects WHERE name = ?", projectname)
return id, err return id, err
} }

View file

@ -2,6 +2,7 @@ package database
import ( import (
"testing" "testing"
"time"
) )
// Tests are not guaranteed to be sequential // Tests are not guaranteed to be sequential
@ -92,9 +93,60 @@ func TestPromoteToAdmin(t *testing.T) {
} }
} }
// func TestAddTimeReport(t *testing.T) { func TestAddTimeReport(t *testing.T) {
db, err := setupState()
if err != nil {
t.Error("setupState failed:", err)
}
// } err = db.AddUser("testuser", "password")
if err != nil {
t.Error("AddUser failed:", err)
}
err = db.AddProject("testproject", "description", "testuser")
if err != nil {
t.Error("AddProject failed:", err)
}
var now = time.Now()
var then = now.Add(time.Hour)
err = db.AddTimeReport("testproject", "testuser", now, then)
if err != nil {
t.Error("AddTimeReport failed:", err)
}
}
func TestAddUserToProject(t *testing.T) {
db, err := setupState()
if err != nil {
t.Error("setupState failed:", err)
}
err = db.AddUser("testuser", "password")
if err != nil {
t.Error("AddUser failed:", err)
}
err = db.AddProject("testproject", "description", "testuser")
if err != nil {
t.Error("AddProject failed:", err)
}
var now = time.Now()
var then = now.Add(time.Hour)
err = db.AddTimeReport("testproject", "testuser", now, then)
if err != nil {
t.Error("AddTimeReport failed:", err)
}
err = db.AddUserToProject("testuser", "testproject", "user")
if err != nil {
t.Error("AddUserToProject failed:", err)
}
}
// func TestAddUserToProject(t *testing.T) { // func TestAddUserToProject(t *testing.T) {

View file

@ -1,11 +1,9 @@
CREATE TABLE IF NOT EXISTS projects ( CREATE TABLE IF NOT EXISTS projects (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
projectId TEXT DEFAULT (HEX(RANDOMBLOB(4))) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL UNIQUE, name VARCHAR(255) NOT NULL UNIQUE,
description TEXT NOT NULL, description TEXT NOT NULL,
owner_user_id INTEGER NOT NULL, owner_user_id INTEGER NOT NULL,
FOREIGN KEY (owner_user_id) REFERENCES users (id) FOREIGN KEY (owner_user_id) REFERENCES users (id)
); );
CREATE INDEX IF NOT EXISTS projects_projectId_index ON projects (projectId);
CREATE INDEX IF NOT EXISTS projects_user_id_index ON projects (owner_user_id); CREATE INDEX IF NOT EXISTS projects_user_id_index ON projects (owner_user_id);

View file

@ -1,10 +1,11 @@
CREATE TABLE IF NOT EXISTS time_reports ( CREATE TABLE IF NOT EXISTS time_reports (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
reportId TEXT DEFAULT (HEX(RANDOMBLOB(6))) NOT NULL UNIQUE,
project_id INTEGER NOT NULL, project_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
start DATETIME NOT NULL, start DATETIME NOT NULL,
end DATETIME NOT NULL, end DATETIME NOT NULL,
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
); );
CREATE TRIGGER IF NOT EXISTS time_reports_start_before_end CREATE TRIGGER IF NOT EXISTS time_reports_start_before_end