Compare commits

...

4 commits

Author SHA1 Message Date
Imbus
25fdf3bb9b Nuke dead code 2024-03-13 12:29:15 +01:00
Imbus
c4632104a8 Commenting out trigger related to salts 2024-03-13 11:46:17 +01:00
Imbus
736cebe036 Sql comments and salts table 2024-03-12 20:44:54 +01:00
Imbus
9b67a580da Gluecode for database/handlers 2024-03-12 20:44:40 +01:00
8 changed files with 76 additions and 164 deletions

View file

@ -12,7 +12,9 @@ import (
// Interface for the database // Interface for the database
type Database interface { type Database interface {
// Insert a new user into the database, password should be hashed before calling
AddUser(username string, password string) error AddUser(username string, password string) error
RemoveUser(username string) error RemoveUser(username string) error
PromoteToAdmin(username string) error PromoteToAdmin(username string) error
GetUserId(username string) (int, error) GetUserId(username string) (int, error)

View file

@ -1,3 +1,7 @@
-- Id is a surrogate key for in ternal use
-- userId is what is used for external id
-- username is what is used for login
-- password is the hashed password
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
userId TEXT DEFAULT (HEX(RANDOMBLOB(4))) NOT NULL UNIQUE, userId TEXT DEFAULT (HEX(RANDOMBLOB(4))) NOT NULL UNIQUE,
@ -5,5 +9,6 @@ CREATE TABLE IF NOT EXISTS users (
password VARCHAR(255) NOT NULL password VARCHAR(255) NOT NULL
); );
-- Users are commonly searched by username and userId
CREATE INDEX IF NOT EXISTS users_username_index ON users (username); CREATE INDEX IF NOT EXISTS users_username_index ON users (username);
CREATE INDEX IF NOT EXISTS users_userId_index ON users (userId); CREATE INDEX IF NOT EXISTS users_userId_index ON users (userId);

View file

@ -0,0 +1,16 @@
-- It is unclear weather this table will be used
-- Create the table to store hash salts
CREATE TABLE salts (
id INTEGER PRIMARY KEY,
salt TEXT NOT NULL
);
-- Commented out for now, no time for good practices, which is atrocious
-- Create a trigger to automatically generate a salt when inserting a new user record
-- CREATE TRIGGER generate_salt_trigger
-- AFTER INSERT ON users
-- BEGIN
-- INSERT INTO salts (salt) VALUES (randomblob(16));
-- UPDATE users SET salt_id = (SELECT last_insert_rowid()) WHERE id = new.id;
-- END;

View file

@ -11,11 +11,11 @@ import (
// The actual interface that we will use // The actual interface that we will use
type GlobalState interface { type GlobalState interface {
Register(c *fiber.Ctx) error // To register a new user Register(c *fiber.Ctx) error // To register a new user
UserDelete(c *fiber.Ctx) error // To delete a user UserDelete(c *fiber.Ctx) error // To delete a user
Login(c *fiber.Ctx) error // To get the token Login(c *fiber.Ctx) error // To get the token
LoginRenew(c *fiber.Ctx) error // To renew the token LoginRenew(c *fiber.Ctx) error // To renew the token
// CreateProject(c *fiber.Ctx) error // To create a new project CreateProject(c *fiber.Ctx) error // To create a new project
// GetProjects(c *fiber.Ctx) error // To get all projects // GetProjects(c *fiber.Ctx) error // To get all projects
// GetProject(c *fiber.Ctx) error // To get a specific project // GetProject(c *fiber.Ctx) error // To get a specific project
// UpdateProject(c *fiber.Ctx) error // To update a project // UpdateProject(c *fiber.Ctx) error // To update a project
@ -58,7 +58,7 @@ type GState struct {
// @Failure 500 {string} string "Internal server error" // @Failure 500 {string} string "Internal server error"
// @Router /api/register [post] // @Router /api/register [post]
func (gs *GState) Register(c *fiber.Ctx) error { func (gs *GState) Register(c *fiber.Ctx) error {
u := new(types.User) u := new(types.NewUser)
if err := c.BodyParser(u); err != nil { if err := c.BodyParser(u); err != nil {
return c.Status(400).SendString(err.Error()) return c.Status(400).SendString(err.Error())
} }
@ -142,3 +142,24 @@ func (gs *GState) LoginRenew(c *fiber.Ctx) error {
} }
return c.JSON(fiber.Map{"token": t}) return c.JSON(fiber.Map{"token": t})
} }
// CreateProject is a simple handler that creates a new project
func (gs *GState) CreateProject(c *fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token)
p := new(types.NewProject)
if err := c.BodyParser(p); err != nil {
return c.Status(400).SendString(err.Error())
}
// Get the username from the token and set it as the owner of the project
// This is ugly but
claims := user.Claims.(jwt.MapClaims)
p.Owner = claims["name"].(string)
if err := gs.Db.AddProject(p.Name, p.Description, p.Owner); err != nil {
return c.Status(500).SendString(err.Error())
}
return c.Status(200).SendString("Project added")
}

View file

@ -1,19 +0,0 @@
package model
type TimeReport struct {
reportId string
projectName string
userName string
userRole string
reportDate string
timeWorked uint64
isSigned bool
reportStatus string // Example "draft", "signed", "unsigned"
}
type Project struct {
timeReports []TimeReport
projectName string
projectmembers map[string]User
projectRoles map[string]User
}

View file

@ -1,139 +0,0 @@
package model
import (
"errors"
)
type Account struct {
fullName string
userName string
}
type Administrator struct {
projects map[string]Project
Account
ProjectMember // comp
}
// Administrator reciever functions
func (administrator Administrator) addUser(project *Project, user *User) error {
// WIP
return errors.New("WIP")
}
func (administrator Administrator) removerUser(project *Project, user *User) error {
// WIP
return errors.New("WIP")
}
func (administrator Administrator) deleteProject(project *Project) error {
// WIP
return errors.New("WIP")
}
func (administrator Administrator) changeUserRole(project *Project, user *User) error {
// WIP
return errors.New("WIP")
}
func (administrator *Administrator) login() error {
// WIP
return errors.New("WIP")
}
func (administrator *Administrator) logout() error {
// WIP
return errors.New("WIP")
}
type ProjectManager struct {
managedProjects map[string]Project // projekt som förvaltas av projektledaren
totalTime uint64 // total totalt tid arbetat av projektledaren
Account
ProjectMember // comp
}
// ProjectManager reciever functions
func (projectManager ProjectManager) signReport(timeReport *TimeReport, user User) error {
// WIP
return errors.New("WIP")
}
func (projectManager ProjectManager) unsignReport(timeReport *TimeReport, user User) error {
// WIP
return errors.New("WIP")
}
func (projectManager ProjectManager) getAllReports(project *Project) ([]TimeReport, error) {
// WIP
return project.timeReports, errors.New("WIP")
}
func (projectManager ProjectManager) assignRole(user *User, project *Project, newRole string) error {
// WIP
return errors.New("WIP")
}
func (projectManager ProjectManager) removeMember(project *Project, user *User) error {
// WIP
return errors.New("WIP")
}
func (projectManager ProjectManager) getTotalTime(project *Project) (uint64, error) {
// WIP
return 0, errors.New("WIP")
}
func (projectManager *ProjectManager) login() error {
// WIP
return errors.New("WIP")
}
func (projectManager *ProjectManager) logout() error {
// WIP
return errors.New("WIP")
}
type ProjectMember struct {
timereports []TimeReport
role string // ?????
Account // comp
}
// User reciever functions
// function used to create a time report, returning a *TimeReport is questionable
func (ProjectMember *ProjectMember) createTimeReport(Project *Project) (*TimeReport, error) {
// WIP
return &TimeReport{}, errors.New("WIP")
}
func (ProjectMember ProjectMember) getTimeReport(timereports *[]TimeReport) (*TimeReport, error) {
// WIP
return &TimeReport{}, errors.New("WIP")
}
func (ProjectMember *ProjectMember) editTimeReport(timereport *TimeReport) {
// timereport.editReport()
// WIP
}
func (projectUser ProjectMember) deleteTimeReport(timeReport *TimeReport) error { // Ska bara project manager kunna göra detta? fråga ledarna!
// WIP
return errors.New("WIP")
}
func (projectUser *ProjectMember) login() error {
// WIP
return errors.New("WIP")
}
func (projectUser *ProjectMember) logout() error {
// WIP
return errors.New("WIP")
}
type User interface {
login()
logout()
}

View file

@ -0,0 +1,21 @@
package types
import (
"time"
)
// Project is a struct that holds the information about a project
type Project struct {
ID int `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Description string `json:"description" db:"description"`
Owner string `json:"owner" db:"owner"`
Created time.Time `json:"created" db:"created"`
}
// As it arrives from the client
type NewProject struct {
Name string `json:"name"`
Description string `json:"description"`
Owner string `json:"owner"`
}

View file

@ -16,6 +16,11 @@ func (u *User) ToPublicUser() (*PublicUser, error) {
}, nil }, nil
} }
type NewUser struct {
Username string `json:"username"`
Password string `json:"password"`
}
// PublicUser represents a user that is safe to send over the API (no password) // PublicUser represents a user that is safe to send over the API (no password)
type PublicUser struct { type PublicUser struct {
UserId string `json:"userId"` UserId string `json:"userId"`