fix: error handling for icons (#17)

fix: error handling for icons

Second batch of error handling in icon handlers
This commit is contained in:
Krzysztof Dryś 2023-11-29 13:13:38 +01:00 committed by GitHub
parent e6bfee866a
commit 05242e7729
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 115 additions and 115 deletions

View File

@ -3,9 +3,12 @@ package adapters
import (
"errors"
"fmt"
"github.com/google/uuid"
"github.com/twofas/2fas-server/internal/api/icons/domain"
"gorm.io/gorm"
"github.com/twofas/2fas-server/internal/api/icons/domain"
"github.com/twofas/2fas-server/internal/common/db"
)
type IconCouldNotBeFound struct {
@ -53,8 +56,11 @@ func (r *IconMysqlRepository) FindById(id uuid.UUID) (*domain.Icon, error) {
result := r.db.First(&Icon, "id = ?", id.String())
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, IconCouldNotBeFound{IconId: id.String()}
if err := result.Error; err != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, IconCouldNotBeFound{IconId: id.String()}
}
return nil, db.WrapError(err)
}
return Icon, nil

View File

@ -3,9 +3,12 @@ package adapters
import (
"errors"
"fmt"
"github.com/google/uuid"
"github.com/twofas/2fas-server/internal/api/icons/domain"
"gorm.io/gorm"
"github.com/twofas/2fas-server/internal/api/icons/domain"
"github.com/twofas/2fas-server/internal/common/db"
)
type IconRequestCouldNotBeFound struct {
@ -42,7 +45,7 @@ func (r *IconRequestMysqlRepository) Update(iconRequest *domain.IconRequest) err
func (r *IconRequestMysqlRepository) Delete(iconRequest *domain.IconRequest) error {
if err := r.db.Delete(iconRequest).Error; err != nil {
return err
return db.WrapError(err)
}
return nil
@ -52,9 +55,11 @@ func (r *IconRequestMysqlRepository) FindById(id uuid.UUID) (*domain.IconRequest
iconRequest := &domain.IconRequest{}
result := r.db.First(&iconRequest, "id = ?", id.String())
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, IconRequestCouldNotBeFound{IconRequestId: id.String()}
if err := result.Error; err != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, IconRequestCouldNotBeFound{IconRequestId: id.String()}
}
return nil, db.WrapError(err)
}
return iconRequest, nil

View File

@ -12,11 +12,11 @@ import (
)
type WebServiceCouldNotBeFound struct {
WebServiceId string
Identifier string
}
func (e WebServiceCouldNotBeFound) Error() string {
return fmt.Sprintf("Web service could not be found: %s", e.WebServiceId)
return fmt.Sprintf("Web service could not be found: %s", e.Identifier)
}
type WebServiceMysqlRepository struct {
@ -29,7 +29,7 @@ func NewWebServiceMysqlRepository(db *gorm.DB) *WebServiceMysqlRepository {
func (r *WebServiceMysqlRepository) Save(webService *domain.WebService) error {
if err := r.db.Create(webService).Error; err != nil {
return err
return db.WrapError(err)
}
return nil
@ -37,7 +37,7 @@ func (r *WebServiceMysqlRepository) Save(webService *domain.WebService) error {
func (r *WebServiceMysqlRepository) Update(webService *domain.WebService) error {
if err := r.db.Updates(webService).Error; err != nil {
return err
return db.WrapError(err)
}
return nil
@ -45,7 +45,7 @@ func (r *WebServiceMysqlRepository) Update(webService *domain.WebService) error
func (r *WebServiceMysqlRepository) Delete(webService *domain.WebService) error {
if err := r.db.Delete(webService).Error; err != nil {
return err
return db.WrapError(err)
}
return nil
@ -58,7 +58,7 @@ func (r *WebServiceMysqlRepository) FindById(id uuid.UUID) (*domain.WebService,
if err := result.Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, WebServiceCouldNotBeFound{WebServiceId: id.String()}
return nil, WebServiceCouldNotBeFound{Identifier: id.String()}
}
return nil, db.WrapError(err)
}
@ -73,7 +73,7 @@ func (r *WebServiceMysqlRepository) FindByName(name string) (*domain.WebService,
if err := result.Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("web service could not be found")
return nil, WebServiceCouldNotBeFound{Identifier: name}
}
return nil, db.WrapError(err)
}

View File

@ -2,15 +2,22 @@ package command
import (
"encoding/json"
"github.com/doug-martin/goqu/v9"
"github.com/google/uuid"
"github.com/twofas/2fas-server/internal/api/icons/domain"
"github.com/twofas/2fas-server/internal/common/logging"
"github.com/twofas/2fas-server/internal/common/storage"
"gorm.io/datatypes"
"gorm.io/gorm"
"fmt"
"image/png"
"path/filepath"
"github.com/pkg/errors"
"github.com/twofas/2fas-server/internal/api/icons/adapters"
"github.com/doug-martin/goqu/v9"
"github.com/google/uuid"
"gorm.io/datatypes"
"gorm.io/gorm"
"github.com/twofas/2fas-server/internal/api/icons/domain"
"github.com/twofas/2fas-server/internal/common/db"
"github.com/twofas/2fas-server/internal/common/logging"
"github.com/twofas/2fas-server/internal/common/storage"
)
type CreateIconRequest struct {
@ -125,25 +132,21 @@ type UpdateWebServiceFromIconRequestHandler struct {
func (h *UpdateWebServiceFromIconRequestHandler) Handle(cmd *UpdateWebServiceFromIconRequest) error {
webServiceId, err := uuid.Parse(cmd.WebServiceId)
if err != nil {
return err
}
iconRequestId, err := uuid.Parse(cmd.IconRequestId)
if err != nil {
return err
}
iconRequest, err := h.IconsRequestsRepository.FindById(iconRequestId)
if err != nil {
return err
}
webService, err := h.WebServiceRepository.FindById(webServiceId)
if err != nil {
return err
}
@ -153,23 +156,20 @@ func (h *UpdateWebServiceFromIconRequestHandler) Handle(cmd *UpdateWebServiceFro
lightIconStoragePath := filepath.Join(iconsStoragePath, filepath.Base(iconRequest.LightIconUrl))
lightIconImg, err := h.IconsStorage.Get(lightIconStoragePath)
if err != nil {
return err
return fmt.Errorf("failed to get the icon from the storage: %w", err)
}
lightIconPng, err := png.Decode(lightIconImg)
if err != nil {
return err
return fmt.Errorf("failed to decode the icon as pgn: %w", err)
}
lightIconId := uuid.New()
lightIconNewPath := filepath.Join(iconsStoragePath, lightIconId.String()+".png")
newLightIconLocation, err := h.IconsStorage.Move(lightIconStoragePath, lightIconNewPath)
if err != nil {
return err
return fmt.Errorf("failed to move icons storage: %w", err)
}
lightIcon := &domain.Icon{
@ -182,9 +182,8 @@ func (h *UpdateWebServiceFromIconRequestHandler) Handle(cmd *UpdateWebServiceFro
}
err = h.IconsRepository.Save(lightIcon)
if err != nil {
return err
return fmt.Errorf("failed to save light icon: %w", err)
}
iconsIds := []string{
@ -195,23 +194,20 @@ func (h *UpdateWebServiceFromIconRequestHandler) Handle(cmd *UpdateWebServiceFro
darkIconStoragePath := filepath.Join(iconsStoragePath, filepath.Base(iconRequest.DarkIconUrl))
darkIconImg, err := h.IconsStorage.Get(darkIconStoragePath)
if err != nil {
return err
return fmt.Errorf("failed to get dark icon: %w", err)
}
darkIconPng, err := png.Decode(darkIconImg)
if err != nil {
return err
return fmt.Errorf("failed to decode dark icon: %w", err)
}
darkIconId := uuid.New()
darkIconNewPath := filepath.Join(iconsStoragePath, darkIconId.String()+".png")
newDarkIconLocation, err := h.IconsStorage.Move(darkIconStoragePath, darkIconNewPath)
if err != nil {
return err
return fmt.Errorf("failed to move dark icon: %w", err)
}
darkIcon := &domain.Icon{
@ -224,15 +220,17 @@ func (h *UpdateWebServiceFromIconRequestHandler) Handle(cmd *UpdateWebServiceFro
}
err = h.IconsRepository.Save(darkIcon)
if err != nil {
return err
return fmt.Errorf("failed to save dark icon: %w", err)
}
iconsIds = append(iconsIds, darkIconId.String())
}
iconsJson, err := json.Marshal(iconsIds)
if err != nil {
return fmt.Errorf("failed to marshal icon ids: %w", err)
}
iconsCollection := &domain.IconsCollection{
Id: iconsCollectionId,
@ -241,64 +239,65 @@ func (h *UpdateWebServiceFromIconRequestHandler) Handle(cmd *UpdateWebServiceFro
}
err = h.IconsCollectionsRepository.Save(iconsCollection)
if err != nil {
return err
return fmt.Errorf("failed to save icons collection: %w", err)
}
var webServiceIconsCollectionsIds []string
err = json.Unmarshal(webService.IconsCollections, &webServiceIconsCollectionsIds)
if err != nil {
return err
return fmt.Errorf("failed to decode icons collection from web service: %w", err)
}
for _, outdatedIconsCollectionId := range webServiceIconsCollectionsIds {
id, _ := uuid.Parse(outdatedIconsCollectionId)
id, err := uuid.Parse(outdatedIconsCollectionId)
if err != nil {
return fmt.Errorf("failed to parse 'outdatedIconsCollectionId' %q: %w", outdatedIconsCollectionId, err)
}
outDatedIconsCollection, err := h.IconsCollectionsRepository.FindById(id)
if err != nil {
logging.
WithField("icon_collection_id", outdatedIconsCollectionId).
Error("Out of date icons collection cannot be found")
}
err = h.IconsCollectionsRepository.Delete(outDatedIconsCollection)
if err != nil {
logging.
WithField("icon_collection_id", outdatedIconsCollectionId).
Error("Cannot delete out of date icons collection")
} else {
err = h.IconsCollectionsRepository.Delete(outDatedIconsCollection)
if err != nil {
logging.
WithField("icon_collection_id", outdatedIconsCollectionId).
Error("Cannot delete out of date icons collection")
}
}
var outdatedCollectionIcons []string
err = json.Unmarshal(outDatedIconsCollection.Icons, &outdatedCollectionIcons)
if err != nil {
return err
return fmt.Errorf("failed to decode 'outdatedCollectionIcons': %w", err)
}
for _, outdatedIconId := range webServiceIconsCollectionsIds {
iconId, _ := uuid.Parse(outdatedIconId)
iconToDelete, err := h.IconsRepository.FindById(iconId)
if err == nil {
h.IconsRepository.Delete(iconToDelete)
} else if db.IsDBError(err) {
logging.
WithField("icon_id", iconId).
Error("Failed to delete icon by id")
}
}
}
webService.IconsCollections = datatypes.JSON(`["` + iconsCollection.Id.String() + `"]`)
h.WebServiceRepository.Update(webService)
if err := h.WebServiceRepository.Update(webService); err != nil {
return fmt.Errorf("failed to update web service %q: %w", webService.Id.String(), err)
}
err = h.IconsRequestsRepository.Delete(iconRequest)
if err != nil {
return err
return fmt.Errorf("failed to delete icon request %q: %w", iconRequest.Id.String(), err)
}
return nil
@ -319,21 +318,23 @@ type TransformIconRequestToWebServiceHandler struct {
func (h *TransformIconRequestToWebServiceHandler) Handle(cmd *TransformIconRequestToWebService) error {
iconRequestId, err := uuid.Parse(cmd.IconRequestId)
if err != nil {
return err
return fmt.Errorf("invalid 'iconRequestId': %w", err)
}
iconRequest, err := h.IconsRequestsRepository.FindById(iconRequestId)
if err != nil {
return err
}
conflict, err := h.WebServiceRepository.FindByName(iconRequest.ServiceName)
if conflict != nil {
_, err = h.WebServiceRepository.FindByName(iconRequest.ServiceName)
if err == nil {
return domain.WebServiceAlreadyExistsError{Name: iconRequest.ServiceName}
} else {
var notFound adapters.WebServiceCouldNotBeFound
if !errors.Is(err, &notFound) {
return fmt.Errorf("failed to find web service by name: %w", err)
}
}
iconsCollectionId := uuid.New()
@ -341,23 +342,20 @@ func (h *TransformIconRequestToWebServiceHandler) Handle(cmd *TransformIconReque
lightIconStoragePath := filepath.Join(iconsStoragePath, filepath.Base(iconRequest.LightIconUrl))
lightIconImg, err := h.IconsStorage.Get(lightIconStoragePath)
if err != nil {
return err
return fmt.Errorf("failed to get light icon: %w", err)
}
lightIconPng, err := png.Decode(lightIconImg)
if err != nil {
return err
return fmt.Errorf("failed to decode light icon: %w", err)
}
lightIconId := uuid.New()
lightIconNewPath := filepath.Join(iconsStoragePath, lightIconId.String()+".png")
newLightIconLocation, err := h.IconsStorage.Move(lightIconStoragePath, lightIconNewPath)
if err != nil {
return err
return fmt.Errorf("failed to move light icon: %w", err)
}
lightIcon := &domain.Icon{
@ -370,9 +368,8 @@ func (h *TransformIconRequestToWebServiceHandler) Handle(cmd *TransformIconReque
}
err = h.IconsRepository.Save(lightIcon)
if err != nil {
return err
return fmt.Errorf("failed to save light icon: %w", err)
}
iconsIds := []string{
@ -383,23 +380,20 @@ func (h *TransformIconRequestToWebServiceHandler) Handle(cmd *TransformIconReque
darkIconStoragePath := filepath.Join(iconsStoragePath, filepath.Base(iconRequest.DarkIconUrl))
darkIconImg, err := h.IconsStorage.Get(darkIconStoragePath)
if err != nil {
return err
return fmt.Errorf("failed to get dark icon: %w", err)
}
darkIconPng, err := png.Decode(darkIconImg)
if err != nil {
return err
return fmt.Errorf("failed to decode dark icon: %w", err)
}
darkIconId := uuid.New()
darkIconNewPath := filepath.Join(iconsStoragePath, darkIconId.String()+".png")
newDarkIconLocation, err := h.IconsStorage.Move(darkIconStoragePath, darkIconNewPath)
if err != nil {
return err
return fmt.Errorf("failed to move dark icon: %w", err)
}
darkIcon := &domain.Icon{
@ -412,15 +406,17 @@ func (h *TransformIconRequestToWebServiceHandler) Handle(cmd *TransformIconReque
}
err = h.IconsRepository.Save(darkIcon)
if err != nil {
return err
return fmt.Errorf("failed to save dark icon: %w", err)
}
iconsIds = append(iconsIds, darkIconId.String())
}
iconsJson, err := json.Marshal(iconsIds)
if err != nil {
return fmt.Errorf("failed to encode icon ids: %w", err)
}
iconsCollection := &domain.IconsCollection{
Id: iconsCollectionId,
@ -429,9 +425,8 @@ func (h *TransformIconRequestToWebServiceHandler) Handle(cmd *TransformIconReque
}
err = h.IconsCollectionsRepository.Save(iconsCollection)
if err != nil {
return err
return fmt.Errorf("failed to save icons collection: %w", err)
}
webService := &domain.WebService{
@ -444,15 +439,13 @@ func (h *TransformIconRequestToWebServiceHandler) Handle(cmd *TransformIconReque
}
err = h.WebServiceRepository.Save(webService)
if err != nil {
return err
return fmt.Errorf("failed to save web service: %w", err)
}
err = h.IconsRequestsRepository.Delete(iconRequest)
if err != nil {
return err
return fmt.Errorf("failed to delete icon request: %w", err)
}
return nil

View File

@ -53,7 +53,7 @@ func (h *WebServiceQueryHandler) FindOne(query *WebServiceQuery) (*WebServicePre
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, db.WrapError(err)
}
return nil, adapters.WebServiceCouldNotBeFound{WebServiceId: query.Id}
return nil, adapters.WebServiceCouldNotBeFound{Identifier: query.Id}
}
return presenter, nil

View File

@ -91,7 +91,6 @@ func (r *RoutesHandler) UpdateWebService(c *gin.Context) {
c.ShouldBindJSON(cmd)
err := r.validator.Struct(cmd)
if err != nil {
var notFoundErr adapters.WebServiceCouldNotBeFound
@ -537,7 +536,6 @@ func (r *RoutesHandler) UpdateWebServiceFromIconRequest(c *gin.Context) {
c.BindJSON(cmd)
err := r.validator.Struct(cmd)
if err != nil {
validationErrors := err.(validator.ValidationErrors)
c.JSON(400, api.NewBadRequestError(validationErrors))
@ -548,10 +546,15 @@ func (r *RoutesHandler) UpdateWebServiceFromIconRequest(c *gin.Context) {
logging.LogCommand(cmd)
err = r.cqrs.Commands.UpdateWebServiceFromIconRequest.Handle(cmd)
if err != nil {
c.JSON(400, api.NewBadRequestError(err))
logging.LogCommandFailed(cmd, err)
if db.IsDBError(err) {
c.JSON(500, api.NewInternalServerError(err))
return
}
c.JSON(400, api.NewBadRequestError(err))
return
}
@ -576,10 +579,12 @@ func (r *RoutesHandler) TransformToWebService(c *gin.Context) {
WebServiceId: webServiceId,
}
c.BindUri(cmd)
if err := c.BindUri(cmd); err != nil {
// c.BindUri already returned 400 and error.
return
}
err := r.validator.Struct(cmd)
if err != nil {
validationErrors := err.(validator.ValidationErrors)
c.JSON(400, api.NewBadRequestError(validationErrors))
@ -589,7 +594,6 @@ func (r *RoutesHandler) TransformToWebService(c *gin.Context) {
logging.LogCommand(cmd)
err = r.cqrs.Commands.TransformIconRequestToWebService.Handle(cmd)
if err != nil {
var conflictErr domain.WebServiceAlreadyExistsError

View File

@ -1,15 +1,18 @@
package aws
import (
"fmt"
"io"
"os"
"path/filepath"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/twofas/2fas-server/internal/common/logging"
"io"
"os"
"path/filepath"
)
type AwsS3 struct {
@ -44,27 +47,16 @@ func (s *AwsS3) Get(path string) (file *os.File, err error) {
downloader := s3manager.NewDownloader(sess)
f, err := os.Create(name)
if err != nil {
logging.WithFields(logging.Fields{
"error": err.Error(),
"file": f.Name(),
}).Error("Cannot create file")
return nil, fmt.Errorf("failed to create file: %w", err)
}
_, err = downloader.Download(f, &s3.GetObjectInput{
Bucket: aws.String(directory),
Key: aws.String(name),
})
if err != nil {
logging.WithFields(logging.Fields{
"error": err.Error(),
"bucket": directory,
"filename": name,
}).Error("Cannot download file")
return nil, err
return nil, fmt.Errorf("failed to download the object from s3: %w", err)
}
return f, nil