package main import ( "encoding/json" "fmt" "image-storage/auth" "image-storage/model" "io" "log" "net/http" "time" "github.com/jmoiron/sqlx" "golang.org/x/crypto/bcrypt" _ "modernc.org/sqlite" ) func main() { db, err := sqlx.Connect("sqlite", "./db/sqlite.db") if err != nil { log.Fatalf("failed to connect to db: %v", err) } defer db.Close() srv := NewServer(":5000") srv.Handle("POST /api/auth/register", func(w http.ResponseWriter, r *http.Request) error { var body struct { Email string `json:"email"` Password string `json:"password"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { return srv.Error("empty body", err, 400) } if body.Email == "" || body.Password == "" { return srv.Error("email or password missing", nil, 400) } hash, err := bcrypt.GenerateFromPassword([]byte(body.Password), 10) if err != nil { return fmt.Errorf("failed to generate password hash: %v", err) } user := &model.User{ Email: body.Email, Password: string(hash), } if err := user.Create(db); err != nil { return srv.Error("failed to create user", err, 400) } if err := user.FindByID(db); err != nil { return fmt.Errorf("failed to populate user object after creating it: %v", err) } expiryTime := time.Now().Add(time.Hour * 24 * 30) token, err := auth.GenerateUserToken(user.ID, expiryTime) if err != nil { return fmt.Errorf("failed to generate access token: %v", err) } auth.SetUserCookie(w, token, expiryTime) return srv.JSON(w, user, 201) }) srv.Handle("POST /api/auth/login", func(w http.ResponseWriter, r *http.Request) error { var body struct { Email string `json:"email"` Password string `json:"password"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { return srv.Error("empty body", err, 400) } if body.Email == "" || body.Password == "" { return srv.Error("email or password missing", nil, 400) } user := &model.User{Email: body.Email} if err := user.FindByEmail(db); err != nil { return srv.Error("user not found", err, 404) } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(body.Password)); err != nil { return srv.Error("invalid password", nil, 400) } expiryTime := time.Now().Add(time.Hour * 24 * 30) token, err := auth.GenerateUserToken(user.ID, expiryTime) if err != nil { return fmt.Errorf("failed to generate access token: %v", err) } auth.SetUserCookie(w, token, expiryTime) return srv.JSON(w, user, 200) }) srv.Handle("POST /api/images", func(w http.ResponseWriter, r *http.Request) error { userId, err := auth.GetUserIdFromRequest(r) if err != nil { return srv.Error("unauthorized", err, 401) } user := &model.User{Model: model.Model{ID: userId}} if err := user.FindByID(db); err != nil { return srv.Error("user not found", nil, 401) } data, err := io.ReadAll(r.Body) if err != nil { return fmt.Errorf("failed to read request body: %v", err) } if len(data) == 0 { return srv.Error("empty body", nil, 400) } img := &model.Image{ UserID: user.ID, Data: data, ContentType: r.Header.Get("Content-Type"), } if err := img.Create(db); err != nil { return srv.Error("failed to save image to database: %v", err, 400) } return srv.JSON(w, img, 201) }) srv.Handle("GET /api/images", func(w http.ResponseWriter, r *http.Request) error { userId, err := auth.GetUserIdFromRequest(r) if err != nil { return srv.Error("unauthorized", err, 401) } rows, err := db.Queryx("SELECT * FROM images WHERE user_id = ?", userId) if err != nil { return srv.Error("images not found", err, 400) } images := []model.Image{} for rows.Next() { img := model.Image{} if err := rows.StructScan(&img); err != nil { log.Printf("failed to save image to struct: %v", err) continue } images = append(images, img) } return srv.JSON(w, images, 200) }) srv.Handle("GET /images/{id}", func(w http.ResponseWriter, r *http.Request) error { img := &model.Image{ID: r.PathValue("id")} if err := img.FindByID(db); err != nil { return srv.Error("image not found", nil, 404) } w.Header().Set("Content-Type", img.ContentType) w.Write(img.Data) return nil }) srv.Handle("DELETE /api/images/{id}", func(w http.ResponseWriter, r *http.Request) error { img := &model.Image{ID: r.PathValue("id")} if err := img.FindByID(db); err != nil { return srv.Error("image not found", nil, 404) } if err := img.DeleteByID(db); err != nil { return srv.Error("failed to delete image: %v", err, 500) } return srv.JSON(w, struct { Ok bool `json:"ok"` }{true}, 200) }) if err := srv.ListenAndServe(); err != nil { log.Fatalf("failed to start http server: %v", err) } }