BREAKING CHANGE: V2 of thr SDK #12

Merged
fenpaws merged 124 commits from develop/postgresql into main 2024-07-01 20:46:28 +00:00
8 changed files with 324 additions and 150 deletions
Showing only changes of commit d94ae83c2f - Show all commits

View File

@ -1,7 +0,0 @@
package error
type MissingAnthrovePostIDError struct{}
func (e *MissingAnthrovePostIDError) Error() string {
return "AnthrovePostID is empty"
}

View File

@ -3,24 +3,29 @@ package postgres
import ( import (
"context" "context"
"errors" "errors"
errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors"
error2 "git.dragse.it/anthrove/otter-space-sdk/error"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error { func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error {
result := db.WithContext(ctx).Create(&anthrovePost)
if result.RowsAffected == 0 { if anthrovePost == nil {
return &error2.NoDataWritten{} return &errors2.EntityValidationFailed{Reason: "anthrovePost is nil"}
} }
result := db.WithContext(ctx).Create(&anthrovePost)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrDuplicatedKey) { if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
return &error2.EntityAlreadyExists{} return &errors2.EntityAlreadyExists{}
} }
return result.Error
}
if result.RowsAffected == 0 {
return &errors2.NoDataWritten{}
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -32,44 +37,58 @@ func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) err
} }
func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID) (*models.Post, error) { func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID) (*models.Post, error) {
if anthrovePostID == "" { if anthrovePostID == "" {
return nil, &error2.MissingAnthrovePostIDError{} return nil, &errors2.EntityValidationFailed{Reason: "anthrovePostID is not set"}
} }
//TODO maybe check ofor id length too...?
var post models.Post var post models.Post
result := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID) result := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &error2.NoDataFound{} return nil, &errors2.NoDataFound{}
} }
return nil, result.Error
} }
return &post, nil return &post, nil
} }
func GetPostByURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.Post, error) { func GetPostByURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.Post, error) {
var post models.Post
err := db.WithContext(ctx).Raw(`SELECT p.id AS id, p.rating as rating FROM "Post" AS p INNER JOIN "PostReference" AS pr ON p.id = pr.post_id AND pr.url = $1 LIMIT 1`, sourceURL).First(&post).Error
if err != nil { if sourceURL == "" {
if errors.Is(err, gorm.ErrRecordNotFound) { return nil, &errors2.EntityValidationFailed{Reason: "sourceURL is not set"}
fenpaws marked this conversation as resolved Outdated

didn't we call the sourceURL not postUrl or so?
Something, so we don't mix it up with domainUrl or sourceDomain...

didn't we call the sourceURL not postUrl or so? Something, so we don't mix it up with domainUrl or sourceDomain...
return nil, nil }
var post models.Post
result := db.WithContext(ctx).Raw(`SELECT p.id AS id, p.rating as rating FROM "Post" AS p INNER JOIN "PostReference" AS pr ON p.id = pr.post_id AND pr.url = $1 LIMIT 1`, sourceURL).First(&post)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &errors2.NoDataFound{}
} }
return nil, err return nil, result.Error
} }
return &post, nil return &post, nil
} }
func GetPostBySourceID(ctx context.Context, db *gorm.DB, sourceID models.AnthroveSourceID) (*models.Post, error) { func GetPostBySourceID(ctx context.Context, db *gorm.DB, sourceID models.AnthroveSourceID) (*models.Post, error) {
var post models.Post
err := db.WithContext(ctx).Raw(`SELECT p.id AS id, p.rating as rating FROM "Post" AS p INNER JOIN "PostReference" AS pr ON p.id = pr.post_id AND pr.source_id = $1 LIMIT 1`, sourceID).First(&post).Error
if err != nil { if sourceID == "" {
if errors.Is(err, gorm.ErrRecordNotFound) { return nil, &errors2.EntityValidationFailed{Reason: "sourceID is not set"}
return nil, nil }
var post models.Post
result := db.WithContext(ctx).Raw(`SELECT p.id AS id, p.rating as rating FROM "Post" AS p INNER JOIN "PostReference" AS pr ON p.id = pr.post_id AND pr.source_id = $1 LIMIT 1`, sourceID).First(&post)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &errors2.NoDataFound{}
} }
return nil, err return nil, result.Error
} }
return &post, nil return &post, nil

View File

