From c13378d3b964c85b77f7f1c467fd3c70a35a3ba3 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Sun, 17 Mar 2024 01:32:10 +0100 Subject: [PATCH 1/3] Proper login endpoint functionality --- backend/internal/database/db.go | 10 ++++++++++ backend/internal/handlers/global_state.go | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index 6b8a990..ef365cd 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -14,6 +14,7 @@ import ( type Database interface { // Insert a new user into the database, password should be hashed before calling AddUser(username string, password string) error + CheckUser(username string, password string) bool RemoveUser(username string) error PromoteToAdmin(username string) error GetUserId(username string) (int, error) @@ -77,6 +78,15 @@ func DbConnect(dbpath string) Database { return &Db{db} } +func (d *Db) CheckUser(username string, password string) bool { + var dbPassword string + err := d.Get(&dbPassword, "SELECT password FROM users WHERE username = ?", username) + if err != nil { + return false + } + return dbPassword == password +} + // GetProjectsForUser retrieves all projects associated with a specific user. func (d *Db) GetProjectsForUser(username string) ([]types.Project, error) { var projects []types.Project diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index f7172f5..648b4ed 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -110,8 +110,7 @@ func (gs *GState) Login(c *fiber.Ctx) error { user := c.FormValue("user") pass := c.FormValue("pass") - // Throws Unauthorized error - if user != "user" || pass != "pass" { + if !gs.Db.CheckUser(user, pass) { return c.SendStatus(fiber.StatusUnauthorized) } From 04d7a2cdeccd041bf0d07170a7f15287247bbb79 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Sun, 17 Mar 2024 01:55:24 +0100 Subject: [PATCH 2/3] Test script --- Makefile | 4 ++++ testing.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 testing.py diff --git a/Makefile b/Makefile index 668ccf1..97db62e 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,10 @@ clean: remove-podman-containers cd backend && make clean @echo "Cleaned up!" +.PHONY: itest +itest: + python testing.py + # Cleans up everything related to podman, not just the project. Make sure you understand what this means. podman-clean: podman system reset --force diff --git a/testing.py b/testing.py new file mode 100644 index 0000000..6394b94 --- /dev/null +++ b/testing.py @@ -0,0 +1,47 @@ +import requests +import string +import random + +def randomString(len=10): + """Generate a random string of fixed length """ + letters = string.ascii_lowercase + return ''.join(random.choice(letters) for i in range(len)) + +# Defined once per test run +username = randomString() + +# Define the base URL of the API +base_url = "http://localhost:8080" + +# Define the endpoint to test +registerPath = base_url + "/api/register" +loginPath = base_url + "/api/login" + +# Define a function to prform POST request with data and return response +def create_user(data): + response = requests.post(registerPath, json=data) + return response + +def login(username, password): + response = requests.post(loginPath, json={"username": username, "password": password}) + return response + +def test_login(): + response = login(username, "always_same") + assert response.status_code == 200, "Login failed" + print("Login successful") + print(response.json()["token"]) + +# Define a function to test the POST request +def test_create_user(): + data = {"username": username, "password": "always_same"} + response = create_user(data) + assert response.status_code == 200, "Registration failed" + print("Registration successful") + +# Run the tests +if __name__ == "__main__": + # test_get_users() + test_create_user() + test_login() + From 2e44d1437023411d7458b7ee2ad40dbe76db665d Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Sun, 17 Mar 2024 03:39:31 +0100 Subject: [PATCH 3/3] Extending test script --- backend/internal/handlers/global_state.go | 13 ++++-- testing.py | 56 +++++++++++++++++------ 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index 648b4ed..415b215 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -106,17 +106,20 @@ func (gs *GState) IncrementButtonCount(c *fiber.Ctx) error { // Login is a simple login handler that returns a JWT token func (gs *GState) Login(c *fiber.Ctx) error { - // To test: curl --data "user=user&pass=pass" http://localhost:8080/api/login - user := c.FormValue("user") - pass := c.FormValue("pass") + // The body type is identical to a NewUser + u := new(types.NewUser) + if err := c.BodyParser(u); err != nil { + return c.Status(400).SendString(err.Error()) + } - if !gs.Db.CheckUser(user, pass) { + if !gs.Db.CheckUser(u.Username, u.Password) { + println("User not found") return c.SendStatus(fiber.StatusUnauthorized) } // Create the Claims claims := jwt.MapClaims{ - "name": user, + "name": u.Username, "admin": false, "exp": time.Now().Add(time.Hour * 72).Unix(), } diff --git a/testing.py b/testing.py index 6394b94..fa97567 100644 --- a/testing.py +++ b/testing.py @@ -2,46 +2,74 @@ import requests import string import random + def randomString(len=10): - """Generate a random string of fixed length """ + """Generate a random string of fixed length""" letters = string.ascii_lowercase - return ''.join(random.choice(letters) for i in range(len)) + return "".join(random.choice(letters) for i in range(len)) + # Defined once per test run username = randomString() +token = None -# Define the base URL of the API +# The base URL of the API base_url = "http://localhost:8080" -# Define the endpoint to test +# Endpoint to test registerPath = base_url + "/api/register" loginPath = base_url + "/api/login" +addProjectPath = base_url + "/api/project" + # Define a function to prform POST request with data and return response -def create_user(data): - response = requests.post(registerPath, json=data) +def register(username: string, password: string): + print("Registering with username: ", username, " and password: ", password) + response = requests.post( + registerPath, json={"username": username, "password": password} + ) + print(response.text) return response -def login(username, password): - response = requests.post(loginPath, json={"username": username, "password": password}) + +def login(username: string, password: string): + print("Logging in with username: ", username, " and password: ", password) + response = requests.post( + loginPath, json={"username": username, "password": password} + ) + print(response.text) return response + def test_login(): response = login(username, "always_same") assert response.status_code == 200, "Login failed" print("Login successful") - print(response.json()["token"]) + return response.json()["token"] + # Define a function to test the POST request def test_create_user(): - data = {"username": username, "password": "always_same"} - response = create_user(data) + response = register(username, "always_same") assert response.status_code == 200, "Registration failed" print("Registration successful") -# Run the tests + +def test_add_project(): + loginResponse = login(username, "always_same") + token = loginResponse.json()["token"] + projectName = randomString() + response = requests.post( + addProjectPath, + json={"name": projectName, "description": "This is a project"}, + headers={"Authorization": "Bearer " + token}, + ) + print(response.text) + assert response.status_code == 200, "Add project failed" + print("Add project successful") + + if __name__ == "__main__": - # test_get_users() test_create_user() test_login() - + test_add_project()