From 5b03d38392c872e24209c61cc85f95c592aa9952 Mon Sep 17 00:00:00 2001 From: John Costa Date: Fri, 11 Apr 2025 19:35:49 +0100 Subject: [PATCH] wip(token): verifying user when getting the image --- backend/main.go | 303 +++++++++++++++++++++--------------------- backend/middleware.go | 30 ++++- 2 files changed, 179 insertions(+), 154 deletions(-) diff --git a/backend/main.go b/backend/main.go index 4a0b08c..7f1deb8 100644 --- a/backend/main.go +++ b/backend/main.go @@ -66,177 +66,174 @@ func main() { w.WriteHeader(http.StatusOK) }) - r.Get("/image", func(w http.ResponseWriter, r *http.Request) { - token := r.Header.Get("Authorization")[7:] + r.Group(func(r chi.Router) { + r.Use(ProtectedRoute) - fmt.Println(token) + r.Get("/image", func(w http.ResponseWriter, r *http.Request) { + userId := r.Context().Value(USER_ID).(uuid.UUID) - userId, err := GetUserIdFromAccess(token) - if err != nil { - log.Println(err) - w.WriteHeader(http.StatusForbidden) - fmt.Fprintf(w, "Get out of here!") - return - } - - images, err := userModel.ListWithProperties(r.Context(), userId) - if err != nil { - log.Println(err) - w.WriteHeader(http.StatusNotFound) - fmt.Fprintf(w, "Something went wrong") - return - } - - log.Println(images) - - type DataType struct { - Type string `json:"type"` - Data any `json:"data"` - } - - dataTypes := make([]DataType, 0) - for _, image := range images { - for _, location := range image.Locations { - dataTypes = append(dataTypes, DataType{ - Type: "location", - Data: location, - }) - } - - for _, event := range image.Events { - dataTypes = append(dataTypes, DataType{ - Type: "event", - Data: event, - }) - } - - for _, note := range image.Notes { - dataTypes = append(dataTypes, DataType{ - Type: "note", - Data: note, - }) - } - } - - jsonImages, err := json.Marshal(dataTypes) - if err != nil { - log.Println(err) - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "Could not create JSON response for this image") - return - } - - w.Write(jsonImages) - }) - - r.Get("/image/{id}", func(w http.ResponseWriter, r *http.Request) { - imageId := r.PathValue("id") - - // TODO: really need authorization here! - image, err := imageModel.Get(r.Context(), uuid.MustParse(imageId)) - if err != nil { - log.Println(err) - w.WriteHeader(http.StatusNotFound) - fmt.Fprintf(w, "Could not get image") - return - } - - // TODO: this could be part of the db table - extension := filepath.Ext(image.Image.ImageName) - extension = extension[1:] - - w.Header().Add("Content-Type", "image/"+extension) - w.Write(image.Image.Image) - }) - - r.Post("/image/{name}", func(w http.ResponseWriter, r *http.Request) { - imageName := r.PathValue("name") - - userId := r.Header.Get("userId") - - w.Header().Add("Access-Control-Allow-Origin", "*") - w.Header().Add("Access-Control-Allow-Credentials", "*") - w.Header().Add("Access-Control-Allow-Headers", "*") - - if len(imageName) == 0 { - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "You need to provide a name in the path") - return - } - - contentType := r.Header.Get("Content-Type") - - log.Println(contentType) - - // TODO: length checks on body - // TODO: extract this shit out - image := make([]byte, 0) - if contentType == "application/base64" { - decoder := base64.NewDecoder(base64.StdEncoding, r.Body) - buf := &bytes.Buffer{} - - decodedIamge, err := io.Copy(buf, decoder) + images, err := userModel.ListWithProperties(r.Context(), userId) if err != nil { log.Println(err) - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "bruh, base64 aint decoding") + w.WriteHeader(http.StatusNotFound) + fmt.Fprintf(w, "Something went wrong") return } - fmt.Println(string(image)) - fmt.Println(decodedIamge) + log.Println(images) - image = buf.Bytes() - } else if contentType == "application/oclet-stream" { - bodyData, err := io.ReadAll(r.Body) + type DataType struct { + Type string `json:"type"` + Data any `json:"data"` + } + + dataTypes := make([]DataType, 0) + for _, image := range images { + for _, location := range image.Locations { + dataTypes = append(dataTypes, DataType{ + Type: "location", + Data: location, + }) + } + + for _, event := range image.Events { + dataTypes = append(dataTypes, DataType{ + Type: "event", + Data: event, + }) + } + + for _, note := range image.Notes { + dataTypes = append(dataTypes, DataType{ + Type: "note", + Data: note, + }) + } + } + + jsonImages, err := json.Marshal(dataTypes) if err != nil { log.Println(err) w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "bruh, binary aint binaring") + fmt.Fprintf(w, "Could not create JSON response for this image") return } - // TODO: check headers - image = bodyData - } else { - log.Println("bad stuff?") - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "Bruh, you need oclet stream or base64") - return - } - - if err != nil { - log.Println("First case") - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "Couldnt read the image from the request body") - return - } - - userImage, err := imageModel.Process(r.Context(), uuid.MustParse(userId), model.Image{ - Image: image, - ImageName: imageName, + w.Write(jsonImages) }) - if err != nil { - log.Println("Second case") - log.Println(err) - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "Could not save image to DB") - return - } - jsonUserImage, err := json.Marshal(userImage) - if err != nil { - log.Println("Third case") - log.Println(err) - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "Could not create JSON response for this image") - return - } + r.Get("/image/{id}", func(w http.ResponseWriter, r *http.Request) { + imageId := r.PathValue("id") - w.WriteHeader(http.StatusCreated) + _ = r.Context().Value(USER_ID).(uuid.UUID) + + // TODO: really need authorization here! + image, err := imageModel.Get(r.Context(), uuid.MustParse(imageId)) + if err != nil { + log.Println(err) + w.WriteHeader(http.StatusNotFound) + fmt.Fprintf(w, "Could not get image") + return + } + + // TODO: this could be part of the db table + extension := filepath.Ext(image.Image.ImageName) + extension = extension[1:] + + w.Header().Add("Content-Type", "image/"+extension) + w.Write(image.Image.Image) + }) + + r.Post("/image/{name}", func(w http.ResponseWriter, r *http.Request) { + imageName := r.PathValue("name") + + userId := r.Header.Get("userId") + + w.Header().Add("Access-Control-Allow-Origin", "*") + w.Header().Add("Access-Control-Allow-Credentials", "*") + w.Header().Add("Access-Control-Allow-Headers", "*") + + if len(imageName) == 0 { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "You need to provide a name in the path") + return + } + + contentType := r.Header.Get("Content-Type") + + log.Println(contentType) + + // TODO: length checks on body + // TODO: extract this shit out + image := make([]byte, 0) + if contentType == "application/base64" { + decoder := base64.NewDecoder(base64.StdEncoding, r.Body) + buf := &bytes.Buffer{} + + decodedIamge, err := io.Copy(buf, decoder) + if err != nil { + log.Println(err) + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "bruh, base64 aint decoding") + return + } + + fmt.Println(string(image)) + fmt.Println(decodedIamge) + + image = buf.Bytes() + } else if contentType == "application/oclet-stream" { + bodyData, err := io.ReadAll(r.Body) + if err != nil { + log.Println(err) + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "bruh, binary aint binaring") + return + } + // TODO: check headers + + image = bodyData + } else { + log.Println("bad stuff?") + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Bruh, you need oclet stream or base64") + return + } + + if err != nil { + log.Println("First case") + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Couldnt read the image from the request body") + return + } + + userImage, err := imageModel.Process(r.Context(), uuid.MustParse(userId), model.Image{ + Image: image, + ImageName: imageName, + }) + if err != nil { + log.Println("Second case") + log.Println(err) + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Could not save image to DB") + return + } + + jsonUserImage, err := json.Marshal(userImage) + if err != nil { + log.Println("Third case") + log.Println(err) + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Could not create JSON response for this image") + return + } + + w.WriteHeader(http.StatusCreated) + + fmt.Fprint(w, string(jsonUserImage)) + w.Header().Add("Content-Type", "application/json") + }) - fmt.Fprint(w, string(jsonUserImage)) - w.Header().Add("Content-Type", "application/json") }) r.Post("/login", func(w http.ResponseWriter, r *http.Request) { diff --git a/backend/middleware.go b/backend/middleware.go index 7f005b0..02fec9c 100644 --- a/backend/middleware.go +++ b/backend/middleware.go @@ -1,6 +1,10 @@ package main -import "net/http" +import ( + "context" + "fmt" + "net/http" +) func CorsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -11,3 +15,27 @@ func CorsMiddleware(next http.Handler) http.Handler { next.ServeHTTP(w, r) }) } + +const USER_ID = "UserID" + +func ProtectedRoute(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("Authorization") + if len(token) < len("Bearer ") { + w.WriteHeader(http.StatusUnauthorized) + return + } + + fmt.Println(token[len("Bearer "):]) + userId, err := GetUserIdFromAccess(token[len("Bearer "):]) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + return + } + + contextWithUserId := context.WithValue(r.Context(), USER_ID, userId) + + newR := r.WithContext(contextWithUserId) + next.ServeHTTP(w, newR) + }) +}