@ -2,6 +2,8 @@ package postgres
import ( import (
"context" "context"
"errors"
errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
@ -9,23 +11,44 @@ import (
func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error {
var source models.Source var source models.Source
var err error
if anthrovePostID == "" {
return &errors2.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"}
}
if len(anthrovePostID) != 25 {
return &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"}
}
if sourceDomain == "" {
return &errors2.EntityValidationFailed{Reason: "sourceDomain cannot be empty"}
}
// Find the source // Find the source
err = db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&source).Error result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&source)
if err != nil { if result.Error != nil {
return err if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return &errors2.NoDataFound{}
}
return result.Error
} }
// Establish the relationship // Establish the relationship
err = db.WithContext(ctx).Create(models.PostReference{ result = db.WithContext(ctx).Create(models.PostReference{
PostID: string(anthrovePostID), PostID: string(anthrovePostID),
SourceID: string(source.ID), SourceID: string(source.ID),
URL: string(sourceDomain), URL: string(sourceDomain),
}).Error })
if err != nil { if result.Error != nil {
return err if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
return &errors2.EntityAlreadyExists{}
}
return result.Error
}
if result.RowsAffected == 0 {
return &errors2.NoDataWritten{}
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -37,14 +60,34 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr
} }
func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error {
if anthrovePostID == "" {
return &errors2.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"}
}
if len(anthrovePostID) != 25 {
return &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"}
}
if anthroveUserID == "" {
return &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
}
userFavorite := models.UserFavorites{ userFavorite := models.UserFavorites{
UserID: string(anthroveUserID), UserID: string(anthroveUserID),
PostID: string(anthrovePostID), PostID: string(anthrovePostID),
} }
err := db.WithContext(ctx).Create(&userFavorite).Error result := db.WithContext(ctx).Create(&userFavorite)
if err != nil { if result.Error != nil {
return err if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
return &errors2.EntityAlreadyExists{}
}
return result.Error
}
if result.RowsAffected == 0 {
return &errors2.NoDataWritten{}
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -57,9 +100,25 @@ func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthrov
func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) {
var count int64 var count int64
err := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count).Error
if err != nil { if anthrovePostID == "" {
return false, err return false, &errors2.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"}
}
if len(anthrovePostID) != 25 {
return false, &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"}
}
if anthroveUserID == "" {
return false, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
}
result := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return false, &errors2.NoDataFound{}
}
return false, result.Error
} }
exists := count > 0 exists := count > 0

View File

@ -2,7 +2,8 @@ package postgres
import ( import (
"context" "context"
"fmt" "errors"
errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -13,15 +14,22 @@ import (
func CreateSource(ctx context.Context, db *gorm.DB, anthroveSource *models.Source) error { func CreateSource(ctx context.Context, db *gorm.DB, anthroveSource *models.Source) error {
if anthroveSource.Domain == "" { if anthroveSource.Domain == "" {
return fmt.Errorf("anthroveSource domain is required") return &errors2.EntityValidationFailed{Reason: "Domain is required"}
} }
result := db.WithContext(ctx).Where(models.Source{Domain: anthroveSource.Domain}).FirstOrCreate(anthroveSource) result := db.WithContext(ctx).Where(models.Source{Domain: anthroveSource.Domain}).FirstOrCreate(anthroveSource)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
return &errors2.EntityAlreadyExists{}
}
return result.Error return result.Error
} }
if result.RowsAffected == 0 {
return &errors2.NoDataWritten{}
}
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"node_source_url": anthroveSource.Domain, "node_source_url": anthroveSource.Domain,
"node_source_displayName": anthroveSource.DisplayName, "node_source_displayName": anthroveSource.DisplayName,
@ -38,6 +46,9 @@ func GetAllSource(ctx context.Context, db *gorm.DB) ([]models.Source, error) {
result := db.WithContext(ctx).Find(&sources) result := db.WithContext(ctx).Find(&sources)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &errors2.NoDataFound{}
} // TODO really...? i don't think this error handling should be here..? / not possible
return nil, result.Error return nil, result.Error
} }
@ -53,12 +64,15 @@ func GetSourceByDomain(ctx context.Context, db *gorm.DB, sourceDomain models.Ant
var sources models.Source var sources models.Source
if sourceDomain == "" { if sourceDomain == "" {
return nil, fmt.Errorf("domain is required") return nil, &errors2.EntityValidationFailed{Reason: "AnthroveSourceDomain is not set"}
} }
result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&sources) result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&sources)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &errors2.NoDataFound{}
}
return nil, result.Error return nil, result.Error
} }

View File

@ -2,7 +2,8 @@ package postgres
import ( import (
"context" "context"
"fmt" "errors"
errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
@ -10,10 +11,20 @@ import (
func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error {
resultTag := db.WithContext(ctx).Where(tag).Create(tag) if tag == nil {
return &errors2.EntityValidationFailed{Reason: "Tag is nil"}
}
if resultTag.Error != nil { result := db.WithContext(ctx).Where(tag).Create(tag)
return resultTag.Error if result.Error != nil {
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
return &errors2.EntityAlreadyExists{}
}
return result.Error
}
if result.RowsAffected == 0 {
return &errors2.NoDataWritten{}
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -24,30 +35,36 @@ func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error {
return nil return nil
} }
func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, PostID models.AnthrovePostID, tag *models.Tag) error { func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, tag *models.Tag) error {
if PostID == "" { if anthrovePostID == "" {
return fmt.Errorf("PostID is empty") return &errors2.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"}
}
if len(anthrovePostID) != 25 {
return &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"}
} }
if tag == nil { if tag == nil {
return fmt.Errorf("tag is nill") return &errors2.EntityValidationFailed{Reason: "Tag is nil"}
} }
pgPost := models.Post{ pgPost := models.Post{
BaseModel: models.BaseModel[models.AnthrovePostID]{ BaseModel: models.BaseModel[models.AnthrovePostID]{
ID: PostID, ID: anthrovePostID,
}, },
} }
err := db.WithContext(ctx).Model(&pgPost).Association("Tags").Append(tag) err := db.WithContext(ctx).Model(&pgPost).Association("Tags").Append(tag)
if err != nil { if err != nil {
return err if errors.Is(err, gorm.ErrRecordNotFound) {
return &errors2.NoDataFound{}
}
return errors.Join(err, &errors2.NoRelationCreated{})
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"anthrove_post_id": PostID, "anthrove_post_id": anthrovePostID,
"tag_name": tag.Name, "tag_name": tag.Name,
"tag_type": tag.Type, "tag_type": tag.Type,
}).Trace("database: created tag node") }).Trace("database: created tag node")
@ -57,8 +74,13 @@ func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, PostID models
func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) { func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) {
var tags []models.Tag var tags []models.Tag
result := db.WithContext(ctx).Find(&tags) result := db.WithContext(ctx).Find(&tags)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { // TODO really...? i don't think this error handling should be here..? / not possible
return nil, &errors2.NoDataFound{}
}
return nil, result.Error return nil, result.Error
} }

View File

