Compare commits
	
		
			18 commits
		
	
	
		
			1a412dc8a0
			...
			5696310a68
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
							 | 
						5696310a68 | ||
| 
							 | 
						40caa2d158 | ||
| 
							 | 
						37bbbb6098 | ||
| 
							 | 
						e03727613d | ||
| 
							 | 
						8a34fc07fa | ||
| 
							 | 
						b93df693d2 | ||
| 
							 | 
						447f2b73eb | ||
| 
							 | 
						3683552af8 | ||
| 
							 | 
						c7fe5e8775 | ||
| 
							 | 
						402b0ac08b | ||
| 
							 | 
						9240d5e052 | ||
| 
							 | 
						1977125923 | ||
| 
							 | 
						b999e47f94 | ||
| 
							 | 
						e7e79ced13 | ||
| 
							 | 
						141e5c8bb6 | ||
| 
							 | 
						b7fcafd75c | ||
| 
							 | 
						060dc1ee3d | ||
| 
							 | 
						79eb59ad46 | 
					 10 changed files with 228 additions and 39 deletions
				
			
		| 
						 | 
					@ -2,6 +2,7 @@ package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"embed"
 | 
						"embed"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"ttime/internal/types"
 | 
						"ttime/internal/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +31,7 @@ type Database interface {
 | 
				
			||||||
	GetProject(projectId int) (types.Project, error)
 | 
						GetProject(projectId int) (types.Project, error)
 | 
				
			||||||
	GetUserRole(username string, projectname string) (string, error)
 | 
						GetUserRole(username string, projectname string) (string, error)
 | 
				
			||||||
	GetWeeklyReport(username string, projectName string, week int) (types.WeeklyReport, error)
 | 
						GetWeeklyReport(username string, projectName string, week int) (types.WeeklyReport, error)
 | 
				
			||||||
 | 
						SignWeeklyReport(reportId int, projectManagerId int) error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This struct is a wrapper type that holds the database connection
 | 
					// This struct is a wrapper type that holds the database connection
 | 
				
			||||||
