diff --git a/Go/auth/auth.go b/Go/auth/auth.go index f487b6c22050ea8d035e774f29832b2734dedeec..2ba8ef4d4d52c6c8125f86cfe370bea09ee99473 100644 --- a/Go/auth/auth.go +++ b/Go/auth/auth.go @@ -5,7 +5,6 @@ import ( firebase "firebase.google.com/go" "firebase.google.com/go/auth" "google.golang.org/api/option" - "log" "os" ) @@ -19,16 +18,12 @@ func GetFireBaseAuthClient() (*auth.Client, error) { sa := option.WithCredentialsFile(os.Getenv("FIREBASE_CREDENTIALS_FILE")) app, err := firebase.NewApp(ctx, nil, sa) if err != nil { - log.Println("Credentials not found: " + os.Getenv("FIREBASE_CREDENTIALS_FILE")) - log.Println("Error on getting the application") return nil, err } //No initial error, so a client is used to gather other information client, err := app.Auth(ctx) if err != nil { - // Logging the error - log.Println("Credentials file: '" + os.Getenv("FIREBASE_CREDENTIALS_FILE") + "' lead to an error.") return nil, err } diff --git a/Go/cmd/globeboard/app.go b/Go/cmd/globeboard/app.go index c384d3933c7be683be8e20df2448eacd260feaa5..d44c928972366b9bb07264811bff69ee55c6e96e 100644 --- a/Go/cmd/globeboard/app.go +++ b/Go/cmd/globeboard/app.go @@ -37,11 +37,11 @@ func main() { mux := http.NewServeMux() mux.HandleFunc(Paths.Root, handlers.EmptyHandler) mux.HandleFunc(Endpoints.UserRegistration, util.UserRegistrationHandler) - mux.HandleFunc(Endpoints.UserDeletion, util.UserDeletionHandler) + mux.HandleFunc(Endpoints.UserDeletionId, util.UserDeletionHandler) mux.HandleFunc(Endpoints.ApiKey, util.APIKeyHandler) mux.HandleFunc(Endpoints.RegistrationsID, dashboard.RegistrationsIdHandler) mux.HandleFunc(Endpoints.Registrations, dashboard.RegistrationsHandler) - mux.HandleFunc(Endpoints.Dashboards, dashboard.DashboardsHandler) + mux.HandleFunc(Endpoints.DashboardsID, dashboard.DashboardsIdHandler) mux.HandleFunc(Endpoints.NotificationsID, dashboard.NotificationsIdHandler) mux.HandleFunc(Endpoints.Notifications, dashboard.NotificationsHandler) mux.HandleFunc(Endpoints.Status, dashboard.StatusHandler) diff --git a/Go/cmd/globeboard/app_test.go b/Go/cmd/globeboard/app_test.go index a381d39701d2f0b4e7f444069597bbc3def23870..500ea5a1785e462eb3bf958d78550390c2eec31b 100644 --- a/Go/cmd/globeboard/app_test.go +++ b/Go/cmd/globeboard/app_test.go @@ -1,14 +1,20 @@ package main import ( + "bytes" + "encoding/json" + "fmt" "globeboard/internal/handlers" "globeboard/internal/handlers/endpoint/dashboard" + "globeboard/internal/handlers/endpoint/util" "globeboard/internal/utils/constants/Endpoints" "globeboard/internal/utils/constants/Paths" "log" "net/http" "net/http/httptest" + "net/url" "os" + "strings" "testing" ) @@ -19,8 +25,14 @@ const ( ) var ( - token = os.Getenv("TOKEN") - ID = "" + mux = http.NewServeMux() + wrongToken = "bhuiozdfbbjkwsrbnjlsfbjnklsdv" //Keyboard Mash + token = "sk-token-brrr-access" + UUID = "me_me_me_me" + docId1 = "420" + docId2 = "420" + webhookId1 = "69" + webhookId2 = "69" ) func fileExistsTest(filename string) bool { @@ -35,26 +47,47 @@ func init() { if !fileExistsTest(os.Getenv("FIREBASE_CREDENTIALS_FILE")) { log.Panic("Firebase Credentials file is not mounted: ", os.Getenv("FIREBASE_CREDENTIALS_FILE")) } - err := os.Setenv("GO_ENV", "test") - if err != nil { - panic("Unable to set GO_ENV") - } + + mux.HandleFunc(Paths.Root, handlers.EmptyHandler) + mux.HandleFunc(Endpoints.UserRegistration, util.UserRegistrationHandler) + mux.HandleFunc(Endpoints.UserDeletionId, util.UserDeletionHandler) + mux.HandleFunc(Endpoints.ApiKey, util.APIKeyHandler) + mux.HandleFunc(Endpoints.RegistrationsID, dashboard.RegistrationsIdHandler) + mux.HandleFunc(Endpoints.Registrations, dashboard.RegistrationsHandler) + mux.HandleFunc(Endpoints.DashboardsID, dashboard.DashboardsIdHandler) + mux.HandleFunc(Endpoints.NotificationsID, dashboard.NotificationsIdHandler) + mux.HandleFunc(Endpoints.Notifications, dashboard.NotificationsHandler) + mux.HandleFunc(Endpoints.Status, dashboard.StatusHandler) + } +/* Test Root Once */ + // TestRoot confirms that Root Endpoint returns 303 See Other for All Requests. func TestRoot(t *testing.T) { // Create a request to your endpoint with the GET method - req, err := http.NewRequest("GET", Paths.Root, nil) + req, err := http.NewRequest(http.MethodGet, Paths.Root, nil) if err != nil { t.Fatal(err) } // Create a ResponseRecorder to record the response rr := httptest.NewRecorder() - handler := http.HandlerFunc(handlers.EmptyHandler) + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusSeeOther { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusSeeOther) + } + + req, err = http.NewRequest(http.MethodPost, Paths.Root, nil) + if err != nil { + t.Fatal(err) + } // Serve the request to the handler - handler.ServeHTTP(rr, req) + mux.ServeHTTP(rr, req) // Check the status code if status := rr.Code; status != http.StatusSeeOther { @@ -62,13 +95,13 @@ func TestRoot(t *testing.T) { status, http.StatusSeeOther) } - req, err = http.NewRequest("POST", Paths.Root, nil) + req, err = http.NewRequest(http.MethodPut, Paths.Root, nil) if err != nil { t.Fatal(err) } // Serve the request to the handler - handler.ServeHTTP(rr, req) + mux.ServeHTTP(rr, req) // Check the status code if status := rr.Code; status != http.StatusSeeOther { @@ -76,57 +109,122 @@ func TestRoot(t *testing.T) { status, http.StatusSeeOther) } - req, err = http.NewRequest("PUT", Paths.Root, nil) + req, err = http.NewRequest(http.MethodPatch, Paths.Root, nil) if err != nil { t.Fatal(err) } // Serve the request to the handler - handler.ServeHTTP(rr, req) + mux.ServeHTTP(rr, req) // Check the status code if status := rr.Code; status != http.StatusSeeOther { t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusSeeOther) } -} -// TestStatusGetNoKey confirms that the Status Endpoint returns Status Bad Request for GET Method without an API token. -func TestStatusGetNoKey(t *testing.T) { - // Create a request to your endpoint with the GET method - req, err := http.NewRequest("GET", Endpoints.Status, nil) + req, err = http.NewRequest(http.MethodDelete, Paths.Root, nil) if err != nil { t.Fatal(err) } - // Create a ResponseRecorder to record the response - rr := httptest.NewRecorder() - handler := http.HandlerFunc(dashboard.StatusHandler) - // Serve the request to the handler - handler.ServeHTTP(rr, req) + mux.ServeHTTP(rr, req) // Check the status code - if status := rr.Code; status != http.StatusUnauthorized { + if status := rr.Code; status != http.StatusSeeOther { t.Errorf("handler returned wrong status code: got %v want %v", - status, http.StatusUnauthorized) + status, http.StatusSeeOther) + } +} + +/* Run tests as intended */ + +func TestRegisterHandlerRegister(t *testing.T) { + form := url.Values{} + form.Add("username", DisplayName) + form.Add("email", Email) + form.Add("password", Password) + + req, err := http.NewRequest(http.MethodPost, Endpoints.UserRegistration, strings.NewReader(form.Encode())) + if err != nil { + t.Fatal(err) + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusCreated { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusCreated) + } + + // Decode the JSON response + var response struct { + Token string `json:"token"` + UserID string `json:"userid"` + } + + if err := json.NewDecoder(rr.Body).Decode(&response); err != nil { + t.Fatal("Failed to decode response body:", err) + } + + token = response.Token + UUID = response.UserID +} + +func TestDeleteAPIKeyHandler(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.ApiKey+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + req.Header.Add("Authorization", UUID) + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusNoContent { + t.Errorf("DELETE handler returned wrong status code: got %v want %v", status, http.StatusNoContent) + } +} + +func TestGetAPIKeyHandler(t *testing.T) { + req, err := http.NewRequest(http.MethodGet, Endpoints.ApiKey, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Add("Authorization", UUID) + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusCreated { + t.Errorf("GET handler returned wrong status code: got %v want %v", status, http.StatusCreated) + } + + // Optionally decode the response to check if the correct API key is retrieved + var response struct { + APIKey string `json:"token"` + } + if err := json.NewDecoder(rr.Body).Decode(&response); err != nil { + t.Fatal("Failed to decode response body:", err) } + + token = response.APIKey } -// TestStatusGet confirms that the Status Endpoint returns Status OK for GET Method. func TestStatusGet(t *testing.T) { // Create a request to your endpoint with the GET method - req, err := http.NewRequest("GET", Endpoints.Status+"?token="+token+"", nil) + req, err := http.NewRequest(http.MethodGet, Endpoints.Status+"?token="+token, nil) if err != nil { t.Fatal(err) } // Create a ResponseRecorder to record the response rr := httptest.NewRecorder() - handler := http.HandlerFunc(dashboard.StatusHandler) - - // Serve the request to the handler - handler.ServeHTTP(rr, req) + mux.ServeHTTP(rr, req) // Check the status code if status := rr.Code; status != http.StatusOK { @@ -135,20 +233,309 @@ func TestStatusGet(t *testing.T) { } } -// TestStatusGetWrongKey confirms that the Status Endpoint returns Status Not Accepted for GET Method with incorrect token. -func TestStatusGetWrongKey(t *testing.T) { +func TestNotificationsHandlerPostDiscord(t *testing.T) { + notificationData := []byte(`{ + "url": "https://localhost/discord", + "country": "", + "event": ["INVOKE","REGISTER","CHANGE","DELETE"] + }`) + req, err := http.NewRequest(http.MethodPost, Endpoints.Notifications+"?token="+token, bytes.NewBuffer(notificationData)) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", "application/json") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusCreated { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusCreated) + } + + var response struct { + ID string `json:"id"` + } + + if err := json.NewDecoder(rr.Body).Decode(&response); err != nil { + t.Fatal("Failed to decode response body:", err) + } + + webhookId1 = response.ID +} + +func TestNotificationsHandlerPost(t *testing.T) { + notificationData := []byte(`{ + "url": "https://localhost/", + "country": "", + "event": ["INVOKE","DELETE"] + }`) + req, err := http.NewRequest(http.MethodPost, Endpoints.Notifications+"?token="+token, bytes.NewBuffer(notificationData)) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", "application/json") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusCreated { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusCreated) + } + + var response struct { + ID string `json:"id"` + } + + if err := json.NewDecoder(rr.Body).Decode(&response); err != nil { + t.Fatal("Failed to decode response body:", err) + } + + webhookId2 = response.ID +} + +func TestNotificationsHandlerIdGet(t *testing.T) { + req, err := http.NewRequest(http.MethodGet, Endpoints.Notifications+"/"+webhookId1+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) + } +} + +func TestNotificationsHandlerGet(t *testing.T) { + req, err := http.NewRequest(http.MethodGet, Endpoints.Notifications+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) + } +} + +func TestRegistrationsHandlerPost(t *testing.T) { + registrationData := []byte(`{ + "country": "united states", + "features": { + "temperature": true, + "coordinates": true + } + }`) + + req, err := http.NewRequest(http.MethodPost, Endpoints.Registrations+"?token="+token, bytes.NewBuffer(registrationData)) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", "application/json") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusCreated { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusCreated) + } + + var response struct { + ID string `json:"id"` + LastChange string `json:"lastChange"` + } + + if err := json.NewDecoder(rr.Body).Decode(&response); err != nil { + t.Fatal("Failed to decode response body:", err) + } + + docId1 = response.ID +} + +func TestRegistrationsHandlerPostMinimal(t *testing.T) { + registrationData := []byte(`{ + "isoCode": "no", + "features": { + "temperature": true + } + }`) + + req, err := http.NewRequest(http.MethodPost, Endpoints.Registrations+"?token="+token, bytes.NewBuffer(registrationData)) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", "application/json") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusCreated { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusCreated) + } + + var response struct { + ID string `json:"id"` + LastChange string `json:"lastChange"` + } + + if err := json.NewDecoder(rr.Body).Decode(&response); err != nil { + t.Fatal("Failed to decode response body:", err) + } + + docId2 = response.ID +} + +func TestRegistrationsHandlerGet(t *testing.T) { + req, err := http.NewRequest(http.MethodGet, Endpoints.Registrations+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) + } +} + +func TestRegistrationsIdHandlerPatch(t *testing.T) { + patchData := []byte(`{ + "features": { + "temperature": true, + "precipitation": true, + "capital": true, + "coordinates": true, + "population": true, + "area": true, + "targetCurrencies": ["jpy", "nok", "eur","gbp"] + } + }`) + + req, err := http.NewRequest(http.MethodPatch, Endpoints.Registrations+"/"+docId1+"?token="+token, bytes.NewBuffer(patchData)) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", "application/json") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusAccepted { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusAccepted) + } +} + +func TestRegistrationsIdHandlerGet(t *testing.T) { + testUrl := fmt.Sprintf("%s/%s?token=%s", Endpoints.Registrations, docId1, token) + req, err := http.NewRequest(http.MethodGet, testUrl, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) + } +} + +func TestDashboardIdHandlerGet(t *testing.T) { + testUrl := fmt.Sprintf("%s/%s?token=%s", Endpoints.Dashboards, docId1, token) + req, err := http.NewRequest(http.MethodGet, testUrl, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) + } + t.Log(rr.Body.String()) +} + +func TestDashboardIdHandlerGetMinimal(t *testing.T) { + testUrl := fmt.Sprintf("%s/%s?token=%s", Endpoints.Dashboards, docId2, token) + req, err := http.NewRequest(http.MethodGet, testUrl, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) + } + t.Log(rr.Body.String()) +} + +func TestRegistrationsIdHandlerDeleteMinimal(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.Registrations+"/"+docId2+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusNoContent { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusNoContent) + } +} + +/* Run test with wrong token */ + +func TestDeleteAPIKeyHandlerWrongToken(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.ApiKey+"?token="+wrongToken, nil) + if err != nil { + t.Fatal(err) + } + + req.Header.Add("Authorization", UUID) + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusInternalServerError { + t.Errorf("DELETE handler returned wrong status code: got %v want %v", status, http.StatusInternalServerError) + } +} + +func TestStatusGetWrongToken(t *testing.T) { // Create a request to your endpoint with the GET method - req, err := http.NewRequest("GET", Endpoints.Status+"?token=c35c5742", nil) + req, err := http.NewRequest(http.MethodGet, Endpoints.Status+"?token="+wrongToken, nil) if err != nil { t.Fatal(err) } // Create a ResponseRecorder to record the response rr := httptest.NewRecorder() - handler := http.HandlerFunc(dashboard.DashboardsHandler) + mux.ServeHTTP(rr, req) - // Serve the request to the handler - handler.ServeHTTP(rr, req) + // Check the status code + if status := rr.Code; status != http.StatusNotAcceptable { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotAcceptable) + } +} + +func TestRegistrationsPostWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodPost, Endpoints.Registrations+"?token="+wrongToken, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) // Check the status code if status := rr.Code; status != http.StatusNotAcceptable { @@ -157,38 +544,1314 @@ func TestStatusGetWrongKey(t *testing.T) { } } -// TestStatusMethodNotAllowed confirms that the Status Endpoint returns Status Not Implemented for Methods other than GET. -func TestStatusMethodNotAllowed(t *testing.T) { - // Create a request to your endpoint with a method other than GET - req, err := http.NewRequest("POST", Endpoints.Status, nil) +func TestRegistrationsGetWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Registrations+"?token="+wrongToken, nil) if err != nil { t.Fatal(err) } // Create a ResponseRecorder to record the response rr := httptest.NewRecorder() - handler := http.HandlerFunc(dashboard.StatusHandler) + mux.ServeHTTP(rr, req) - // Serve the request to the handler - handler.ServeHTTP(rr, req) + // Check the status code + if status := rr.Code; status != http.StatusNotAcceptable { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotAcceptable) + } +} + +func TestRegistrationsGetIdWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Registrations+"/"+docId1+"?token="+wrongToken, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) // Check the status code - if status := rr.Code; status != http.StatusNotImplemented { + if status := rr.Code; status != http.StatusNotAcceptable { t.Errorf("handler returned wrong status code: got %v want %v", - status, http.StatusNotImplemented) + status, http.StatusNotAcceptable) } +} - req, err = http.NewRequest("PUT", Endpoints.Status, nil) +func TestRegistrationsPatchIdWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodPatch, Endpoints.Registrations+"/"+docId1+"?token="+wrongToken, nil) if err != nil { t.Fatal(err) } - // Serve the request to the handler - handler.ServeHTTP(rr, req) + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) // Check the status code - if status := rr.Code; status != http.StatusNotImplemented { + if status := rr.Code; status != http.StatusNotAcceptable { t.Errorf("handler returned wrong status code: got %v want %v", - status, http.StatusNotImplemented) + status, http.StatusNotAcceptable) + } +} + +func TestRegistrationsDeleteIdWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodDelete, Endpoints.Registrations+"/"+docId1+"?token="+wrongToken, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotAcceptable { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotAcceptable) + } +} + +func TestDashboardGetIdWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Dashboards+"/"+docId1+"?token="+wrongToken, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotAcceptable { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotAcceptable) + } +} + +func TestNotificationsPostWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodPost, Endpoints.Notifications+"?token="+wrongToken, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotAcceptable { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotAcceptable) + } +} + +func TestNotificationsGetWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Notifications+"?token="+wrongToken, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotAcceptable { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotAcceptable) + } +} + +func TestNotificationsGetIdWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Notifications+"/"+webhookId1+"?token="+wrongToken, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotAcceptable { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotAcceptable) + } +} + +func TestNotificationsDeleteIdWrongToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodDelete, Endpoints.Notifications+"/"+webhookId1+"?token="+wrongToken, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotAcceptable { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotAcceptable) + } +} + +/* Run tests without a token */ + +func TestDeleteAPIKeyHandlerNoToken(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.ApiKey, nil) + if err != nil { + t.Fatal(err) + } + + req.Header.Add("Authorization", UUID) + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusBadRequest { + t.Errorf("DELETE handler returned wrong status code: got %v want %v", status, http.StatusBadRequest) + } +} + +func TestStatusGetNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Status, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestRegistrationsPostNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodPost, Endpoints.Registrations, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestRegistrationsGetNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Registrations, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestRegistrationsGetIdNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Registrations+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestRegistrationsPatchIdNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodPatch, Endpoints.Registrations+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestRegistrationsDeleteIdNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodDelete, Endpoints.Registrations+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestDashboardGetIdNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Dashboards+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestNotificationsPostNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodPost, Endpoints.Notifications, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestNotificationsGetNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Notifications, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestNotificationsGetIdNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Notifications+"/"+webhookId1, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +func TestNotificationsDeleteIdNoToken(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodDelete, Endpoints.Notifications+"/"+webhookId1, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } +} + +/* Empty ID */ + +func TestRegistrationsGetEmptyId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Registrations+"/?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestRegistrationsPatchEmptyId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodPatch, Endpoints.Registrations+"/?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestRegistrationsDeleteEmptyId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodDelete, Endpoints.Registrations+"/?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestDashboardGetEmptyId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Dashboards+"/?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestNotificationsGetEmptyId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Notifications+"/?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestNotificationsDeleteEmptyId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodDelete, Endpoints.Notifications+"/?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +/* Wrong ID */ + +func TestRegistrationsGetWrongId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Registrations+"/aaaaaaaaaaaaaaaaa?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestRegistrationsPatchWrongId(t *testing.T) { + patchData := []byte(`{ + "features": { + "targetCurrencies": ["EUR", "USD", "NOK"] + } + }`) + req, err := http.NewRequest(http.MethodPatch, Endpoints.Registrations+"/aaaaaaaaaaaaaaaaa?token="+token, bytes.NewBuffer(patchData)) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestRegistrationsDeleteWrongId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodDelete, Endpoints.Registrations+"/aaaaaaaaaaaaaaaaa?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestDashboardGetWrongId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Dashboards+"/aaaaaaaaaaaaaaaaa?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestNotificationsGetWrongId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.Notifications+"/aaaaaaaaaaaaaaaaa?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotFound) + } +} + +func TestNotificationsDeleteWrongId(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodDelete, Endpoints.Notifications+"/aaaaaaaaaaaaaaaaa?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusInternalServerError { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusInternalServerError) + } +} + +/* Register Wrong Email, Password */ + +func TestRegisterHandlerRegisterBadEmail(t *testing.T) { + form := url.Values{} + form.Add("username", DisplayName) + form.Add("email", "TesterTesting.test") + form.Add("password", Password) + + req, err := http.NewRequest(http.MethodPost, Endpoints.UserRegistration, strings.NewReader(form.Encode())) + if err != nil { + t.Fatal(err) + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusBadRequest { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusBadRequest) + } +} + +func TestRegisterHandlerRegisterBadPassword(t *testing.T) { + form := url.Values{} + form.Add("username", DisplayName) + form.Add("email", Email) + form.Add("password", "password") + + req, err := http.NewRequest(http.MethodPost, Endpoints.UserRegistration, strings.NewReader(form.Encode())) + if err != nil { + t.Fatal(err) + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusBadRequest { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusBadRequest) + } +} + +/* Empty POST/PATCH Body */ + +func TestDeleteAPIKeyHandlerEmpty(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.ApiKey+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + req.Header.Add("Authorization", "") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("DELETE handler returned wrong status code: got %v want %v", status, http.StatusUnauthorized) + } +} + +func TestGetAPIKeyHandlerEmpty(t *testing.T) { + req, err := http.NewRequest(http.MethodGet, Endpoints.ApiKey, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Add("Authorization", "") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("GET handler returned wrong status code: got %v want %v", status, http.StatusUnauthorized) + } +} + +func TestRegisterHandlerEmptyRegister(t *testing.T) { + req, err := http.NewRequest(http.MethodPost, Endpoints.UserRegistration, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusBadRequest { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusBadRequest) + } +} + +func TestNotificationsHandlerEmptyPost(t *testing.T) { + req, err := http.NewRequest(http.MethodPost, Endpoints.Notifications+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", "application/json") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusBadRequest { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusBadRequest) + } +} + +func TestRegistrationsHandlerEmptyPost(t *testing.T) { + req, err := http.NewRequest(http.MethodPost, Endpoints.Registrations+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", "application/json") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusBadRequest { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusBadRequest) + } +} + +func TestRegistrationsIdHandlerEmptyPatch(t *testing.T) { + req, err := http.NewRequest(http.MethodPatch, Endpoints.Registrations+"/"+docId1+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", "application/json") + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusBadRequest { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusBadRequest) + } +} + +/* Delete User No UUID & Wrong UUID */ + +func TestRegisterHandlerDeleteNoUUID(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.UserDeletion+"/", nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusNotFound) + } +} + +func TestRegisterHandlerDeleteWrongUUID(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.UserDeletion+"/NTNU2024", nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusInternalServerError { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusInternalServerError) + } +} + +/* Endpoint "Not Implemented" Methods Check */ + +func TestUserRegister(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.UserRegistration, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPut, Endpoints.UserRegistration, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPatch, Endpoints.UserRegistration, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodDelete, Endpoints.UserRegistration, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } +} + +func TestUserDeletion(t *testing.T) { + // Create a request to your endpoint with the GET method + req, err := http.NewRequest(http.MethodGet, Endpoints.UserDeletion+"/"+UUID, nil) + if err != nil { + t.Fatal(err) + } + + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPut, Endpoints.UserDeletion+"/"+UUID, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPatch, Endpoints.UserDeletion+"/"+UUID, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPost, Endpoints.UserDeletion+"/"+UUID, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } +} + +func TestAPIKeyHandler(t *testing.T) { + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + + req, err := http.NewRequest(http.MethodPut, Endpoints.ApiKey, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPatch, Endpoints.ApiKey, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPost, Endpoints.ApiKey, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } +} + +func TestStatus(t *testing.T) { + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + + req, err := http.NewRequest(http.MethodPut, Endpoints.Status, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPatch, Endpoints.Status, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPost, Endpoints.Status, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodDelete, Endpoints.Status, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } +} + +func TestRegistrations(t *testing.T) { + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + + req, err := http.NewRequest(http.MethodPut, Endpoints.Registrations, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPatch, Endpoints.Registrations, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodDelete, Endpoints.Registrations, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } +} + +func TestRegistrationsId(t *testing.T) { + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + + req, err := http.NewRequest(http.MethodPut, Endpoints.Registrations+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPost, Endpoints.Registrations+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } +} + +func TestDashboardId(t *testing.T) { + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + + req, err := http.NewRequest(http.MethodPut, Endpoints.Dashboards+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPost, Endpoints.Dashboards+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPatch, Endpoints.Dashboards+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodDelete, Endpoints.Dashboards+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } +} + +func TestNotifications(t *testing.T) { + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + + req, err := http.NewRequest(http.MethodPut, Endpoints.Notifications, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPatch, Endpoints.Notifications, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodDelete, Endpoints.Notifications, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } +} + +func TestNotificationsId(t *testing.T) { + // Create a ResponseRecorder to record the response + rr := httptest.NewRecorder() + + req, err := http.NewRequest(http.MethodPut, Endpoints.Notifications+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPost, Endpoints.Notifications+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } + + req, err = http.NewRequest(http.MethodPatch, Endpoints.Notifications+"/"+docId1, nil) + if err != nil { + t.Fatal(err) + } + + // Serve the request to the handler + mux.ServeHTTP(rr, req) + + // Check the status code + if status := rr.Code; status != http.StatusNotImplemented { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusNotImplemented) + } +} + +/* Clean UP */ + +func TestRegistrationsIdHandlerDelete(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.Registrations+"/"+docId1+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusNoContent { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusNoContent) + } +} + +func TestNotificationsHandlerDeleteDiscord(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.Notifications+"/"+webhookId1+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusNoContent { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusNoContent) + } +} + +func TestNotificationsHandlerDelete(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.Notifications+"/"+webhookId2+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusNoContent { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusNoContent) + } +} + +func TestDeleteAPIKey(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.ApiKey+"?token="+token, nil) + if err != nil { + t.Fatal(err) + } + + req.Header.Add("Authorization", UUID) + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusNoContent { + t.Errorf("DELETE handler returned wrong status code: got %v want %v", status, http.StatusNoContent) + } +} + +func TestRegisterHandlerDelete(t *testing.T) { + req, err := http.NewRequest(http.MethodDelete, Endpoints.UserDeletion+"/"+UUID, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + mux.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusNoContent { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusNoContent) } } diff --git a/Go/db/db.go b/Go/db/db.go index 4fb7f68c8d46a62101d914f24043f2104f400519..4cf3dfa8e4e91c0e8790cdc9a0bf72ada4cfddbb 100644 --- a/Go/db/db.go +++ b/Go/db/db.go @@ -44,7 +44,7 @@ func getFirestoreClient() (*firestore.Client, error) { client, err := app.Firestore(ctx) if err != nil { // Logging the error - log.Println("Credentials file: '" + os.Getenv("FIREBASE_CREDENTIALS_FILE") + "' lead to an error.") + log.Print("Firestore reported an error: ", err) return nil, err } @@ -72,36 +72,34 @@ func TestDBConnection() string { "lastChecked": firestore.ServerTimestamp, }, firestore.MergeAll) - if err != nil { - grpcStatusCode := status.Code(err) - switch grpcStatusCode { - case codes.Canceled: - return fmt.Sprintf("%d %s", http.StatusRequestTimeout, http.StatusText(http.StatusRequestTimeout)) - case codes.DeadlineExceeded: - return fmt.Sprintf("%d %s", http.StatusGatewayTimeout, http.StatusText(http.StatusGatewayTimeout)) - case codes.PermissionDenied: - return fmt.Sprintf("%d %s", http.StatusForbidden, http.StatusText(http.StatusForbidden)) - case codes.NotFound: - // This might indicate the collection or document does not exist, - //which for this purpose is treated as a connection success - // since the error was Firestore-specific and not network or permission related. - return fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK)) - case codes.ResourceExhausted: - return fmt.Sprintf("%d %s", http.StatusTooManyRequests, http.StatusText(http.StatusTooManyRequests)) - case codes.Unauthenticated: - return fmt.Sprintf("%d %s", http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized)) - case codes.Unavailable: - return fmt.Sprintf("%d %s", http.StatusServiceUnavailable, http.StatusText(http.StatusServiceUnavailable)) - case codes.Unknown, codes.Internal: - return fmt.Sprintf("%d %s", http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) - default: - // For any other codes, return a generic HTTP 500 error - return fmt.Sprintf("%d %s", http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) - } - } - - // If no error, the document update was successful, indicating good connectivity and permissions. - return fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK)) + grpcStatusCode := status.Code(err) + switch grpcStatusCode { + case codes.OK: + return fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK)) + case codes.Canceled: + return fmt.Sprintf("%d %s", http.StatusRequestTimeout, http.StatusText(http.StatusRequestTimeout)) + case codes.DeadlineExceeded: + return fmt.Sprintf("%d %s", http.StatusGatewayTimeout, http.StatusText(http.StatusGatewayTimeout)) + case codes.PermissionDenied: + return fmt.Sprintf("%d %s", http.StatusForbidden, http.StatusText(http.StatusForbidden)) + case codes.NotFound: + // This might indicate the collection or document does not exist, + //which for this purpose is treated as a connection success + // since the error was Firestore-specific and not network or permission related. + return fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK)) + case codes.ResourceExhausted: + return fmt.Sprintf("%d %s", http.StatusTooManyRequests, http.StatusText(http.StatusTooManyRequests)) + case codes.Unauthenticated: + return fmt.Sprintf("%d %s", http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized)) + case codes.Unavailable: + return fmt.Sprintf("%d %s", http.StatusServiceUnavailable, http.StatusText(http.StatusServiceUnavailable)) + case codes.Unknown, codes.Internal: + return fmt.Sprintf("%d %s", http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + default: + // For any other codes, return a generic HTTP 500 error + return fmt.Sprintf("%d %s", http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + } + } func AddApiKey(docID, UUID string, key string) error { @@ -151,7 +149,7 @@ func AddApiKey(docID, UUID string, key string) error { return nil } -func DeleteApiKey(apiKey string) error { +func DeleteApiKey(UUID, apiKey string) error { client, err := getFirestoreClient() if err != nil { return err @@ -167,7 +165,7 @@ func DeleteApiKey(apiKey string) error { // Create a reference to the Firestore collection ref := client.Collection(Firestore.ApiKeyCollection) - iter := ref.Where("APIKey", "==", apiKey).Limit(1).Documents(ctx) + iter := ref.Where("UUID", "==", UUID).Where("APIKey", "==", apiKey).Limit(1).Documents(ctx) defer iter.Stop() var docID string @@ -249,7 +247,7 @@ func GetAPIKeyUUID(apiKey string) string { } } -func AddRegistration(docID string, data *structs.CountryInfoGet) error { +func AddRegistration(docID string, data *structs.CountryInfoInternal) error { client, err := getFirestoreClient() if err != nil { return err @@ -281,16 +279,18 @@ func AddRegistration(docID string, data *structs.CountryInfoGet) error { return nil } -func GetRegistrations(UUID string) ([]*structs.CountryInfoGet, error) { +func GetRegistrations(UUID string) ([]*structs.CountryInfoInternal, error) { client, err := getFirestoreClient() if err != nil { return nil, err } - defer func() { - if err := client.Close(); err != nil { + defer func(client *firestore.Client) { + err := client.Close() + if err != nil { log.Printf(FirebaseClosingErr, err) + return } - }() + }(client) // Reference to the Firestore collection ref := client.Collection(Firestore.RegistrationCollection) @@ -302,10 +302,10 @@ func GetRegistrations(UUID string) ([]*structs.CountryInfoGet, error) { return nil, err } - var cis []*structs.CountryInfoGet + var cis []*structs.CountryInfoInternal for _, doc := range docs { - var ci *structs.CountryInfoGet + var ci *structs.CountryInfoInternal if err := doc.DataTo(&ci); err != nil { log.Printf(ParsingError, err) return nil, err @@ -316,16 +316,18 @@ func GetRegistrations(UUID string) ([]*structs.CountryInfoGet, error) { return cis, nil } -func GetSpecificRegistration(ID, UUID string) (*structs.CountryInfoGet, error) { +func GetSpecificRegistration(ID, UUID string) (*structs.CountryInfoInternal, error) { client, err := getFirestoreClient() if err != nil { return nil, err } - defer func() { - if err := client.Close(); err != nil { + defer func(client *firestore.Client) { + err := client.Close() + if err != nil { log.Printf(FirebaseClosingErr, err) + return } - }() + }(client) // Reference to the Firestore collection ref := client.Collection(Firestore.RegistrationCollection) @@ -333,7 +335,7 @@ func GetSpecificRegistration(ID, UUID string) (*structs.CountryInfoGet, error) { iter := ref.Where("ID", "==", ID).Where("UUID", "==", UUID).Limit(1).Documents(ctx) defer iter.Stop() - var ci *structs.CountryInfoGet + var ci *structs.CountryInfoInternal // Iterate over the query results for { @@ -354,16 +356,18 @@ func GetSpecificRegistration(ID, UUID string) (*structs.CountryInfoGet, error) { return nil, errors.New("no registration with that ID was found") } -func UpdateRegistration(ID, UUID string, data *structs.CountryInfoGet) error { +func UpdateRegistration(ID, UUID string, data *structs.CountryInfoInternal) error { client, err := getFirestoreClient() if err != nil { return err } - defer func() { - if err := client.Close(); err != nil { + defer func(client *firestore.Client) { + err := client.Close() + if err != nil { log.Printf(FirebaseClosingErr, err) + return } - }() + }(client) // Reference to the Firestore collection ref := client.Collection(Firestore.RegistrationCollection) @@ -475,11 +479,13 @@ func GetAllWebhooks() ([]structs.WebhookGet, error) { if err != nil { return nil, err } - defer func() { - if err := client.Close(); err != nil { + defer func(client *firestore.Client) { + err := client.Close() + if err != nil { log.Printf(FirebaseClosingErr, err) + return } - }() + }(client) // Reference to the Firestore collection ref := client.Collection(Firestore.WebhookCollection) @@ -510,11 +516,13 @@ func GetWebhooksUser(UUID string) ([]structs.WebhookResponse, error) { if err != nil { return nil, err } - defer func() { - if err := client.Close(); err != nil { + defer func(client *firestore.Client) { + err := client.Close() + if err != nil { log.Printf(FirebaseClosingErr, err) + return } - }() + }(client) // Reference to the Firestore collection ref := client.Collection(Firestore.WebhookCollection) @@ -545,11 +553,13 @@ func GetSpecificWebhook(ID, UUID string) (*structs.WebhookResponse, error) { if err != nil { return nil, err } - defer func() { - if err := client.Close(); err != nil { + defer func(client *firestore.Client) { + err := client.Close() + if err != nil { log.Printf(FirebaseClosingErr, err) + return } - }() + }(client) // Reference to the Firestore collection ref := client.Collection(Firestore.WebhookCollection) @@ -569,7 +579,6 @@ func GetSpecificWebhook(ID, UUID string) (*structs.WebhookResponse, error) { return nil, fmt.Errorf(IterationFailed, err) } if err := doc.DataTo(&webhook); err != nil { - log.Println("Error retrieving document:", err) return nil, err } return webhook, nil diff --git a/Go/internal/func/dashboardFunctions.go b/Go/internal/func/dashboardFunctions.go index adf28b0fca9d0752c33e49e958235a840920451c..986106b1584301a439a29df169d1d19488a4775d 100644 --- a/Go/internal/func/dashboardFunctions.go +++ b/Go/internal/func/dashboardFunctions.go @@ -10,6 +10,7 @@ import ( "log" "net/http" "strconv" + "strings" ) type OpenMeteoTemp struct { @@ -18,6 +19,10 @@ type OpenMeteoTemp struct { } `json:"current"` } +const ( + alphaCodes = "alpha?codes=" +) + func GetTemp(coordinates structs.CoordinatesDashboard) (float64, error) { response, err := http.Get(External.OpenMeteoAPI + "?latitude=" + (coordinates.Latitude) + "&longitude=" + (coordinates.Longitude) + "¤t=temperature_2m") if err != nil { @@ -50,7 +55,7 @@ type OpenMeteoPrecipitation struct { } `json:"current"` } -func GetPrecipitation(coordinates structs.CoordinatesDashboard) (float64, error) { +func GetPrecipitation(coordinates *structs.CoordinatesDashboard) (float64, error) { response, err := http.Get(External.OpenMeteoAPI + "?latitude=" + (coordinates.Latitude) + "&longitude=" + (coordinates.Longitude) + "¤t=precipitation") if err != nil { return 0, err @@ -82,7 +87,7 @@ type Country struct { } func GetCapital(isocode string) (string, error) { - response, err := http.Get(External.CountriesAPI + isocode + "&fields=capital") + response, err := http.Get(External.CountriesAPI + alphaCodes + isocode + "&fields=capital") if err != nil { return "nil", err } @@ -114,7 +119,7 @@ type CountryCoordinates struct { func GetCoordinates(isocode string) (structs.CoordinatesDashboard, error) { var empty = structs.CoordinatesDashboard{} - response, err := http.Get(External.CountriesAPI + isocode + "&fields=latlng") + response, err := http.Get(External.CountriesAPI + alphaCodes + isocode + "&fields=latlng") if err != nil { return empty, err } @@ -148,7 +153,7 @@ type CountryPopulation struct { } func GetPopulation(isocode string) (int, error) { - response, err := http.Get(External.CountriesAPI + isocode + "&fields=population") + response, err := http.Get(External.CountriesAPI + alphaCodes + isocode + "&fields=population") if err != nil { return 0, err } @@ -178,7 +183,7 @@ type CountryArea struct { } func GetArea(isocode string) (float64, error) { - response, err := http.Get(External.CountriesAPI + isocode + "&fields=area") + response, err := http.Get(External.CountriesAPI + alphaCodes + isocode + "&fields=area") if err != nil { return 0, err } @@ -221,7 +226,7 @@ func GetExchangeRate(isocode string, currencies []string) (map[string]float64, e } exchangeRate := make(map[string]float64) for _, currency := range currencies { - exchangeRate[currency] = exchangeRateList[currency] + exchangeRate[strings.ToUpper(currency)] = exchangeRateList[strings.ToUpper(currency)] } return exchangeRate, nil @@ -254,7 +259,7 @@ func fetchCurrencyRates(currency string) (map[string]float64, error) { } func getExchangeRateList(isocode string) (map[string]float64, error) { - response, err := http.Get(External.CountriesAPI + isocode + "&fields=currencies") + response, err := http.Get(External.CountriesAPI + alphaCodes + isocode + "&fields=currencies") if err != nil { return nil, err } @@ -276,7 +281,6 @@ func getExchangeRateList(isocode string) (map[string]float64, error) { } for currency := range currencyData[0].Currencies { - log.Print(currency) rates, err := fetchCurrencyRates(currency) if err != nil { return nil, fmt.Errorf("error fetching currency rates: %v", err) diff --git a/Go/internal/func/supported_countries.go b/Go/internal/func/supported_countries.go index bad5fc47962f0bd14dcc53996e5ab5c9c3e7b0d0..0f10336cb7a5d52d1656020f66d4569fd03b28e3 100644 --- a/Go/internal/func/supported_countries.go +++ b/Go/internal/func/supported_countries.go @@ -47,7 +47,7 @@ func getSupportedCountries() (map[string]string, error) { return countriesMap, nil } -func ValidateCountryInfo(ci *structs.CountryInfoGet) error { +func ValidateCountryInfo(ci *structs.CountryInfoInternal) error { err := validateCountryNameIsoCode(ci) if err != nil { return err @@ -60,10 +60,10 @@ func ValidateCountryInfo(ci *structs.CountryInfoGet) error { return nil } -func validateCountryNameIsoCode(ci *structs.CountryInfoGet) error { - validCountries, err := getSupportedCountries() // Adjusted to use the map version. +func validateCountryNameIsoCode(ci *structs.CountryInfoInternal) error { + validCountries, err := getSupportedCountries() if err != nil { - return errors.New("error validating country") + return fmt.Errorf("error validating country: %v", err) } if err := validateCountryOrIsoCodeProvided(ci); err != nil { @@ -81,14 +81,14 @@ func validateCountryNameIsoCode(ci *structs.CountryInfoGet) error { return validateCorrespondence(ci, validCountries) } -func validateCountryOrIsoCodeProvided(ci *structs.CountryInfoGet) error { +func validateCountryOrIsoCodeProvided(ci *structs.CountryInfoInternal) error { if ci.Country == "" && ci.IsoCode == "" { return errors.New("either country name or ISO code must be provided") } return nil } -func validateIsoCode(ci *structs.CountryInfoGet, validCountries map[string]string) error { +func validateIsoCode(ci *structs.CountryInfoInternal, validCountries map[string]string) error { if ci.IsoCode != "" { ci.IsoCode = strings.ToTitle(ci.IsoCode) if country, exists := validCountries[ci.IsoCode]; !exists { @@ -100,7 +100,7 @@ func validateIsoCode(ci *structs.CountryInfoGet, validCountries map[string]strin return nil } -func updateAndValidateIsoCodeForCountry(ci *structs.CountryInfoGet, validCountries map[string]string) error { +func updateAndValidateIsoCodeForCountry(ci *structs.CountryInfoInternal, validCountries map[string]string) error { if ci.IsoCode == "" && ci.Country != "" { ci.Country = cases.Title(language.English, cases.Compact).String(ci.Country) for code, name := range validCountries { @@ -114,7 +114,7 @@ func updateAndValidateIsoCodeForCountry(ci *structs.CountryInfoGet, validCountri return nil } -func validateCorrespondence(ci *structs.CountryInfoGet, validCountries map[string]string) error { +func validateCorrespondence(ci *structs.CountryInfoInternal, validCountries map[string]string) error { if ci.Country != "" && ci.IsoCode != "" { ci.Country = cases.Title(language.English, cases.Compact).String(ci.Country) if validCountries[ci.IsoCode] != ci.Country { diff --git a/Go/internal/func/webhook_payload.go b/Go/internal/func/webhook_payload.go index b4157a89772c0e0b5816486694a852903d8850cc..cf0e16bbb458b3dd3a0237bd275a22648fed2262 100644 --- a/Go/internal/func/webhook_payload.go +++ b/Go/internal/func/webhook_payload.go @@ -24,7 +24,7 @@ var ( method = "" ) -func LoopSendWebhooksRegistrations(caller string, ci *structs.CountryInfoGet, endpoint, eventAction string) { +func LoopSendWebhooksRegistrations(caller string, ci *structs.CountryInfoExternal, endpoint, eventAction string) { client, err := authenticate.GetFireBaseAuthClient() if err != nil { log.Printf("Error initializing Firebase Auth: %v", err) @@ -33,9 +33,6 @@ func LoopSendWebhooksRegistrations(caller string, ci *structs.CountryInfoGet, en ctx := context.Background() - // Remove UUID from webhook json - ci.UUID = "" - // Ignoring error as we've already confirmed the caller at the endpoint. user, _ := client.GetUser(ctx, caller) @@ -69,23 +66,25 @@ func LoopSendWebhooksRegistrations(caller string, ci *structs.CountryInfoGet, en } for _, webhook := range webhooks { - if isRegistrationWebhookValid(caller, ci, eventAction, webhook) && strings.Contains(webhook.URL, "discord") { - sendDiscordWebhookPayload( - email, - title, - color, - method, - endpoint, - ci, - webhook.URL) - } else { - sendWebhookPayload( - email, - title, - method, - endpoint, - isocode, - webhook.URL) + if isRegistrationWebhookValid(caller, ci, eventAction, webhook) { + if strings.Contains(webhook.URL, "discord") { + sendDiscordWebhookPayload( + email, + title, + color, + method, + endpoint, + ci, + webhook.URL) + } else { + sendWebhookPayload( + email, + title, + method, + endpoint, + isocode, + webhook.URL) + } } } } @@ -115,28 +114,30 @@ func LoopSendWebhooksDashboard(caller string, dr *structs.DashboardResponse) { } for _, webhook := range webhooks { - if isDashboardWebhookValid(caller, dr, Webhooks.EventInvoke, webhook) && strings.Contains(webhook.URL, "discord") { - sendDiscordWebhookPayload( - email, - title, - color, - method, - Endpoints.Dashboards, - dr, - webhook.URL) - } else { - sendWebhookPayload( - email, - title, - method, - Endpoints.Dashboards, - isocode, - webhook.URL) + if isDashboardWebhookValid(caller, dr, Webhooks.EventInvoke, webhook) { + if strings.Contains(webhook.URL, "discord") { + sendDiscordWebhookPayload( + email, + title, + color, + method, + Endpoints.DashboardsID, + dr, + webhook.URL) + } else { + sendWebhookPayload( + email, + title, + method, + Endpoints.DashboardsID, + isocode, + webhook.URL) + } } } } -func isRegistrationWebhookValid(caller string, ci *structs.CountryInfoGet, eventAction string, webhook structs.WebhookGet) bool { +func isRegistrationWebhookValid(caller string, ci *structs.CountryInfoExternal, eventAction string, webhook structs.WebhookGet) bool { if webhook.UUID == "" || webhook.UUID == caller { if webhook.Country == "" || webhook.Country == ci.IsoCode { if stringListContains(webhook.Event, eventAction) { diff --git a/Go/internal/handlers/endpoint/dashboard/dashboards_handler.go b/Go/internal/handlers/endpoint/dashboard/dashboards_id_handler.go similarity index 87% rename from Go/internal/handlers/endpoint/dashboard/dashboards_handler.go rename to Go/internal/handlers/endpoint/dashboard/dashboards_id_handler.go index 5cad818099d8431821badb2e1eedf002d8fd1b10..394437ea3f9fdfef48d849fa2e86c9f2dc727f89 100644 --- a/Go/internal/handlers/endpoint/dashboard/dashboards_handler.go +++ b/Go/internal/handlers/endpoint/dashboard/dashboards_id_handler.go @@ -9,7 +9,6 @@ import ( "globeboard/internal/utils/structs" "log" "net/http" - "os" "strconv" "time" ) @@ -18,8 +17,8 @@ const ( RetrivalError = "Error getting country information" ) -// DashboardsHandler handles requests to the book count API endpoint. -func DashboardsHandler(w http.ResponseWriter, r *http.Request) { +// DashboardsIdHandler handles requests to the book count API endpoint. +func DashboardsIdHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: handleDashboardGetRequest(w, r) @@ -94,14 +93,18 @@ func handleDashboardGetRequest(w http.ResponseWriter, r *http.Request) { return } - if os.Getenv("GO_ENV") != "test" { - _func.LoopSendWebhooksDashboard(UUID, dr) - } + _func.LoopSendWebhooksDashboard(UUID, dr) } -func getWeatherInfo(w http.ResponseWriter, reg *structs.CountryInfoGet, dr *structs.DashboardResponse) bool { +func getWeatherInfo(w http.ResponseWriter, reg *structs.CountryInfoInternal, dr *structs.DashboardResponse) bool { if reg.Features.Temperature { - temp, err := _func.GetTemp(dr.Features.Coordinates) + coords, err := _func.GetCoordinates(reg.IsoCode) + if err != nil { + log.Print("Error getting Coordinates Information: ", err) + http.Error(w, RetrivalError, http.StatusInternalServerError) + return true + } + temp, err := _func.GetTemp(coords) if err != nil { log.Print("Error getting Temperature Information: ", err) http.Error(w, RetrivalError, http.StatusInternalServerError) @@ -122,7 +125,7 @@ func getWeatherInfo(w http.ResponseWriter, reg *structs.CountryInfoGet, dr *stru return false } -func getCurrencyInfo(w http.ResponseWriter, reg *structs.CountryInfoGet, dr *structs.DashboardResponse) bool { +func getCurrencyInfo(w http.ResponseWriter, reg *structs.CountryInfoInternal, dr *structs.DashboardResponse) bool { if reg.Features.TargetCurrencies != nil && len(reg.Features.TargetCurrencies) != 0 { exchangeRate, err := _func.GetExchangeRate(reg.IsoCode, reg.Features.TargetCurrencies) if err != nil { @@ -135,7 +138,7 @@ func getCurrencyInfo(w http.ResponseWriter, reg *structs.CountryInfoGet, dr *str return false } -func getCountryInfo(w http.ResponseWriter, reg *structs.CountryInfoGet, dr *structs.DashboardResponse) bool { +func getCountryInfo(w http.ResponseWriter, reg *structs.CountryInfoInternal, dr *structs.DashboardResponse) bool { if reg.Features.Capital { capital, err := _func.GetCapital(reg.IsoCode) if err != nil { @@ -153,7 +156,7 @@ func getCountryInfo(w http.ResponseWriter, reg *structs.CountryInfoGet, dr *stru http.Error(w, RetrivalError, http.StatusInternalServerError) return true } - dr.Features.Coordinates = coords + dr.Features.Coordinates = &coords } if reg.Features.Population { diff --git a/Go/internal/handlers/endpoint/dashboard/notifications_id_handler.go b/Go/internal/handlers/endpoint/dashboard/notifications_id_handler.go index def3461d7ee75f3c86fdb463aea3549636bbd849..8958cc9037cbbe51c8cf37f7e0e061ba0750bc43 100644 --- a/Go/internal/handlers/endpoint/dashboard/notifications_id_handler.go +++ b/Go/internal/handlers/endpoint/dashboard/notifications_id_handler.go @@ -44,7 +44,7 @@ func handleNotifGetRequest(w http.ResponseWriter, r *http.Request) { hook, err := db.GetSpecificWebhook(ID, UUID) if err != nil { log.Print("Error getting document from database: ", err) - http.Error(w, "Error retrieving data from database", http.StatusInternalServerError) + http.Error(w, "Error retrieving data from database", http.StatusNotFound) return } diff --git a/Go/internal/handlers/endpoint/dashboard/registrations_handler.go b/Go/internal/handlers/endpoint/dashboard/registrations_handler.go index c2fffd48ca44d4862ca273e5fb365a0c8bc7ce39..093ee9a232ac9b41e800e83bd4ed54e69180e717 100644 --- a/Go/internal/handlers/endpoint/dashboard/registrations_handler.go +++ b/Go/internal/handlers/endpoint/dashboard/registrations_handler.go @@ -13,7 +13,6 @@ import ( "io" "log" "net/http" - "os" ) const ( @@ -36,8 +35,8 @@ func RegistrationsHandler(w http.ResponseWriter, r *http.Request) { } } -func DecodeCountryInfo(data io.ReadCloser) (*structs.CountryInfoGet, error) { - var ci *structs.CountryInfoGet +func DecodeCountryInfo(data io.ReadCloser) (*structs.CountryInfoInternal, error) { + var ci *structs.CountryInfoInternal if err := json.NewDecoder(data).Decode(&ci); err != nil { return nil, err } @@ -117,9 +116,14 @@ func handleRegPostRequest(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - if os.Getenv("GO_ENV") != "test" { - _func.LoopSendWebhooksRegistrations(UUID, reg, Endpoints.Registrations, Webhooks.EventRegister) - } + + cie := new(structs.CountryInfoExternal) + cie.ID = reg.ID + cie.Country = reg.Country + cie.IsoCode = reg.IsoCode + cie.Features = reg.Features + + _func.LoopSendWebhooksRegistrations(UUID, cie, Endpoints.Registrations, Webhooks.EventRegister) } // handleRegGetAllRequest handles GET requests to retrieve a registered country. @@ -149,16 +153,27 @@ func handleRegGetAllRequest(w http.ResponseWriter, r *http.Request) { // Write the status code to the response w.WriteHeader(http.StatusOK) + // Parse Data for External Users + var cies []*structs.CountryInfoExternal + for _, reg := range regs { + cie := new(structs.CountryInfoExternal) + cie.ID = reg.ID + cie.Country = reg.Country + cie.IsoCode = reg.IsoCode + cie.Features = reg.Features + cie.Lastchange = reg.Lastchange + cies = append(cies, cie) + } + // Serialize the struct to JSON and write it to the response - err = json.NewEncoder(w).Encode(regs) + err = json.NewEncoder(w).Encode(cies) if err != nil { // Handle error http.Error(w, err.Error(), http.StatusInternalServerError) return } - if os.Getenv("GO_ENV") != "test" { - for _, reg := range regs { - _func.LoopSendWebhooksRegistrations(UUID, reg, Endpoints.Registrations, Webhooks.EventInvoke) - } + + for _, cie := range cies { + _func.LoopSendWebhooksRegistrations(UUID, cie, Endpoints.Registrations, Webhooks.EventInvoke) } } diff --git a/Go/internal/handlers/endpoint/dashboard/registrations_id_handler.go b/Go/internal/handlers/endpoint/dashboard/registrations_id_handler.go index 1fb8f849a117dec07311e1e646571478d71ac105..4f06d22579718c0e4f0e2b2c8f5168938492ecee 100644 --- a/Go/internal/handlers/endpoint/dashboard/registrations_id_handler.go +++ b/Go/internal/handlers/endpoint/dashboard/registrations_id_handler.go @@ -12,7 +12,6 @@ import ( "io" "log" "net/http" - "os" ) const ( @@ -57,7 +56,7 @@ func handleRegGetRequest(w http.ResponseWriter, r *http.Request) { reg, err := db.GetSpecificRegistration(ID, UUID) if err != nil { log.Print("Error getting document from database: ", err) - http.Error(w, "Error retrieving data from database", http.StatusInternalServerError) + http.Error(w, "Error retrieving data from database", http.StatusNotFound) return } @@ -67,17 +66,22 @@ func handleRegGetRequest(w http.ResponseWriter, r *http.Request) { // Write the status code to the response w.WriteHeader(http.StatusOK) + cie := new(structs.CountryInfoExternal) + cie.ID = reg.ID + cie.Country = reg.Country + cie.IsoCode = reg.IsoCode + cie.Features = reg.Features + cie.Lastchange = reg.Lastchange + // Serialize the struct to JSON and write it to the response - err = json.NewEncoder(w).Encode(reg) + err = json.NewEncoder(w).Encode(cie) if err != nil { // Handle error http.Error(w, err.Error(), http.StatusInternalServerError) return } - if os.Getenv("GO_ENV") != "test" { - _func.LoopSendWebhooksRegistrations(UUID, reg, Endpoints.RegistrationsID, Webhooks.EventInvoke) - } + _func.LoopSendWebhooksRegistrations(UUID, cie, Endpoints.RegistrationsID, Webhooks.EventInvoke) } // handleRegPatchRequest handles PUT requests to Update a registered country. @@ -106,37 +110,61 @@ func handleRegPatchRequest(w http.ResponseWriter, r *http.Request) { return } - countryInfo, err, errcode := patchCountryInformation(r, ID, UUID) + ci, err, errcode := patchCountryInformation(r, ID, UUID) if err != nil { err := fmt.Sprintf("Error patching data together: %v", err) http.Error(w, err, errcode) return } - err = _func.ValidateCountryInfo(countryInfo) + err = _func.ValidateCountryInfo(ci) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + http.Error(w, err.Error(), http.StatusInternalServerError) return } - err = db.UpdateRegistration(ID, UUID, countryInfo) + err = db.UpdateRegistration(ID, UUID, ci) if err != nil { err := fmt.Sprintf("Error saving patched data to database: %v", err) http.Error(w, err, http.StatusInternalServerError) return } + reg, err := db.GetSpecificRegistration(ID, UUID) + if err != nil { + err := fmt.Sprint("Error retrieving updated document: ", err) + http.Error(w, err, http.StatusNotFound) + return + } + + cie := new(structs.CountryInfoExternal) + cie.ID = reg.ID + cie.Country = reg.Country + cie.IsoCode = reg.IsoCode + cie.Features = reg.Features + cie.Lastchange = reg.Lastchange + + w.Header().Set("content-type", "application/json") w.WriteHeader(http.StatusAccepted) - if os.Getenv("GO_ENV") != "test" { - _func.LoopSendWebhooksRegistrations(UUID, countryInfo, Endpoints.RegistrationsID, Webhooks.EventChange) + response := map[string]interface{}{ + "lastChange": cie.Lastchange, } + + err = json.NewEncoder(w).Encode(response) + if err != nil { + // Handle error + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + _func.LoopSendWebhooksRegistrations(UUID, cie, Endpoints.RegistrationsID, Webhooks.EventChange) } -func patchCountryInformation(r *http.Request, ID, UUID string) (*structs.CountryInfoGet, error, int) { +func patchCountryInformation(r *http.Request, ID, UUID string) (*structs.CountryInfoInternal, error, int) { reg, err := db.GetSpecificRegistration(ID, UUID) if err != nil { - return nil, err, http.StatusInternalServerError + return nil, err, http.StatusNotFound } bytes, err := json.Marshal(reg) @@ -179,8 +207,8 @@ func patchCountryInformation(r *http.Request, ID, UUID string) (*structs.Country return nil, err, http.StatusInternalServerError } - // Unmarshal the JSON data into the CountryInfoGet struct. - var countryInfo *structs.CountryInfoGet + // Unmarshal the JSON data into the CountryInfoInternal struct. + var countryInfo *structs.CountryInfoInternal err = json.Unmarshal(jsonData, &countryInfo) if err != nil { return nil, err, http.StatusInternalServerError @@ -249,7 +277,12 @@ func handleRegDeleteRequest(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) - if os.Getenv("GO_ENV") != "test" { - _func.LoopSendWebhooksRegistrations(UUID, reg, Endpoints.RegistrationsID, Webhooks.EventDelete) - } + cie := new(structs.CountryInfoExternal) + cie.ID = reg.ID + cie.Country = reg.Country + cie.IsoCode = reg.IsoCode + cie.Features = reg.Features + cie.Lastchange = reg.Lastchange + + _func.LoopSendWebhooksRegistrations(UUID, cie, Endpoints.RegistrationsID, Webhooks.EventDelete) } diff --git a/Go/internal/handlers/endpoint/dashboard/status_handler.go b/Go/internal/handlers/endpoint/dashboard/status_handler.go index 553a1625080135431e3f277576659dbb7cd4aff6..424c5f682f7b197aa8bad6733c4859caf0427c7d 100644 --- a/Go/internal/handlers/endpoint/dashboard/status_handler.go +++ b/Go/internal/handlers/endpoint/dashboard/status_handler.go @@ -76,7 +76,7 @@ func handleStatusGetRequest(w http.ResponseWriter, r *http.Request) { // Initialize a status response. status := structs.StatusResponse{ - CountriesApi: getEndpointStatus(External.CountriesAPI + "no"), + CountriesApi: getEndpointStatus(External.CountriesAPI + "alpha?codes=no"), MeteoApi: getEndpointStatus(External.OpenMeteoAPI), CurrencyApi: getEndpointStatus(External.CurrencyAPI + "nok"), FirebaseDB: db.TestDBConnection(), diff --git a/Go/internal/handlers/endpoint/util/apikey_handler.go b/Go/internal/handlers/endpoint/util/apikey_handler.go index 4df57638b6f537856b6305174d6f4b219b0bff69..10058a15ba830410bc5e8dfcccb9d15c93170442 100644 --- a/Go/internal/handlers/endpoint/util/apikey_handler.go +++ b/Go/internal/handlers/endpoint/util/apikey_handler.go @@ -28,17 +28,37 @@ func handleApiKeyDeleteRequest(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() token := query.Get("token") + UUID := r.Header.Get("Authorization") + + ctx := context.Background() + + client, err := authenticate.GetFireBaseAuthClient() + if err != nil { + log.Printf("error getting Auth client: %v\n", err) + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } + + // Verify the ID token + _, err = client.GetUser(ctx, UUID) + if err != nil { + log.Printf("error verifying UUID: %v\n", err) + http.Error(w, "Not Authorized", http.StatusUnauthorized) + return + } + if token == "" { http.Error(w, "Please specify API Key to delete: '?token={API_Key}' ", http.StatusBadRequest) return } - err := db.DeleteApiKey(token) + err = db.DeleteApiKey(UUID, token) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } + w.WriteHeader(http.StatusNoContent) } func handleApiKeyGetRequest(w http.ResponseWriter, r *http.Request) { @@ -75,8 +95,12 @@ func handleApiKeyGetRequest(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) + response := map[string]string{ + "token": key, + } + // Encode books as JSON and send the response. - if err := json.NewEncoder(w).Encode(key); err != nil { + if err := json.NewEncoder(w).Encode(response); err != nil { http.Error(w, "Error encoding JSON response: "+err.Error(), http.StatusInternalServerError) return } diff --git a/Go/internal/handlers/endpoint/util/user_register_handler.go b/Go/internal/handlers/endpoint/util/user_register_handler.go index cee83284e8b1482baff39fe32f867f039688fe43..684675f70a1cd39cd15abe714e822f601b35dea5 100644 --- a/Go/internal/handlers/endpoint/util/user_register_handler.go +++ b/Go/internal/handlers/endpoint/util/user_register_handler.go @@ -2,8 +2,8 @@ package util import ( "context" + "encoding/json" "firebase.google.com/go/auth" - "fmt" authenticate "globeboard/auth" "globeboard/db" _func "globeboard/internal/func" @@ -36,7 +36,7 @@ func registerUser(w http.ResponseWriter, r *http.Request) { http.Error(w, "Error initializing Firebase Auth", http.StatusInternalServerError) return } - name := r.FormValue("name") + name := r.FormValue("username") email := r.FormValue("email") password := r.FormValue("password") @@ -65,7 +65,7 @@ func registerUser(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("content-type", "text/html") + w.Header().Set("content-type", "application/json") UDID := _func.GenerateUID(constants.DocIdLength) key := _func.GenerateAPIKey(constants.ApiKeyLength) @@ -77,18 +77,27 @@ func registerUser(w http.ResponseWriter, r *http.Request) { return } - _, err = fmt.Fprintf(w, "Successfully registered user: %s\n"+ - "API Key: %s \n\n"+ - "To delete and get a new API Key utilize: Authorization: \"%v\" at:\n<a href=\"/util/v1/key\">/util/v1/key</a>", u.DisplayName, key, u.UID) + response := struct { + Token string `json:"token"` + UserID string `json:"userid"` + }{ + Token: key, + UserID: u.UID, + } + + w.WriteHeader(http.StatusCreated) + + encoder := json.NewEncoder(w) + err = encoder.Encode(response) if err != nil { - log.Print("Error writing response to ResponseWriter: ", err) - http.Error(w, ISE, http.StatusInternalServerError) + log.Printf("Error encoding JSON response: %v\n", err) + http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } } func isValidEmail(email string) bool { - regex := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`) + regex := regexp.MustCompile(`(?i)^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`) return regex.MatchString(email) } diff --git a/Go/internal/utils/constants/Endpoints/endpoints.go b/Go/internal/utils/constants/Endpoints/endpoints.go index c9590ba581c3bed80604d82f3d22e042707227a6..4cb434930f0da521d0b515c28fd8182e47f00ffc 100644 --- a/Go/internal/utils/constants/Endpoints/endpoints.go +++ b/Go/internal/utils/constants/Endpoints/endpoints.go @@ -9,10 +9,12 @@ import ( const ( ApiKey = Paths.Util + constants.APIVersion + "/key" UserRegistration = Paths.Util + constants.APIVersion + "/user/register" - UserDeletion = Paths.Util + constants.APIVersion + "/user/delete/{ID}" + UserDeletion = Paths.Util + constants.APIVersion + "/user/delete" + UserDeletionId = Paths.Util + constants.APIVersion + "/user/delete/{ID}" RegistrationsID = Paths.Dashboards + constants.APIVersion + "/registrations/{ID}" Registrations = Paths.Dashboards + constants.APIVersion + "/registrations" - Dashboards = Paths.Dashboards + constants.APIVersion + "/dashboard/{ID}" + DashboardsID = Paths.Dashboards + constants.APIVersion + "/dashboard/{ID}" + Dashboards = Paths.Dashboards + constants.APIVersion + "/dashboard" NotificationsID = Paths.Dashboards + constants.APIVersion + "/notifications/{ID}" Notifications = Paths.Dashboards + constants.APIVersion + "/notifications" Status = Paths.Dashboards + constants.APIVersion + "/status" diff --git a/Go/internal/utils/constants/External/external.go b/Go/internal/utils/constants/External/external.go index 023eef1c773c7813603b75551a000c0508001690..ddbe912f6497bda238e7cb50d1f228a73e9446ce 100644 --- a/Go/internal/utils/constants/External/external.go +++ b/Go/internal/utils/constants/External/external.go @@ -7,5 +7,6 @@ package External const ( CurrencyAPI = "http://129.241.150.113:9090/currency/" OpenMeteoAPI = "https://api.open-meteo.com/v1/forecast" - CountriesAPI = "http://129.241.150.113:8080/v3.1/alpha?codes=" + //OpenMeteoAPI = "https://google.com" + CountriesAPI = "http://129.241.150.113:8080/v3.1/" ) diff --git a/Go/internal/utils/structs/structs.go b/Go/internal/utils/structs/structs.go index 8e3840459dd4516879277c09ea8f789a39f96ea6..4cfa3acd4143dbfb649f848154785a1a8e9284b1 100644 --- a/Go/internal/utils/structs/structs.go +++ b/Go/internal/utils/structs/structs.go @@ -10,7 +10,15 @@ type APIKey struct { // Registrations Structs -type CountryInfoGet struct { +type CountryInfoExternal struct { + ID string `json:"id"` + Country string `json:"country"` + IsoCode string `json:"isoCode"` + Features Features `json:"features"` + Lastchange time.Time `json:"lastchange"` +} + +type CountryInfoInternal struct { ID string `json:"id"` UUID string `json:"uuid"` Country string `json:"country"` @@ -40,18 +48,18 @@ type DashboardResponse struct { } type FeaturesDashboard struct { - Temperature string `json:"temperature"` - Precipitation string `json:"precipitation"` - Capital string `json:"capital"` - Coordinates CoordinatesDashboard `json:"coordinates"` - Population int `json:"population"` - Area string `json:"area"` - TargetCurrencies map[string]float64 `json:"targetCurrencies"` + Temperature string `json:"temperature,omitempty"` + Precipitation string `json:"precipitation,omitempty"` + Capital string `json:"capital,omitempty"` + Coordinates *CoordinatesDashboard `json:"coordinates,omitempty"` + Population int `json:"population,omitempty"` + Area string `json:"area,omitempty"` + TargetCurrencies map[string]float64 `json:"targetCurrencies,omitempty"` } type CoordinatesDashboard struct { - Latitude string `json:"latitude"` - Longitude string `json:"longitude"` + Latitude string `json:"latitude,omitempty"` + Longitude string `json:"longitude,omitempty"` } // Status structs diff --git a/README.md b/README.md index afac2f6385a445673381b381cf118e61892a5ec6..12544060fad49827b17617090d4d37379e3873ad 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ This code was developed by: | Status Code | `204 No Content` | |:------------|:-----------------| -### Delete your API key: +### Get a New API key: (Old must be deleted first, only allowed one) ```http GET /util/v1/key/ @@ -99,11 +99,13 @@ This code was developed by: } ``` -### Get a New API key: (Old must be deleted first, only allowed one) +### Delete your API key: ```http DELETE /util/v1/key/?token={token} ``` +| Authorization | `Your UUID` | +|:--------------|:------------| | Parameter | Type | Description | |:----------|:---------|:------------------------------------------| @@ -538,7 +540,6 @@ To run this project, you will need to add the following environment variables to `FIREBASE_CREDENTIALS_FILE` - Path to your Firebase credentials file. - ## Run Locally - Clone the repository