From 848cab106eb494c8cef6a30295466776a270dfde Mon Sep 17 00:00:00 2001 From: Unbewohnte Date: Mon, 18 Sep 2023 20:16:43 +0300 Subject: [PATCH] feat: implemented complete TODO button --- pages/index.html | 26 +++++++++++++--------- scripts/api.js | 5 ++--- src/conf/conf.go | 4 ++-- src/main.go | 2 -- src/server/api.go | 50 ++++++++++++------------------------------ src/server/api_test.go | 4 ++-- src/server/page.go | 4 +--- src/server/server.go | 20 +++++------------ 8 files changed, 43 insertions(+), 72 deletions(-) diff --git a/pages/index.html b/pages/index.html index bde1bd0..cad04df 100644 --- a/pages/index.html +++ b/pages/index.html @@ -209,23 +209,29 @@ document.addEventListener('DOMContentLoaded', async function() { // Fetch and display TODOs response = await get_todos(username, password); let todosJson = await response.json(); + let todos = []; + let completeButtonIDs = []; if (response.ok && todosJson != null) { let todosDiv = document.getElementById("todos"); todosJson.forEach((item) => { console.log(item); - - let todo_complete_btn_id = "btn-complete-" + String(item.id); + todos.push(item); + let todoCompleteBtnID = "btn-complete-" + String(item.id); todosDiv.innerHTML += "

" + item.text + - "

"; - - document.getElementById(todo_complete_btn_id).addEventListener("click", async (event) => { - response = await delete_todo(username, password, item); - if (response.ok) { - location.reload(); - } - }); + + completeButtonIDs.push(todoCompleteBtnID); + }); + } + + for (let i = 0; i < completeButtonIDs.length; i++) { + document.getElementById(completeButtonIDs[i]).addEventListener("click", async (event) => { + response = await delete_todo(username, password, todos[i].id); + if (response.ok) { + location.reload(); + } }); } }, false) diff --git a/scripts/api.js b/scripts/api.js index 9221728..f76474b 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -37,13 +37,12 @@ async function get_todo_groups(username, password) { }); } -async function delete_todo(username, password, todo) { - return fetch("/api/todo", { +async function delete_todo(username, password, id) { + return fetch("/api/todo/"+String(id), { method: "DELETE", headers: { "EnctyptedBase64": "false", "Auth": username + "<-->" + password, - body: JSON.stringify(todo), }, }); } diff --git a/src/conf/conf.go b/src/conf/conf.go index c8394aa..e90fc7b 100644 --- a/src/conf/conf.go +++ b/src/conf/conf.go @@ -11,7 +11,7 @@ type Conf struct { CertFilePath string `json:"cert_file_path"` KeyFilePath string `json:"key_file_path"` BaseContentDir string `json:"base_content_dir"` - ProdDBPath string `json:"production_db"` + ProdDBName string `json:"production_db_name"` } // Creates a default server configuration @@ -21,7 +21,7 @@ func Default() Conf { CertFilePath: "", KeyFilePath: "", BaseContentDir: ".", - ProdDBPath: "dela.db", + ProdDBName: "dela.db", } } diff --git a/src/main.go b/src/main.go index 66f8d8f..23c7718 100644 --- a/src/main.go +++ b/src/main.go @@ -44,8 +44,6 @@ func init() { Conf.BaseContentDir = WDir } - // Check if database exists and create it otherwise - logger.Info("[Init] Successful initializaion!") } diff --git a/src/server/api.go b/src/server/api.go index 37250e3..3fffb21 100644 --- a/src/server/api.go +++ b/src/server/api.go @@ -6,6 +6,8 @@ import ( "encoding/json" "io" "net/http" + "path" + "strconv" "time" ) @@ -15,23 +17,6 @@ func (s *Server) UserEndpoint(w http.ResponseWriter, req *http.Request) { // Delete an existing user defer req.Body.Close() - // Read body - body, err := io.ReadAll(req.Body) - if err != nil { - logger.Warning("[Server] Failed to read request body to delete a user: %s", err) - http.Error(w, "Failed to read body", http.StatusInternalServerError) - return - } - - // Unmarshal JSON - var newUser db.User - err = json.Unmarshal(body, &newUser) - if err != nil { - logger.Warning("[Server] Received invalid user JSON for deletion: %s", err) - http.Error(w, "Invalid user JSON", http.StatusBadRequest) - return - } - username := GetUsernameFromAuth(req) // Check if auth data is valid @@ -43,7 +28,7 @@ func (s *Server) UserEndpoint(w http.ResponseWriter, req *http.Request) { // It is, indeed, a user // Delete with all TODOs - err = s.db.DeleteUserClean(username) + err := s.db.DeleteUserClean(username) if err != nil { logger.Error("[Server] Failed to delete %s: %s", username, err) http.Error(w, "Failed to delete user or TODO contents", http.StatusInternalServerError) @@ -127,36 +112,28 @@ func (s *Server) TodoEndpoint(w http.ResponseWriter, req *http.Request) { // Delete an existing TODO defer req.Body.Close() - // Read body - body, err := io.ReadAll(req.Body) - if err != nil { - logger.Warning("[Server] Failed to read request body to possibly delete a TODO: %s", err) - http.Error(w, "Failed to read body", http.StatusInternalServerError) + // Check if this user actually exists and the password is valid + if !IsRequestAuthValid(req, s.db) { + http.Error(w, "Invalid user auth data", http.StatusForbidden) return } - // Unmarshal JSON - var todo db.Todo - err = json.Unmarshal(body, &todo) + // Obtain TODO ID + todoIDStr := path.Base(req.URL.Path) + todoID, err := strconv.ParseUint(todoIDStr, 10, 64) if err != nil { - logger.Warning("[Server] Received invalid TODO JSON for deletion: %s", err) - http.Error(w, "Invalid TODO JSON", http.StatusBadRequest) - return - } - - // Check if given user actually owns this TODO - if !IsRequestAuthValid(req, s.db) { - http.Error(w, "Invalid user auth data", http.StatusForbidden) + http.Error(w, "Invalid TODO ID", http.StatusBadRequest) return } - if !DoesUserOwnTodo(GetUsernameFromAuth(req), todo.ID, s.db) { + // Check if the user owns this TODO + if !DoesUserOwnTodo(GetUsernameFromAuth(req), todoID, s.db) { http.Error(w, "You don't own this TODO", http.StatusForbidden) return } // Now delete - err = s.db.DeleteTodo(todo.ID) + err = s.db.DeleteTodo(todoID) if err != nil { logger.Error("[Server] Failed to delete %s's TODO: %s", GetUsernameFromAuth(req), err) http.Error(w, "Failed to delete TODO", http.StatusInternalServerError) @@ -164,6 +141,7 @@ func (s *Server) TodoEndpoint(w http.ResponseWriter, req *http.Request) { } // Success! + logger.Info("[Server] deleted TODO with ID %d", todoID) w.WriteHeader(http.StatusOK) case http.MethodPost: diff --git a/src/server/api_test.go b/src/server/api_test.go index 7e541c9..345e503 100644 --- a/src/server/api_test.go +++ b/src/server/api_test.go @@ -18,12 +18,12 @@ func TestApi(t *testing.T) { // Create a new server config := conf.Default() config.BaseContentDir = "../../" - config.ProdDBPath = filepath.Join(os.TempDir(), "dela_test_db.db") + config.ProdDBName = filepath.Join(os.TempDir(), "dela_test_db.db") server, err := New(config) if err != nil { t.Fatalf("failed to create a new server: %s", err) } - defer os.Remove(config.ProdDBPath) + defer os.Remove(config.ProdDBName) go func() { time.Sleep(time.Second * 5) diff --git a/src/server/page.go b/src/server/page.go index c8eef4c..22a9570 100644 --- a/src/server/page.go +++ b/src/server/page.go @@ -1,7 +1,6 @@ package server import ( - "Unbewohnte/dela/logger" "html/template" "path/filepath" ) @@ -13,9 +12,8 @@ func getPage(pagesDir string, basePageName string, pageName string) (*template.T filepath.Join(pagesDir, pageName), ) if err != nil { - logger.Error("Failed to parse page files (pagename is \"%s\"): %s", pageName, err) return nil, err } return page, nil -} \ No newline at end of file +} diff --git a/src/server/server.go b/src/server/server.go index d2f8e61..c0d6500 100644 --- a/src/server/server.go +++ b/src/server/server.go @@ -49,10 +49,10 @@ func New(config conf.Conf) (*Server, error) { } // get database working - serverDB, err := db.FromFile(config.ProdDBPath) + serverDB, err := db.FromFile(filepath.Join(config.BaseContentDir, config.ProdDBName)) if err != nil { // Create one then - serverDB, err = db.Create(config.ProdDBPath) + serverDB, err = db.Create(filepath.Join(config.BaseContentDir, config.ProdDBName)) if err != nil { logger.Error("Failed to create a new database: %s", err) return nil, err @@ -95,7 +95,7 @@ func New(config conf.Conf) (*Server, error) { filepath.Join(server.config.BaseContentDir, PagesDirName), "base.html", "index.html", ) if err != nil { - http.Error(w, "Internal server error", http.StatusInternalServerError) + http.Error(w, "Page processing error", http.StatusInternalServerError) } requestedPage.ExecuteTemplate(w, "index.html", nil) @@ -109,22 +109,14 @@ func New(config conf.Conf) (*Server, error) { if err == nil { requestedPage.ExecuteTemplate(w, req.URL.Path[1:]+".html", nil) } else { - // Redirect to the index - index, err := getPage( - filepath.Join(server.config.BaseContentDir, PagesDirName), - "base.html", - req.URL.Path[1:]+".html", - ) - if err != nil { - http.Error(w, "Internal server error", http.StatusInternalServerError) - } - - index.ExecuteTemplate(w, "index.html", nil) + http.Error(w, "Page processing error", http.StatusInternalServerError) } } }) mux.HandleFunc("/api/user", server.UserEndpoint) mux.HandleFunc("/api/todo", server.TodoEndpoint) + mux.HandleFunc("/api/todo/", server.TodoEndpoint) + // mux.HandleFunc("/api/group", server.TodoGroupEndpoint) server.http.Handler = mux