@ -2,7 +2,8 @@ package postgres
import ( import (
"context" "context"
"fmt" "errors"
errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors"
"git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
@ -11,7 +12,11 @@ import (
func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error {
if anthroveUserID == "" { if anthroveUserID == "" {
return fmt.Errorf("anthroveUserID cannot be empty") return &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
}
if len(anthroveUserID) != 25 {
return &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"}
} }
user := models.User{ user := models.User{
@ -20,12 +25,16 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove
}, },
} }
err := db.WithContext(ctx).FirstOrCreate(&user).Error result := db.WithContext(ctx).FirstOrCreate(&user)
if err != nil { if result.Error != nil {
log.WithFields(log.Fields{ if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
"anthrove_user_id": anthroveUserID, return &errors2.EntityAlreadyExists{}
}).Error("database: failed to create user") }
return err return result.Error
}
if result.RowsAffected == 0 {
return &errors2.NoDataWritten{}
} }
return nil return nil
@ -34,15 +43,19 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove
func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error { func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error {
if anthroveUserID == "" { if anthroveUserID == "" {
return fmt.Errorf("anthroveUserID cannot be empty") return &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
}
if len(anthroveUserID) != 25 {
return &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"}
} }
if accountId == "" { if accountId == "" {
return fmt.Errorf("account_id cannot be empty") return &errors2.EntityValidationFailed{Reason: "accountID cannot be empty"}
} }
if accountUsername == "" { if accountUsername == "" {
return fmt.Errorf("account_username cannot be empty") return &errors2.EntityValidationFailed{Reason: "accountUsername cannot be empty"}
} }
err := CreateUser(ctx, db, anthroveUserID) err := CreateUser(ctx, db, anthroveUserID)
@ -54,11 +67,12 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs
BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: sourceID}, BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: sourceID},
} }
if err := db.WithContext(ctx).Where(&source).First(&source).Error; err != nil { result := db.WithContext(ctx).Where(&source).First(&source)
log.WithFields(log.Fields{ if result.Error != nil {
"source_id": sourceID, if errors.Is(result.Error, gorm.ErrRecordNotFound) {
}).Error("database: failed to find source") return &errors2.NoDataFound{}
return err }
return result.Error
} }
userSource := models.UserSource{ userSource := models.UserSource{
@ -69,14 +83,13 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs
UserID: string(anthroveUserID), UserID: string(anthroveUserID),
} }
if err := db.WithContext(ctx).FirstOrCreate(&userSource).Error; err != nil { result = db.WithContext(ctx).FirstOrCreate(&userSource)
log.WithFields(log.Fields{ if result.Error != nil {
"anthrove_user_id": anthroveUserID, return errors.Join(result.Error, &errors2.NoRelationCreated{})
"source_id": sourceID, }
"account_username": accountUsername,
"account_id": accountId, if result.RowsAffected == 0 {
}).Error("database: failed to create user-source relationship") return &errors2.NoDataWritten{}
return err
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -90,17 +103,22 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs
} }
func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (int64, error) { func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (int64, error) {
var count int64
if anthroveUserID == "" { if anthroveUserID == "" {
return 0, fmt.Errorf("anthroveUserID cannot be empty") return 0, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
} }
var count int64 if len(anthroveUserID) != 25 {
err := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Count(&count).Error return 0, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"}
if err != nil { }
log.WithFields(log.Fields{
"anthrove_user_id": anthroveUserID, result := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Count(&count)
}).Error("database: failed to get user favorites count") if result.Error != nil {
return 0, err if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return 0, &errors2.NoDataFound{}
}
return 0, result.Error
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -115,22 +133,30 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models.
var userSources []models.UserSource var userSources []models.UserSource
userSourceMap := make(map[string]models.UserSource) userSourceMap := make(map[string]models.UserSource)
err := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error if anthroveUserID == "" {
if err != nil { return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
log.WithFields(log.Fields{ }
"anthrove_user_id": anthroveUserID,
}).Error("database: failed to get user source link") if len(anthroveUserID) != 25 {
return nil, err return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"}
}
result := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &errors2.NoDataFound{}
}
return nil, result.Error
} }
for _, userSource := range userSources { for _, userSource := range userSources {
var source models.Source var source models.Source
err = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source)
if err != nil { if result.Error != nil {
log.WithFields(log.Fields{ if errors.Is(result.Error, gorm.ErrRecordNotFound) {
"source_id": userSource.SourceID, return nil, &errors2.NoDataFound{}
}).Error("database: failed to get source") }
return nil, err return nil, result.Error
} }
userSourceMap[source.DisplayName] = models.UserSource{ userSourceMap[source.DisplayName] = models.UserSource{
@ -152,34 +178,41 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models.
} }
func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) { func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) {
if anthroveUserID == "" {
return nil, fmt.Errorf("anthroveUserID cannot be empty")
}
if sourceID == "" {
return nil, fmt.Errorf("sourceID cannot be empty")
}
var userSources []models.UserSource var userSources []models.UserSource
userSourceMap := make(map[string]models.UserSource) userSourceMap := make(map[string]models.UserSource)
err := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("id = ?", sourceID)).Where("user_id = ?", string(anthroveUserID)).First(&userSources).Error if anthroveUserID == "" {
if err != nil { return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
log.WithFields(log.Fields{ }
"anthrove_user_id": anthroveUserID,
"source_id": sourceID, if len(anthroveUserID) != 25 {
}).Error("database: failed to get specified user source link") return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"}
return nil, err }
if sourceID == "" {
return nil, &errors2.EntityValidationFailed{Reason: "sourceID cannot be empty"}
}
if len(sourceID) != 25 {
return nil, &errors2.EntityValidationFailed{Reason: "sourceID needs to be 25 characters long"}
}
result := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("id = ?", sourceID)).Where("user_id = ?", string(anthroveUserID)).First(&userSources)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &errors2.NoDataFound{}
}
return nil, result.Error
} }
for _, userSource := range userSources { for _, userSource := range userSources {
var source models.Source var source models.Source
err = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source)
if err != nil { if result.Error != nil {
log.WithFields(log.Fields{ if errors.Is(result.Error, gorm.ErrRecordNotFound) {
"source_id": userSource.SourceID, return nil, &errors2.NoDataFound{}
}).Error("database: failed to get source") }
return nil, err return nil, result.Error
} }
userSourceMap[source.DisplayName] = models.UserSource{ userSourceMap[source.DisplayName] = models.UserSource{
@ -205,14 +238,16 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU
var users []models.User var users []models.User
var userIDs []models.AnthroveUserID var userIDs []models.AnthroveUserID
err := db.WithContext(ctx).Model(&models.User{}).Find(&users).Error result := db.WithContext(ctx).Model(&models.User{}).Find(&users)
if err != nil { if result.Error != nil {
log.Error("database: failed to get all anthrove user IDs") if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, err return nil, &errors2.NoDataFound{}
}
return nil, result.Error
} }
for _, user := range users { for _, user := range users {
userIDs = append(userIDs, models.AnthroveUserID(user.ID)) userIDs = append(userIDs, user.ID)
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -226,13 +261,19 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse
var userFavorites []models.UserFavorites var userFavorites []models.UserFavorites
var favoritePosts []models.Post var favoritePosts []models.Post
if anthroveUserID == "" {
return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
}
if len(anthroveUserID) != 25 {
return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"}
}
err := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error err := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error
if err != nil { if err != nil {
log.WithFields(log.Fields{ if errors.Is(err, gorm.ErrRecordNotFound) {
"anthrove_user_id": anthroveUserID, return nil, &errors2.NoDataFound{}
"skip": skip, }
"limit": limit,
}).Error("database: failed to get user favorites with pagination")
return nil, err return nil, err
} }
@ -240,9 +281,9 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse
var post models.Post var post models.Post
err = db.WithContext(ctx).Model(&models.Post{}).Where("id = ?", userFavorite.PostID).First(&post).Error err = db.WithContext(ctx).Model(&models.Post{}).Where("id = ?", userFavorite.PostID).First(&post).Error
if err != nil { if err != nil {
log.WithFields(log.Fields{ if errors.Is(err, gorm.ErrRecordNotFound) {
"post_id": userFavorite.PostID, return nil, &errors2.NoDataFound{}
}).Error("database: failed to get post") }
return nil, err return nil, err
} }
@ -263,12 +304,21 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse
func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) {
var userFavorites []models.UserFavorites var userFavorites []models.UserFavorites
err := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites).Error
if err != nil { if anthroveUserID == "" {
log.WithFields(log.Fields{ return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"}
"anthrove_user_id": anthroveUserID, }
}).Error("database: failed to get user favorites")
return nil, err if len(anthroveUserID) != 25 {
return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"}
}
result := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, &errors2.NoDataFound{}
}
return nil, result.Error
} }
tagFrequency := make(map[struct { tagFrequency := make(map[struct {
@ -278,12 +328,12 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov
for _, userFavorite := range userFavorites { for _, userFavorite := range userFavorites {
var post models.Post var post models.Post
err = db.WithContext(ctx).Preload("Tags").First(&post, "id = ?", userFavorite.PostID).Error result = db.WithContext(ctx).Preload("Tags").First(&post, "id = ?", userFavorite.PostID)
if err != nil { if result.Error != nil {
log.WithFields(log.Fields{ if errors.Is(result.Error, gorm.ErrRecordNotFound) {
"post_id": userFavorite.PostID, return nil, &errors2.NoDataFound{}
}).Error("database: failed to get post tags") }
return nil, err return nil, result.Error
} }
for _, tag := range post.Tags { for _, tag := range post.Tags {

View File

@ -1,19 +1,25 @@
package error package errors
type EntityAlreadyExists struct{} type EntityAlreadyExists struct{}
type NoDataWritten struct{}
type NoDataFound struct{}
func (e *EntityAlreadyExists) Error() string { func (e *EntityAlreadyExists) Error() string {
return "EntityAlreadyExists error" return "EntityAlreadyExists error"
} }
type NoDataWritten struct{}
func (e *NoDataWritten) Error() string { func (e *NoDataWritten) Error() string {
return "NoDataWritten error" return "NoDataWritten error"
} }
type NoDataFound struct{}
func (e *NoDataFound) Error() string { func (e *NoDataFound) Error() string {
return "NoDataFound error" return "NoDataFound error"
} }
type NoRelationCreated struct{}
func (e *NoRelationCreated) Error() string {
return "relationship creation error"
}

11
pkg/errors/validation.go Normal file
View File

@ -0,0 +1,11 @@
package errors
import "fmt"
type EntityValidationFailed struct {
Reason string
}
func (e EntityValidationFailed) Error() string {
return fmt.Sprintf("Entity validation failed: %s", e.Reason)
}