| 
						 | 
					@ -270,7 +272,8 @@ func (d *Db) GetWeeklyReport(username string, projectName string, week int) (typ
 | 
				
			||||||
            admin_time,
 | 
					            admin_time,
 | 
				
			||||||
            own_work_time,
 | 
					            own_work_time,
 | 
				
			||||||
            study_time,
 | 
					            study_time,
 | 
				
			||||||
            testing_time
 | 
					            testing_time,
 | 
				
			||||||
 | 
								signed_by
 | 
				
			||||||
        FROM
 | 
					        FROM
 | 
				
			||||||
            weekly_reports
 | 
					            weekly_reports
 | 
				
			||||||
        WHERE
 | 
					        WHERE
 | 
				
			||||||
| 
						 | 
					@ -282,6 +285,34 @@ func (d *Db) GetWeeklyReport(username string, projectName string, week int) (typ
 | 
				
			||||||
	return report, err
 | 
						return report, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SignWeeklyReport signs a weekly report by updating the signed_by field
 | 
				
			||||||
 | 
					// with the provided project manager's ID, but only if the project manager
 | 
				
			||||||
 | 
					// is in the same project as the report
 | 
				
			||||||
 | 
					func (d *Db) SignWeeklyReport(reportId int, projectManagerId int) error {
 | 
				
			||||||
 | 
						// Retrieve the project ID associated with the report
 | 
				
			||||||
 | 
						var reportProjectID int
 | 
				
			||||||
 | 
						err := d.Get(&reportProjectID, "SELECT project_id FROM weekly_reports WHERE report_id = ?", reportId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Retrieve the project ID associated with the project manager
 | 
				
			||||||
 | 
						var managerProjectID int
 | 
				
			||||||
 | 
						err = d.Get(&managerProjectID, "SELECT project_id FROM user_roles WHERE user_id = ? AND p_role = 'project_manager'", projectManagerId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if the project manager is in the same project as the report
 | 
				
			||||||
 | 
						if reportProjectID != managerProjectID {
 | 
				
			||||||
 | 
							return errors.New("project manager doesn't have permission to sign the report")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Update the signed_by field of the specified report
 | 
				
			||||||
 | 
						_, err = d.Exec("UPDATE weekly_reports SET signed_by = ? WHERE report_id = ?", projectManagerId, reportId)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Reads a directory of migration files and applies them to the database.
 | 
					// Reads a directory of migration files and applies them to the database.
 | 
				
			||||||
// This will eventually be used on an embedded directory
 | 
					// This will eventually be used on an embedded directory
 | 
				
			||||||
func (d *Db) Migrate() error {
 | 
					func (d *Db) Migrate() error {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
package database
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -410,3 +411,128 @@ func TestGetWeeklyReport(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Check other fields similarly
 | 
						// Check other fields similarly
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSignWeeklyReport(t *testing.T) {
 | 
				
			||||||
 | 
						db, err := setupState()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("setupState failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add project manager
 | 
				
			||||||
 | 
						err = db.AddUser("projectManager", "password")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddUser failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add a regular user
 | 
				
			||||||
 | 
						err = db.AddUser("testuser", "password")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddUser failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add project
 | 
				
			||||||
 | 
						err = db.AddProject("testproject", "description", "projectManager")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddProject failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add both regular users as members to the project
 | 
				
			||||||
 | 
						err = db.AddUserToProject("testuser", "testproject", "member")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddUserToProject failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = db.AddUserToProject("projectManager", "testproject", "project_manager")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddUserToProject failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add a weekly report for one of the regular users
 | 
				
			||||||
 | 
						err = db.AddWeeklyReport("testproject", "testuser", 1, 1, 1, 1, 1, 1, 1)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddWeeklyReport failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Retrieve the added report
 | 
				
			||||||
 | 
						report, err := db.GetWeeklyReport("testuser", "testproject", 1)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("GetWeeklyReport failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Print project manager's ID
 | 
				
			||||||
 | 
						projectManagerID, err := db.GetUserId("projectManager")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("GetUserId failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Println("Project Manager's ID:", projectManagerID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Sign the report with the project manager
 | 
				
			||||||
 | 
						err = db.SignWeeklyReport(report.ReportId, projectManagerID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("SignWeeklyReport failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Retrieve the report again to check if it's signed
 | 
				
			||||||
 | 
						signedReport, err := db.GetWeeklyReport("testuser", "testproject", 1)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("GetWeeklyReport failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Ensure the report is signed by the project manager
 | 
				
			||||||
 | 
						if *signedReport.SignedBy != projectManagerID {
 | 
				
			||||||
 | 
							t.Errorf("Expected SignedBy to be %d, got %d", projectManagerID, *signedReport.SignedBy)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSignWeeklyReportByAnotherProjectManager(t *testing.T) {
 | 
				
			||||||
 | 
						db, err := setupState()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("setupState failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add project manager
 | 
				
			||||||
 | 
						err = db.AddUser("projectManager", "password")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddUser failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add a regular user
 | 
				
			||||||
 | 
						err = db.AddUser("testuser", "password")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddUser failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add project
 | 
				
			||||||
 | 
						err = db.AddProject("testproject", "description", "projectManager")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddProject failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add the regular user as a member to the project
 | 
				
			||||||
 | 
						err = db.AddUserToProject("testuser", "testproject", "member")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddUserToProject failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add a weekly report for the regular user
 | 
				
			||||||
 | 
						err = db.AddWeeklyReport("testproject", "testuser", 1, 1, 1, 1, 1, 1, 1)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("AddWeeklyReport failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Retrieve the added report
 | 
				
			||||||
 | 
						report, err := db.GetWeeklyReport("testuser", "testproject", 1)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("GetWeeklyReport failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						anotherManagerID, err := db.GetUserId("projectManager")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Error("GetUserId failed:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = db.SignWeeklyReport(report.ReportId, anotherManagerID)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							t.Error("Expected SignWeeklyReport to fail with a project manager who is not in the project, but it didn't")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
CREATE TABLE weekly_reports (
 | 
					CREATE TABLE IF NOT EXISTS weekly_reports (
 | 
				
			||||||
  report_id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
					  report_id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
				
			||||||
  user_id INTEGER NOT NULL,
 | 
					  user_id INTEGER NOT NULL,
 | 
				
			||||||
  project_id INTEGER NOT NULL,
 | 
					  project_id INTEGER NOT NULL,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,13 +22,16 @@ import (
 | 
				
			||||||
func (gs *GState) Register(c *fiber.Ctx) error {
 | 
					func (gs *GState) Register(c *fiber.Ctx) error {
 | 
				
			||||||
	u := new(types.NewUser)
 | 
						u := new(types.NewUser)
 | 
				
			||||||
	if err := c.BodyParser(u); err != nil {
 | 
						if err := c.BodyParser(u); err != nil {
 | 
				
			||||||
 | 
							println("Error parsing body")
 | 
				
			||||||
		return c.Status(400).SendString(err.Error())
 | 
							return c.Status(400).SendString(err.Error())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						println("Adding user:", u.Username)
 | 
				
			||||||
	if err := gs.Db.AddUser(u.Username, u.Password); err != nil {
 | 
						if err := gs.Db.AddUser(u.Username, u.Password); err != nil {
 | 
				
			||||||
		return c.Status(500).SendString(err.Error())
 | 
							return c.Status(500).SendString(err.Error())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						println("User added:", u.Username)
 | 
				
			||||||
	return c.Status(200).SendString("User added")
 | 
						return c.Status(200).SendString("User added")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,9 +60,11 @@ func (gs *GState) Login(c *fiber.Ctx) error {
 | 
				
			||||||
	// The body type is identical to a NewUser
 | 
						// The body type is identical to a NewUser
 | 
				
			||||||
	u := new(types.NewUser)
 | 
						u := new(types.NewUser)
 | 
				
			||||||
	if err := c.BodyParser(u); err != nil {
 | 
						if err := c.BodyParser(u); err != nil {
 | 
				
			||||||
 | 
							println("Error parsing body")
 | 
				
			||||||
		return c.Status(400).SendString(err.Error())
 | 
							return c.Status(400).SendString(err.Error())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						println("Username:", u.Username)
 | 
				
			||||||
	if !gs.Db.CheckUser(u.Username, u.Password) {
 | 
						if !gs.Db.CheckUser(u.Username, u.Password) {
 | 
				
			||||||
		println("User not found")
 | 
							println("User not found")
 | 
				
			||||||
		return c.SendStatus(fiber.StatusUnauthorized)
 | 
							return c.SendStatus(fiber.StatusUnauthorized)
 | 
				
			||||||
| 
						 | 
					@ -74,13 +79,16 @@ func (gs *GState) Login(c *fiber.Ctx) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create token
 | 
						// Create token
 | 
				
			||||||
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
 | 
						token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
 | 
				
			||||||
 | 
						println("Token created for user:", u.Username)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Generate encoded token and send it as response.
 | 
						// Generate encoded token and send it as response.
 | 
				
			||||||
	t, err := token.SignedString([]byte("secret"))
 | 
						t, err := token.SignedString([]byte("secret"))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							println("Error signing token")
 | 
				
			||||||
		return c.SendStatus(fiber.StatusInternalServerError)
 | 
							return c.SendStatus(fiber.StatusInternalServerError)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						println("Successfully signed token for user:", u.Username)
 | 
				
			||||||
	return c.JSON(fiber.Map{"token": t})
 | 
						return c.JSON(fiber.Map{"token": t})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,4 +41,6 @@ type WeeklyReport struct {
 | 
				
			||||||
	StudyTime int `json:"studyTime" db:"study_time"`
 | 
						StudyTime int `json:"studyTime" db:"study_time"`
 | 
				
			||||||
	// Total time spent on testing
 | 
						// Total time spent on testing
 | 
				
			||||||
	TestingTime int `json:"testingTime" db:"testing_time"`
 | 
						TestingTime int `json:"testingTime" db:"testing_time"`
 | 
				
			||||||
 | 
						// The project manager who signed it
 | 
				
			||||||
 | 
						SignedBy *int `json:"signedBy" db:"signed_by"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,8 @@ describe("API", () => {
 | 
				
			||||||
      username: "lol", // Add the username property
 | 
					      username: "lol", // Add the username property
 | 
				
			||||||
      password: "lol",
 | 
					      password: "lol",
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					 | 
				
			||||||
    const response = await api.registerUser(user);
 | 
					    const response = await api.registerUser(user);
 | 
				
			||||||
 | 
					    console.log(response.message);
 | 
				
			||||||
    expect(response.success).toBe(true);
 | 
					    expect(response.success).toBe(true);
 | 
				
			||||||
    expect(response.data).toHaveProperty("userId");
 | 
					    expect(response.data).toHaveProperty("userId");
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
| 
						 | 
					@ -24,7 +23,7 @@ describe("API", () => {
 | 
				
			||||||
      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsImV4cCI6MTcxMDk0MDIwMywibmFtZSI6InJyZ3VtZHpwbWMifQ.V9NHoYMYV61t";
 | 
					      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsImV4cCI6MTcxMDk0MDIwMywibmFtZSI6InJyZ3VtZHpwbWMifQ.V9NHoYMYV61t";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const response = await api.createProject(project, token);
 | 
					    const response = await api.createProject(project, token);
 | 
				
			||||||
 | 
					    console.log(response.message);
 | 
				
			||||||
    expect(response.success).toBe(true);
 | 
					    expect(response.success).toBe(true);
 | 
				
			||||||
    expect(response.data).toHaveProperty("projectId");
 | 
					    expect(response.data).toHaveProperty("projectId");
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
| 
						 | 
					@ -34,7 +33,7 @@ describe("API", () => {
 | 
				
			||||||
      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsImV4cCI6MTcxMDk0MDIwMywibmFtZSI6InJyZ3VtZHpwbWMifQ.V9NHoYMYV61t";
 | 
					      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsImV4cCI6MTcxMDk0MDIwMywibmFtZSI6InJyZ3VtZHpwbWMifQ.V9NHoYMYV61t";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const response = await api.renewToken(refreshToken);
 | 
					    const response = await api.renewToken(refreshToken);
 | 
				
			||||||
 | 
					    console.log(response.message);
 | 
				
			||||||
    expect(response.success).toBe(true);
 | 
					    expect(response.success).toBe(true);
 | 
				
			||||||
    expect(response.data).toHaveProperty("accessToken");
 | 
					    expect(response.data).toHaveProperty("accessToken");
 | 
				
			||||||
    expect(response.data).toHaveProperty("refreshToken");
 | 
					    expect(response.data).toHaveProperty("refreshToken");
 | 
				
			||||||
| 
						 | 
					@ -45,7 +44,7 @@ describe("API", () => {
 | 
				
			||||||
      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsImV4cCI6MTcxMDk0MDIwMywibmFtZSI6InJyZ3VtZHpwbWMifQ.V9NHoYMYV61t";
 | 
					      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsImV4cCI6MTcxMDk0MDIwMywibmFtZSI6InJyZ3VtZHpwbWMifQ.V9NHoYMYV61t";
 | 
				
			||||||
    const username = "rrgumdzpmc";
 | 
					    const username = "rrgumdzpmc";
 | 
				
			||||||
    const response = await api.getUserProjects(username, token);
 | 
					    const response = await api.getUserProjects(username, token);
 | 
				
			||||||
 | 
					    console.log(response.message);
 | 
				
			||||||
    expect(response.success).toBe(true);
 | 
					    expect(response.success).toBe(true);
 | 
				
			||||||
    expect(response.data).toHaveProperty("projects");
 | 
					    expect(response.data).toHaveProperty("projects");
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
| 
						 | 
					@ -65,7 +64,7 @@ describe("API", () => {
 | 
				
			||||||
      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsImV4cCI6MTcxMDk0MDIwMywibmFtZSI6InJyZ3VtZHpwbWMifQ.V9NHoYMYV61t";
 | 
					      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsImV4cCI6MTcxMDk0MDIwMywibmFtZSI6InJyZ3VtZHpwbWMifQ.V9NHoYMYV61t";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const response = await api.submitWeeklyReport(report, token);
 | 
					    const response = await api.submitWeeklyReport(report, token);
 | 
				
			||||||
 | 
					    console.log(response.message);
 | 
				
			||||||
    expect(response.success).toBe(true);
 | 
					    expect(response.success).toBe(true);
 | 
				
			||||||
    expect(response.data).toHaveProperty(
 | 
					    expect(response.data).toHaveProperty(
 | 
				
			||||||
      "message",
 | 
					      "message",
 | 
				
			||||||
| 
						 | 
					@ -80,7 +79,7 @@ describe("API", () => {
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const response = await api.login(user);
 | 
					    const response = await api.login(user);
 | 
				
			||||||
 | 
					    console.log(response.message);
 | 
				
			||||||
    expect(response.success).toBe(true);
 | 
					    expect(response.success).toBe(true);
 | 
				
			||||||
    expect(response.data).toHaveProperty("accessToken");
 | 
					    expect(response.data).toHaveProperty("accessToken");
 | 
				
			||||||
    expect(response.data).toHaveProperty("refreshToken");
 | 
					    expect(response.data).toHaveProperty("refreshToken");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ import {
 | 
				
			||||||
} from "../Types/goTypes";
 | 
					} from "../Types/goTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This type of pattern should be hard to misuse
 | 
					// This type of pattern should be hard to misuse
 | 
				
			||||||
interface APIResponse<T> {
 | 
					export interface APIResponse<T> {
 | 
				
			||||||
  success: boolean;
 | 
					  success: boolean;
 | 
				
			||||||
  message?: string;
 | 
					  message?: string;
 | 
				
			||||||
  data?: T;
 | 
					  data?: T;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,34 +1,54 @@
 | 
				
			||||||
import { NewUser } from "../Types/goTypes";
 | 
					import { NewUser } from "../Types/goTypes";
 | 
				
			||||||
 | 
					import { api, APIResponse } from "../API/API";
 | 
				
			||||||
 | 
					import { Dispatch, SetStateAction } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function LoginCheck(props: { username: string; password: string }): number {
 | 
					/*
 | 
				
			||||||
  //Example users for testing without backend, remove when using backend
 | 
					 * Checks if user is in database with api.login and then sets proper authority level
 | 
				
			||||||
  const admin: NewUser = {
 | 
					 * TODO: change so that it checks for user type (admin, user, pm) somehow instead
 | 
				
			||||||
    username: "admin",
 | 
					 **/
 | 
				
			||||||
    password: "123",
 | 
					function LoginCheck(props: {
 | 
				
			||||||
  };
 | 
					  username: string;
 | 
				
			||||||
  const pmanager: NewUser = {
 | 
					  password: string;
 | 
				
			||||||
    username: "pmanager",
 | 
					  setAuthority: Dispatch<SetStateAction<number>>;
 | 
				
			||||||
    password: "123",
 | 
					}): number {
 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  const user: NewUser = {
 | 
					  const user: NewUser = {
 | 
				
			||||||
    username: "user",
 | 
					    username: props.username,
 | 
				
			||||||
    password: "123",
 | 
					    password: props.password,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					  api
 | 
				
			||||||
 | 
					    .login(user)
 | 
				
			||||||
 | 
					    .then((response: APIResponse<string>) => {
 | 
				
			||||||
 | 
					      if (response.success) {
 | 
				
			||||||
 | 
					        if (response.data !== undefined) {
 | 
				
			||||||
 | 
					          const token = response.data;
 | 
				
			||||||
 | 
					          //TODO: change so that it checks for user type (admin, user, pm) instead
 | 
				
			||||||
 | 
					          if (token !== "" && props.username === "admin") {
 | 
				
			||||||
 | 
					            props.setAuthority((prevAuth) => {
 | 
				
			||||||
 | 
					              prevAuth = 1;
 | 
				
			||||||
 | 
					              return prevAuth;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          } else if (token !== "" && props.username === "pm") {
 | 
				
			||||||
 | 
					            props.setAuthority((prevAuth) => {
 | 
				
			||||||
 | 
					              prevAuth = 2;
 | 
				
			||||||
 | 
					              return prevAuth;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          } else if (token !== "" && props.username === "user") {
 | 
				
			||||||
 | 
					            props.setAuthority((prevAuth) => {
 | 
				
			||||||
 | 
					              prevAuth = 3;
 | 
				
			||||||
 | 
					              return prevAuth;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          console.error("Token was undefined");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        console.error("Token could not be fetched");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .catch((error) => {
 | 
				
			||||||
 | 
					      console.error("An error occurred during login:", error);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //TODO: Compare with db instead when finished
 | 
					 | 
				
			||||||
  if (props.username === admin.username && props.password === admin.password) {
 | 
					 | 
				
			||||||
    return 1;
 | 
					 | 
				
			||||||
  } else if (
 | 
					 | 
				
			||||||
    props.username === pmanager.username &&
 | 
					 | 
				
			||||||
    props.password === pmanager.password
 | 
					 | 
				
			||||||
  ) {
 | 
					 | 
				
			||||||
    return 2;
 | 
					 | 
				
			||||||
  } else if (
 | 
					 | 
				
			||||||
    props.username === user.username &&
 | 
					 | 
				
			||||||
    props.password === user.password
 | 
					 | 
				
			||||||
  ) {
 | 
					 | 
				
			||||||
    return 3;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,9 +15,10 @@ function LoginPage(props: {
 | 
				
			||||||
   and if so, redirect to correct page */
 | 
					   and if so, redirect to correct page */
 | 
				
			||||||
  function handleSubmit(event: FormEvent<HTMLFormElement>): void {
 | 
					  function handleSubmit(event: FormEvent<HTMLFormElement>): void {
 | 
				
			||||||
    event.preventDefault();
 | 
					    event.preventDefault();
 | 
				
			||||||
    props.setAuthority((prevAuth) => {
 | 
					    LoginCheck({
 | 
				
			||||||
      prevAuth = LoginCheck({ username: username, password: password });
 | 
					      username: username,
 | 
				
			||||||
      return prevAuth;
 | 
					      password: password,
 | 
				
			||||||
 | 
					      setAuthority: props.setAuthority,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ function PMProjectMembers(): JSX.Element {
 | 
				
			||||||
          onClick={(): void => {
 | 
					          onClick={(): void => {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
 | 
					          type={"button"}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      </Link>
 | 
					      </Link>
 | 
				
			||||||
      <Link to="/PM-time-role">
 | 
					      <Link to="/PM-time-role">
 | 
				
			||||||
| 
						 | 
					@ -22,6 +23,7 @@ function PMProjectMembers(): JSX.Element {
 | 
				
			||||||
          onClick={(): void => {
 | 
					          onClick={(): void => {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
 | 
					          type={"button"}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      </Link>
 | 
					      </Link>
 | 
				
			||||||
      <BackButton />
 | 
					      <BackButton />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue