From 7a266bafd87308d50dbe1697af8b175d3fc56d1b Mon Sep 17 00:00:00 2001
From: celogeek <me@celogeek.com>
Date: Wed, 2 Mar 2022 16:30:34 +0100
Subject: [PATCH] move errors

---
 .gitignore                        |  1 +
 internal/photos/api/account.go    |  7 ++++---
 internal/photos/api/check_body.go |  3 ++-
 internal/photos/api/errors.go     | 30 ------------------------------
 internal/photos/api/file.go       | 21 +++++++++++++++------
 internal/photos/api/main.go       |  5 +++--
 internal/photos/api/recovery.go   |  3 ++-
 internal/photos/api/session.go    |  7 ++++---
 internal/photoserrors/accounts.go |  9 +++++++++
 internal/photoserrors/albums.go   |  9 +++++++++
 internal/photoserrors/panic.go    |  9 +++++++++
 internal/photoserrors/requests.go |  9 +++++++++
 internal/photoserrors/session.go  | 10 ++++++++++
 internal/photoserrors/store.go    | 14 ++++++++++++++
 internal/store/core.go            |  6 ++++--
 15 files changed, 95 insertions(+), 48 deletions(-)
 create mode 100644 internal/photoserrors/accounts.go
 create mode 100644 internal/photoserrors/albums.go
 create mode 100644 internal/photoserrors/panic.go
 create mode 100644 internal/photoserrors/requests.go
 create mode 100644 internal/photoserrors/session.go
 create mode 100644 internal/photoserrors/store.go

diff --git a/.gitignore b/.gitignore
index 1269488..9de6f55 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 data
+.DS_Store
\ No newline at end of file
diff --git a/internal/photos/api/account.go b/internal/photos/api/account.go
index ebd7228..992cb2d 100644
--- a/internal/photos/api/account.go
+++ b/internal/photos/api/account.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/gin-gonic/gin"
 	"gitlab.celogeek.com/photos/api/internal/photos/models"
+	"gitlab.celogeek.com/photos/api/internal/photoserrors"
 	"gopkg.in/validator.v2"
 	"gorm.io/gorm"
 )
@@ -33,7 +34,7 @@ func (s *Service) Signup(c *gin.Context) {
 		return
 	}
 	if accountExists > 0 {
-		s.Error(c, http.StatusConflict, ErrAccountExists)
+		s.Error(c, http.StatusConflict, photoserrors.ErrAccountExists)
 		return
 	}
 	if err := s.DB.Create(models.NewAccount(account.Login, account.Password)).Error; err != nil {
@@ -57,7 +58,7 @@ func (s *Service) Login(c *gin.Context) {
 	session, err := models.NewSession(s.DB, account.Login, account.Password)
 	if err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
-			s.Error(c, http.StatusNotFound, ErrAccountAuth)
+			s.Error(c, http.StatusNotFound, photoserrors.ErrAccountAuth)
 		} else {
 			s.Error(c, http.StatusInternalServerError, err)
 		}
@@ -77,7 +78,7 @@ func (s *Service) Logout(c *gin.Context) {
 		return
 	}
 	if res.RowsAffected == 0 {
-		s.Error(c, http.StatusNotFound, ErrSessionNotFound)
+		s.Error(c, http.StatusNotFound, photoserrors.ErrSessionNotFound)
 		return
 	}
 	c.JSON(http.StatusOK, gin.H{
diff --git a/internal/photos/api/check_body.go b/internal/photos/api/check_body.go
index 039a58c..82f0b24 100644
--- a/internal/photos/api/check_body.go
+++ b/internal/photos/api/check_body.go
@@ -4,11 +4,12 @@ import (
 	"net/http"
 
 	"github.com/gin-gonic/gin"
+	"gitlab.celogeek.com/photos/api/internal/photoserrors"
 )
 
 func (s *Service) RequireBody(c *gin.Context) {
 	if c.Request.Method == "POST" && c.Request.ContentLength == 0 {
-		s.Error(c, http.StatusBadRequest, ErrReqMissingBody)
+		s.Error(c, http.StatusBadRequest, photoserrors.ErrReqMissingBody)
 		return
 	}
 }
diff --git a/internal/photos/api/errors.go b/internal/photos/api/errors.go
index 52c6b6c..eddc7f1 100644
--- a/internal/photos/api/errors.go
+++ b/internal/photos/api/errors.go
@@ -1,39 +1,9 @@
 package api
 
 import (
-	"errors"
-
 	"github.com/gin-gonic/gin"
 )
 
-var (
-	// Session
-	ErrSessionNotFound = errors.New("session not found")
-	ErrSessionInvalid  = errors.New("session invalid")
-	ErrTokenMissing    = errors.New("token missing")
-
-	// Request
-	ErrReqMissingBody = errors.New("missing body")
-	ErrReqNotFound    = errors.New("this route doesn't exists")
-
-	// Account
-	ErrAccountExists = errors.New("account exists")
-	ErrAccountAuth   = errors.New("login or password incorrect")
-
-	// Panic
-	ErrUnexpected = errors.New("an unexpected error occur")
-
-	// Album
-	ErrAlbumDontExists = errors.New("album doesn't exists")
-
-	// Store
-	ErrStorePathNotADirectory = errors.New("store path is not a directory")
-	ErrStoreBadChecksum       = errors.New("checksum should be sha1 in hex format")
-	ErrStoreBadChunkSize      = errors.New("part file size should be 1MB max")
-	ErrStoreMissingChunks     = errors.New("part checksum missing")
-	ErrStoreMismatchChecksum  = errors.New("part files doesn't match the original checksum")
-)
-
 func (s *Service) Error(c *gin.Context, code int, err error) {
 	c.AbortWithStatusJSON(code, gin.H{
 		"status": "failed",
diff --git a/internal/photos/api/file.go b/internal/photos/api/file.go
index 84cad5d..302523b 100644
--- a/internal/photos/api/file.go
+++ b/internal/photos/api/file.go
@@ -5,8 +5,10 @@ import (
 	"fmt"
 	"io"
 	"net/http"
+	"path/filepath"
 
 	"github.com/gin-gonic/gin"
+	"gitlab.celogeek.com/photos/api/internal/photoserrors"
 )
 
 var CHUNK_SIZE int64 = 1 << 20
@@ -24,17 +26,17 @@ func (s *Service) FileCreate(c *gin.Context) {
 	}
 
 	if len(file.Sum) != 40 {
-		s.Error(c, http.StatusBadRequest, ErrStoreBadChecksum)
+		s.Error(c, http.StatusBadRequest, photoserrors.ErrStoreBadChecksum)
 		return
 	}
 	if len(file.Chunks) == 0 {
-		s.Error(c, http.StatusBadRequest, ErrStoreMissingChunks)
+		s.Error(c, http.StatusBadRequest, photoserrors.ErrStoreMissingChunks)
 		return
 	}
 
 	for _, chunk := range file.Chunks {
 		if len(chunk) != 40 {
-			s.Error(c, http.StatusBadRequest, ErrStoreBadChecksum)
+			s.Error(c, http.StatusBadRequest, photoserrors.ErrStoreBadChecksum)
 			return
 		}
 	}
@@ -47,7 +49,7 @@ func (s *Service) FileCreate(c *gin.Context) {
 
 	if r != file.Sum {
 		fmt.Printf("R=%s, O=%s\n", r, file.Sum)
-		s.Error(c, http.StatusExpectationFailed, ErrStoreMismatchChecksum)
+		s.Error(c, http.StatusExpectationFailed, photoserrors.ErrStoreMismatchChecksum)
 		return
 	}
 
@@ -70,12 +72,19 @@ func (s *Service) FileCreateTemp(c *gin.Context) {
 		sumb    = c.Param("sum")
 	)
 	if len(origsum) != 40 || len(sumb) != 40 {
-		s.Error(c, http.StatusBadRequest, ErrStoreBadChecksum)
+		s.Error(c, http.StatusBadRequest, photoserrors.ErrStoreBadChecksum)
+		return
+	}
+
+	originaldir := s.Store.Dir("original", origsum)
+	originalname := filepath.Join(originaldir, origsum)
+	if s.Store.FileExists(originalname) {
+		s.Error(c, http.StatusBadRequest, photoserrors.ErrStoreAlreadyExists)
 		return
 	}
 
 	if c.Request.ContentLength > CHUNK_SIZE {
-		s.Error(c, http.StatusBadRequest, ErrStoreBadChunkSize)
+		s.Error(c, http.StatusBadRequest, photoserrors.ErrStoreBadChunkSize)
 		return
 	}
 
diff --git a/internal/photos/api/main.go b/internal/photos/api/main.go
index 053cd51..07f4d8e 100644
--- a/internal/photos/api/main.go
+++ b/internal/photos/api/main.go
@@ -10,6 +10,7 @@ import (
 
 	"github.com/gin-gonic/gin"
 	"github.com/go-sql-driver/mysql"
+	"gitlab.celogeek.com/photos/api/internal/photoserrors"
 	"gitlab.celogeek.com/photos/api/internal/store"
 	"gorm.io/gorm"
 )
@@ -62,7 +63,7 @@ func (s *Service) SetupRoutes() {
 	album.POST("/tmp/:origsum/:sum", s.FileCreateTemp)
 
 	s.Gin.NoRoute(func(c *gin.Context) {
-		s.Error(c, http.StatusNotFound, ErrReqNotFound)
+		s.Error(c, http.StatusNotFound, photoserrors.ErrReqNotFound)
 	})
 }
 
@@ -72,7 +73,7 @@ func (s *Service) PrepareStore() {
 		s.LogErr.Fatal("Store", err)
 	}
 	if !d.IsDir() {
-		s.LogErr.Fatal("Store", ErrStorePathNotADirectory)
+		s.LogErr.Fatal("Store", photoserrors.ErrStorePathNotADirectory)
 	}
 	if err := s.Store.MkDirs([]string{"tmp", "original"}); err != nil {
 		s.LogErr.Fatal("Store", err)
diff --git a/internal/photos/api/recovery.go b/internal/photos/api/recovery.go
index 508ddd5..7a5e4e7 100644
--- a/internal/photos/api/recovery.go
+++ b/internal/photos/api/recovery.go
@@ -4,13 +4,14 @@ import (
 	"net/http"
 
 	"github.com/gin-gonic/gin"
+	"gitlab.celogeek.com/photos/api/internal/photoserrors"
 )
 
 func (s *Service) Recovery(c *gin.Context) {
 	defer func() {
 		if err := recover(); err != nil {
 			s.LogErr.Print("PANIC", err)
-			s.Error(c, http.StatusInternalServerError, ErrUnexpected)
+			s.Error(c, http.StatusInternalServerError, photoserrors.ErrUnexpected)
 		}
 	}()
 	c.Next()
diff --git a/internal/photos/api/session.go b/internal/photos/api/session.go
index 2f15f61..802b707 100644
--- a/internal/photos/api/session.go
+++ b/internal/photos/api/session.go
@@ -8,13 +8,14 @@ import (
 
 	"github.com/gin-gonic/gin"
 	"gitlab.celogeek.com/photos/api/internal/photos/models"
+	"gitlab.celogeek.com/photos/api/internal/photoserrors"
 	"gorm.io/gorm"
 )
 
 func (s *Service) RequireAuthToken(c *gin.Context) {
 	token := c.GetHeader("Authorization")
 	if !strings.HasPrefix(token, "Private ") {
-		s.Error(c, http.StatusForbidden, ErrTokenMissing)
+		s.Error(c, http.StatusForbidden, photoserrors.ErrTokenMissing)
 		return
 	}
 	token = token[8:]
@@ -30,14 +31,14 @@ func (s *Service) RequireSession(c *gin.Context) {
 	sess := &models.Session{}
 	if err := s.DB.Preload("Account").Where("token = ?", c.GetString("token")).First(sess).Error; err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
-			s.Error(c, http.StatusForbidden, ErrSessionNotFound)
+			s.Error(c, http.StatusForbidden, photoserrors.ErrSessionNotFound)
 		} else {
 			s.Error(c, http.StatusForbidden, err)
 		}
 		return
 	}
 	if sess.Account == nil {
-		s.Error(c, http.StatusInternalServerError, ErrSessionInvalid)
+		s.Error(c, http.StatusInternalServerError, photoserrors.ErrSessionInvalid)
 		return
 	}
 	s.DB.Select("updated_at").Save(sess)
diff --git a/internal/photoserrors/accounts.go b/internal/photoserrors/accounts.go
new file mode 100644
index 0000000..e1a277e
--- /dev/null
+++ b/internal/photoserrors/accounts.go
@@ -0,0 +1,9 @@
+package photoserrors
+
+import "errors"
+
+var (
+	// Account
+	ErrAccountExists = errors.New("account exists")
+	ErrAccountAuth   = errors.New("login or password incorrect")
+)
diff --git a/internal/photoserrors/albums.go b/internal/photoserrors/albums.go
new file mode 100644
index 0000000..1cf28b4
--- /dev/null
+++ b/internal/photoserrors/albums.go
@@ -0,0 +1,9 @@
+package photoserrors
+
+import "errors"
+
+var (
+
+	// Album
+	ErrAlbumDontExists = errors.New("album doesn't exists")
+)
diff --git a/internal/photoserrors/panic.go b/internal/photoserrors/panic.go
new file mode 100644
index 0000000..082b5a0
--- /dev/null
+++ b/internal/photoserrors/panic.go
@@ -0,0 +1,9 @@
+package photoserrors
+
+import "errors"
+
+var (
+
+	// Panic
+	ErrUnexpected = errors.New("an unexpected error occur")
+)
diff --git a/internal/photoserrors/requests.go b/internal/photoserrors/requests.go
new file mode 100644
index 0000000..5ff6913
--- /dev/null
+++ b/internal/photoserrors/requests.go
@@ -0,0 +1,9 @@
+package photoserrors
+
+import "errors"
+
+var (
+	// Request
+	ErrReqMissingBody = errors.New("missing body")
+	ErrReqNotFound    = errors.New("this route doesn't exists")
+)
diff --git a/internal/photoserrors/session.go b/internal/photoserrors/session.go
new file mode 100644
index 0000000..353f868
--- /dev/null
+++ b/internal/photoserrors/session.go
@@ -0,0 +1,10 @@
+package photoserrors
+
+import "errors"
+
+var (
+	// Session
+	ErrSessionNotFound = errors.New("session not found")
+	ErrSessionInvalid  = errors.New("session invalid")
+	ErrTokenMissing    = errors.New("token missing")
+)
diff --git a/internal/photoserrors/store.go b/internal/photoserrors/store.go
new file mode 100644
index 0000000..36dfe93
--- /dev/null
+++ b/internal/photoserrors/store.go
@@ -0,0 +1,14 @@
+package photoserrors
+
+import "errors"
+
+var (
+	// Store
+	ErrStorePathNotADirectory = errors.New("store path is not a directory")
+	ErrStoreBadChecksum       = errors.New("checksum should be sha1 in hex format")
+	ErrStoreBadChunkSize      = errors.New("part file size should be 1MB max")
+	ErrStoreMissingChunks     = errors.New("part checksum missing")
+	ErrStoreWrongChecksum     = errors.New("wrong checksum")
+	ErrStoreMismatchChecksum  = errors.New("part files doesn't match the original checksum")
+	ErrStoreAlreadyExists     = errors.New("original file already exists")
+)
diff --git a/internal/store/core.go b/internal/store/core.go
index e41d5df..13b9616 100644
--- a/internal/store/core.go
+++ b/internal/store/core.go
@@ -7,6 +7,8 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
+
+	"gitlab.celogeek.com/photos/api/internal/photoserrors"
 )
 
 type Store struct {
@@ -40,7 +42,7 @@ func (s *Store) SaveTemp(path string, sumb string, b []byte) error {
 	sumString := hex.EncodeToString(sum.Sum(nil))
 
 	if sumb != sumString {
-		return errors.New("wrong checksum")
+		return photoserrors.ErrStoreWrongChecksum
 	}
 
 	dir := s.Dir(path, sumString)
@@ -89,7 +91,7 @@ func (s *Store) CommitTemp(path string, sumb []string) error {
 	originalname := filepath.Join(originaldir, path)
 
 	if s.FileExists(originalname) {
-		return fmt.Errorf("original file already exists")
+		return photoserrors.ErrStoreAlreadyExists
 	}
 
 	os.MkdirAll(originaldir, 0755)