Compare commits
4 commits
ad4d439887
...
25fdf3bb9b
Author | SHA1 | Date | |
---|---|---|---|
|
25fdf3bb9b | ||
|
c4632104a8 | ||
|
736cebe036 | ||
|
9b67a580da |
8 changed files with 76 additions and 164 deletions
|
@ -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)
|
||||||
|
|
|
@ -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);
|
16
backend/internal/database/migrations/0070_salts.sql
Normal file
16
backend/internal/database/migrations/0070_salts.sql
Normal 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;
|
|
@ -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")
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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()
|
|
||||||
}
|
|
21
backend/internal/types/project.go
Normal file
21
backend/internal/types/project.go
Normal 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"`
|
||||||
|
}
|
|
@ -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"`
|
||||||
|
|
Loading…
Reference in a new issue