From 5015749f707dcdb1d91788bc459a53af88003949 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 3 Jun 2024 19:31:25 +0200 Subject: [PATCH 001/124] chore: streamline the naming to indicate more than graph support Signed-off-by: SoXX --- README.md | 22 +++++------ go.mod | 7 +++- go.sum | 6 +++ internal/logger.go | 8 ++-- internal/post.go | 4 +- internal/relationships.go | 6 +-- internal/source.go | 8 ++-- internal/tag.go | 4 +- internal/user.go | 16 ++++---- pkg/{graph/graph.go => database/database.go} | 38 +++++++++---------- pkg/{graph/impl.go => database/graph_impl.go} | 2 +- 11 files changed, 66 insertions(+), 55 deletions(-) rename pkg/{graph/graph.go => database/database.go} (86%) rename pkg/{graph/impl.go => database/graph_impl.go} (99%) diff --git a/README.md b/README.md index 126a1b6..732fd42 100644 --- a/README.md +++ b/README.md @@ -17,20 +17,20 @@ Here's a simple usage example: package main import ( - "context" - "fmt" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/graph" + "context" + "fmt" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/database" ) func main() { - client := graph.NewGraphConnection() - err := client.Connect(context.Background(), "your-endpoint", "your-username", "your-password") - if err != nil { - fmt.Println(err) - return - } - // further usage of the client... + client := graph.NewGraphConnection() + err := client.Connect(context.Background(), "your-endpoint", "your-username", "your-password") + if err != nil { + fmt.Println(err) + return + } + // further usage of the client... } ``` diff --git a/go.mod b/go.mod index 8593a08..37b8e64 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,9 @@ require ( github.com/sirupsen/logrus v1.9.3 ) -require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect +require ( + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect + gorm.io/gorm v1.25.10 // indirect +) diff --git a/go.sum b/go.sum index b7d2bdf..a7307ff 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,10 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/neo4j/neo4j-go-driver/v5 v5.17.0 h1:Bdqg1Y8Hd3uLYToXtBjysDYXTdMiP7zeUNUEwfbJkSo= github.com/neo4j/neo4j-go-driver/v5 v5.17.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -15,3 +19,5 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= +gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= diff --git a/internal/logger.go b/internal/logger.go index 446869d..5522934 100644 --- a/internal/logger.go +++ b/internal/logger.go @@ -19,21 +19,21 @@ func (n graphLogger) Error(name string, id string, err error) { log.WithFields(log.Fields{ "name": name, "id": id, - }).Errorf("graph: %s", err) + }).Errorf("database: %s", err) } func (n graphLogger) Warnf(name string, id string, msg string, args ...any) { log.WithFields(log.Fields{ "name": name, "id": id, - }).Warnf("graph: %v", fmt.Sprintf(msg, args...)) + }).Warnf("database: %v", fmt.Sprintf(msg, args...)) } func (n graphLogger) Infof(name string, id string, msg string, args ...any) { log.WithFields(log.Fields{ "name": name, "id": id, - }).Infof("graph: %v", fmt.Sprintf(msg, args...)) + }).Infof("database: %v", fmt.Sprintf(msg, args...)) } func (n graphLogger) Debugf(name string, id string, msg string, args ...any) { @@ -41,6 +41,6 @@ func (n graphLogger) Debugf(name string, id string, msg string, args ...any) { log.WithFields(log.Fields{ "name": name, "id": id, - }).Debugf("graph: %v", fmt.Sprintf(msg, args...)) + }).Debugf("database: %v", fmt.Sprintf(msg, args...)) } } diff --git a/internal/post.go b/internal/post.go index 021a841..78136ac 100644 --- a/internal/post.go +++ b/internal/post.go @@ -26,7 +26,7 @@ func CreateAnthrovePostNode(ctx context.Context, driver neo4j.DriverWithContext, log.WithFields(log.Fields{ "anthrove_post_id": anthrovePost.PostID, "anthrove_post_rating": anthrovePost.Rating, - }).Trace("graph: created anthrove post") + }).Trace("database: created anthrove post") return nil } @@ -106,7 +106,7 @@ func executeCheckQuery(ctx context.Context, driver neo4j.DriverWithContext, quer log.WithFields(log.Fields{ "anthrove_post_id": anthrovePost.PostID, "anthrove_post_exists": exists, - }).Trace("graph: checked if post exists") + }).Trace("database: checked if post exists") if !exists { return nil, exists, nil diff --git a/internal/relationships.go b/internal/relationships.go index 7e18bca..6d12ddc 100644 --- a/internal/relationships.go +++ b/internal/relationships.go @@ -33,7 +33,7 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, driver neo4j.DriverW "anthrove_post_id": anthrovePostID, "source_post_url": anthrovePostRelationship.Url, "source_post_id": anthrovePostRelationship.PostID, - }).Trace("graph: creating anthrove post to source link") + }).Trace("database: creating anthrove post to source link") return nil } @@ -59,7 +59,7 @@ func EstablishUserToPostLink(ctx context.Context, driver neo4j.DriverWithContext log.WithFields(log.Fields{ "anthrove_post_id": anthrovePost.PostID, "anthrove_user_id": anthroveUser.UserID, - }).Trace("graph: created user to post link") + }).Trace("database: created user to post link") return nil } @@ -94,7 +94,7 @@ func CheckUserToPostLink(ctx context.Context, driver neo4j.DriverWithContext, an "relationship_exists": exists, "relationship_anthrove_user_id": anthroveUserID, "relationship_e621_post_id": "", - }).Trace("graph: checked user post relationship") + }).Trace("database: checked user post relationship") return exists, nil } diff --git a/internal/source.go b/internal/source.go index bb91fdf..e3c36a6 100644 --- a/internal/source.go +++ b/internal/source.go @@ -22,14 +22,14 @@ func CreateSourceNode(ctx context.Context, driver neo4j.DriverWithContext, anthr _, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) if err != nil { - return fmt.Errorf("graph: %w", err) + return fmt.Errorf("database: %w", err) } log.WithFields(log.Fields{ "node_source_url": anthroveSource.Domain, "node_source_displayName": anthroveSource.DisplayName, "node_source_icon": anthroveSource.Icon, - }).Trace("graph: created source node") + }).Trace("database: created source node") return nil } @@ -70,7 +70,7 @@ func GetAllSourceNodes(ctx context.Context, driver neo4j.DriverWithContext) ([]m log.WithFields(log.Fields{ "tag_amount": len(sources), - }).Trace("graph: created tag node") + }).Trace("database: created tag node") return sources, nil } @@ -107,7 +107,7 @@ func GetSourceNodesByURL(ctx context.Context, driver neo4j.DriverWithContext, so log.WithFields(log.Fields{ "source_url": sourceUrl, - }).Trace("graph: got source node") + }).Trace("database: got source node") return &source, nil } diff --git a/internal/tag.go b/internal/tag.go index 3e5a02d..b91d1cb 100644 --- a/internal/tag.go +++ b/internal/tag.go @@ -29,7 +29,7 @@ func CreateTagNodeWitRelation(ctx context.Context, driver neo4j.DriverWithContex "anthrove_post_id": anthrovePostID, "tag_name": anthroveTag.Name, "tag_type": anthroveTag.Type, - }).Trace("graph: created tag node") + }).Trace("database: created tag node") return nil } @@ -78,7 +78,7 @@ func GetTags(ctx context.Context, driver neo4j.DriverWithContext) ([]models.Tags log.WithFields(log.Fields{ "tag_amount": len(userTags), - }).Trace("graph: created tag node") + }).Trace("database: created tag node") return userTags, nil } diff --git a/internal/user.go b/internal/user.go index a1128ec..5e9fe4d 100644 --- a/internal/user.go +++ b/internal/user.go @@ -46,7 +46,7 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, driver neo4j.DriverWi "source_user_id": userID, "source_user_name": username, "source_domain": sourceDomain, - }).Trace("graph: crated user with relationship") + }).Trace("database: crated user with relationship") return nil } @@ -85,7 +85,7 @@ func GetUserFavoritesCount(ctx context.Context, driver neo4j.DriverWithContext, log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, "anthrove_user_fav_count": userFavoriteCount, - }).Trace("graph: got user favorite count") + }).Trace("database: got user favorite count") return userFavoriteCount, nil } @@ -145,7 +145,7 @@ func GetUserSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anth log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, "anthrove_data": userSource, - }).Trace("graph: got user favorite count") + }).Trace("database: got user favorite count") return userSource, nil } @@ -206,7 +206,7 @@ func GetSpecifiedUserSourceLink(ctx context.Context, driver neo4j.DriverWithCont log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, "anthrove_data": userSource, - }).Trace("graph: got user favorite count") + }).Trace("database: got user favorite count") return userSource, nil } @@ -273,7 +273,7 @@ func GetAnthroveUser(ctx context.Context, driver neo4j.DriverWithContext, anthro log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, - }).Trace("graph: got anthrove user") + }).Trace("database: got anthrove user") return &anthroveUser, nil @@ -310,7 +310,7 @@ func GetAllAnthroveUserIDs(ctx context.Context, driver neo4j.DriverWithContext) log.WithFields(log.Fields{ "anthrove_user_id_count": len(anthroveUsers), - }).Trace("graph: got al anthrove user IDs") + }).Trace("database: got al anthrove user IDs") return anthroveUsers, nil @@ -396,7 +396,7 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverW log.WithFields(log.Fields{ "anthrove_user_fav_count": len(favoritePosts), - }).Trace("graph: got al anthrove user favorites") + }).Trace("database: got al anthrove user favorites") return &models.FavoriteList{Posts: favoritePosts}, nil @@ -448,7 +448,7 @@ func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, driver neo4j.Dri log.WithFields(log.Fields{ "tag_amount": len(userTags), - }).Trace("graph: created tag node") + }).Trace("database: created tag node") return userTags, nil } diff --git a/pkg/graph/graph.go b/pkg/database/database.go similarity index 86% rename from pkg/graph/graph.go rename to pkg/database/database.go index 3cd7630..867e72a 100644 --- a/pkg/graph/graph.go +++ b/pkg/database/database.go @@ -1,4 +1,4 @@ -// Package graph provides a client for using the OtterSpace API. +// Package database provides a client for using the OtterSpace API. // // This package provides a client to interact with the OtterSpace API. It includes // methods for all API endpoints, and convenience methods for common tasks. @@ -11,11 +11,11 @@ // "context" // "fmt" // "git.dragse.it/anthrove/otter-space-sdk/pkg/models" -// "git.dragse.it/anthrove/otter-space-sdk/pkg/graph" +// "git.dragse.it/anthrove/otter-space-sdk/pkg/database" // ) // // func main() { -// client := graph.NewGraphConnection() +// client := database.NewGraphConnection() // err := client.Connect(context.Background(), "your-endpoint", "your-username", "your-password") // if err != nil { // fmt.Println(err) @@ -23,7 +23,7 @@ // } // // further usage of the client... // } -package graph +package database import ( "context" @@ -39,63 +39,63 @@ type OtterSpace interface { // It returns an error if the connection cannot be established. Connect(ctx context.Context, endpoint string, username string, password string) error - // AddUserWithRelationToSource adds a new user to the OtterSpace graph and associates them with a source. + // AddUserWithRelationToSource adds a new user to the OtterSpace database and associates them with a source. // It returns the newly created user and an error if the operation fails. AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error - // AddSource adds a new source to the OtterSpace graph. + // AddSource adds a new source to the OtterSpace database. // It returns an error if the operation fails. AddSource(ctx context.Context, anthroveSource *models.AnthroveSource) error - // AddPost adds a new post to the OtterSpace graph. + // AddPost adds a new post to the OtterSpace database. // It returns an error if the operation fails. AddPost(ctx context.Context, anthrovePost *models.AnthrovePost) error - // AddTagWithRelationToPost adds a new tag to the OtterSpace graph and associates it with a post. + // AddTagWithRelationToPost adds a new tag to the OtterSpace database and associates it with a post. // It returns an error if the operation fails. AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.AnthroveTag) error - // LinkPostWithSource establishes a link between a post and a source in the OtterSpace graph. + // LinkPostWithSource establishes a link between a post and a source in the OtterSpace database. // It returns an error if the operation fails. LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.AnthrovePostRelationship) error - // LinkUserWithPost establishes a link between a user and a post in the OtterSpace graph. + // LinkUserWithPost establishes a link between a user and a post in the OtterSpace database. // It returns an error if the operation fails. LinkUserWithPost(ctx context.Context, anthroveUser *models.AnthroveUser, anthrovePost *models.AnthrovePost) error - // CheckUserPostLink checks if a link between a user and a post exists in the OtterSpace graph. + // CheckUserPostLink checks if a link between a user and a post exists in the OtterSpace database. // It returns true if the link exists, false otherwise, and an error if the operation fails. CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) - // CheckPostNodeExistsByAnthroveID checks if a post node exists in the OtterSpace graph by its Anthrove ID. + // CheckPostNodeExistsByAnthroveID checks if a post node exists in the OtterSpace database by its Anthrove ID. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.AnthrovePost) (*models.AnthrovePost, bool, error) - // CheckPostNodeExistsBySourceURL checks if a post node exists in the OtterSpace graph by its source URL. + // CheckPostNodeExistsBySourceURL checks if a post node exists in the OtterSpace database by its source URL. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.AnthrovePost, bool, error) - // CheckPostNodeExistsBySourceID checks if a post node exists in the OtterSpace graph by its source ID. + // CheckPostNodeExistsBySourceID checks if a post node exists in the OtterSpace database by its source ID. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.AnthrovePost, bool, error) - // GetUserFavoriteCount retrieves the count of a user's favorite posts from the OtterSpace graph. + // GetUserFavoriteCount retrieves the count of a user's favorite posts from the OtterSpace database. // It returns the count and an error if the operation fails. GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) - // GetUserSourceLinks retrieves the links between a user and sources in the OtterSpace graph. + // GetUserSourceLinks retrieves the links between a user and sources in the OtterSpace database. // It returns a map of source domains to user-source relationships, and an error if the operation fails. GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.AnthroveUserRelationship, error) - // GetSpecifiedUserSourceLink GetUserSourceLinks retrieves the links between a user and a specific source in the OtterSpace graph. + // GetSpecifiedUserSourceLink GetUserSourceLinks retrieves the links between a user and a specific source in the OtterSpace database. // It returns a map of source domains to user-source relationships, and an error if the operation fails. GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.AnthroveUserRelationship, error) - // GetAnthroveUser retrieves a user from the OtterSpace graph by their ID. + // GetAnthroveUser retrieves a user from the OtterSpace database by their ID. // It returns the user and an error if the operation fails. GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.AnthroveUser, error) - // GetAllAnthroveUserIDs retrieves all user IDs from the OtterSpace graph. + // GetAllAnthroveUserIDs retrieves all user IDs from the OtterSpace database. // It returns a slice of user IDs and an error if the operation fails. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) diff --git a/pkg/graph/impl.go b/pkg/database/graph_impl.go similarity index 99% rename from pkg/graph/impl.go rename to pkg/database/graph_impl.go index 6b1b3bb..68bc025 100644 --- a/pkg/graph/impl.go +++ b/pkg/database/graph_impl.go @@ -1,4 +1,4 @@ -package graph +package database import ( "context" From ccc6010466710ea9ad371f76c8c37492aa047d92 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 3 Jun 2024 19:32:25 +0200 Subject: [PATCH 002/124] chore: streamline the naming to indicate more than graph support Signed-off-by: SoXX --- internal/{ => graph}/logger.go | 2 +- internal/{ => graph}/post.go | 2 +- internal/{ => graph}/relationships.go | 2 +- internal/{ => graph}/source.go | 2 +- internal/{ => graph}/tag.go | 2 +- internal/{ => graph}/user.go | 2 +- pkg/database/graph_impl.go | 44 +++++++++++++-------------- 7 files changed, 28 insertions(+), 28 deletions(-) rename internal/{ => graph}/logger.go (98%) rename internal/{ => graph}/post.go (99%) rename internal/{ => graph}/relationships.go (99%) rename internal/{ => graph}/source.go (99%) rename internal/{ => graph}/tag.go (99%) rename internal/{ => graph}/user.go (99%) diff --git a/internal/logger.go b/internal/graph/logger.go similarity index 98% rename from internal/logger.go rename to internal/graph/logger.go index 5522934..914db3a 100644 --- a/internal/logger.go +++ b/internal/graph/logger.go @@ -1,4 +1,4 @@ -package internal +package graph import ( "fmt" diff --git a/internal/post.go b/internal/graph/post.go similarity index 99% rename from internal/post.go rename to internal/graph/post.go index 78136ac..6a39f51 100644 --- a/internal/post.go +++ b/internal/graph/post.go @@ -1,4 +1,4 @@ -package internal +package graph import ( "context" diff --git a/internal/relationships.go b/internal/graph/relationships.go similarity index 99% rename from internal/relationships.go rename to internal/graph/relationships.go index 6d12ddc..b77c8e6 100644 --- a/internal/relationships.go +++ b/internal/graph/relationships.go @@ -1,4 +1,4 @@ -package internal +package graph import ( "context" diff --git a/internal/source.go b/internal/graph/source.go similarity index 99% rename from internal/source.go rename to internal/graph/source.go index e3c36a6..cbdc690 100644 --- a/internal/source.go +++ b/internal/graph/source.go @@ -1,4 +1,4 @@ -package internal +package graph import ( "context" diff --git a/internal/tag.go b/internal/graph/tag.go similarity index 99% rename from internal/tag.go rename to internal/graph/tag.go index b91d1cb..0838b13 100644 --- a/internal/tag.go +++ b/internal/graph/tag.go @@ -1,4 +1,4 @@ -package internal +package graph import ( "context" diff --git a/internal/user.go b/internal/graph/user.go similarity index 99% rename from internal/user.go rename to internal/graph/user.go index 5e9fe4d..7d4a8e8 100644 --- a/internal/user.go +++ b/internal/graph/user.go @@ -1,4 +1,4 @@ -package internal +package graph import ( "context" diff --git a/pkg/database/graph_impl.go b/pkg/database/graph_impl.go index 68bc025..fac6a85 100644 --- a/pkg/database/graph_impl.go +++ b/pkg/database/graph_impl.go @@ -2,8 +2,8 @@ package database import ( "context" + "git.dragse.it/anthrove/otter-space-sdk/internal/graph" - "git.dragse.it/anthrove/otter-space-sdk/internal" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "github.com/neo4j/neo4j-go-driver/v5/neo4j" "github.com/neo4j/neo4j-go-driver/v5/neo4j/config" @@ -37,87 +37,87 @@ func (g *graphConnection) Connect(ctx context.Context, endpoint string, username } func (g *graphConnection) AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { - return internal.CreateUserNodeWithSourceRelation(ctx, g.driver, anthroveUserID, sourceDomain, userID, username) + return graph.CreateUserNodeWithSourceRelation(ctx, g.driver, anthroveUserID, sourceDomain, userID, username) } func (g *graphConnection) AddSource(ctx context.Context, anthroveSource *models.AnthroveSource) error { - return internal.CreateSourceNode(ctx, g.driver, anthroveSource) + return graph.CreateSourceNode(ctx, g.driver, anthroveSource) } func (g *graphConnection) AddPost(ctx context.Context, anthrovePost *models.AnthrovePost) error { - return internal.CreateAnthrovePostNode(ctx, g.driver, anthrovePost) + return graph.CreateAnthrovePostNode(ctx, g.driver, anthrovePost) } func (g *graphConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.AnthroveTag) error { - return internal.CreateTagNodeWitRelation(ctx, g.driver, anthrovePostID, anthroveTag) + return graph.CreateTagNodeWitRelation(ctx, g.driver, anthrovePostID, anthroveTag) } func (g *graphConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.AnthrovePostRelationship) error { - return internal.EstablishAnthrovePostToSourceLink(ctx, g.driver, anthrovePostID, anthroveSourceDomain, anthrovePostRelationship) + return graph.EstablishAnthrovePostToSourceLink(ctx, g.driver, anthrovePostID, anthroveSourceDomain, anthrovePostRelationship) } func (g *graphConnection) LinkUserWithPost(ctx context.Context, anthroveUser *models.AnthroveUser, anthrovePost *models.AnthrovePost) error { - return internal.EstablishUserToPostLink(ctx, g.driver, anthroveUser, anthrovePost) + return graph.EstablishUserToPostLink(ctx, g.driver, anthroveUser, anthrovePost) } func (g *graphConnection) CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { - return internal.CheckUserToPostLink(ctx, g.driver, anthroveUserID, sourcePostID, sourceUrl) + return graph.CheckUserToPostLink(ctx, g.driver, anthroveUserID, sourcePostID, sourceUrl) } func (g *graphConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.AnthrovePost) (*models.AnthrovePost, bool, error) { - return internal.CheckIfAnthrovePostNodeExistsByAnthroveID(ctx, g.driver, anthrovePost) + return graph.CheckIfAnthrovePostNodeExistsByAnthroveID(ctx, g.driver, anthrovePost) } func (g *graphConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.AnthrovePost, bool, error) { - return internal.CheckIfAnthrovePostNodeExistsBySourceURl(ctx, g.driver, sourceUrl) + return graph.CheckIfAnthrovePostNodeExistsBySourceURl(ctx, g.driver, sourceUrl) } func (g *graphConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.AnthrovePost, bool, error) { - return internal.CheckIfAnthrovePostNodeExistsBySourceID(ctx, g.driver, sourcePostID) + return graph.CheckIfAnthrovePostNodeExistsBySourceID(ctx, g.driver, sourcePostID) } func (g *graphConnection) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { - return internal.GetUserFavoritesCount(ctx, g.driver, anthroveUserID) + return graph.GetUserFavoritesCount(ctx, g.driver, anthroveUserID) } func (g *graphConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.AnthroveUserRelationship, error) { - return internal.GetUserSourceLink(ctx, g.driver, anthroveUserID) + return graph.GetUserSourceLink(ctx, g.driver, anthroveUserID) } func (g *graphConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.AnthroveUserRelationship, error) { - return internal.GetSpecifiedUserSourceLink(ctx, g.driver, anthroveUserID, sourceDisplayName) + return graph.GetSpecifiedUserSourceLink(ctx, g.driver, anthroveUserID, sourceDisplayName) } func (g *graphConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.AnthroveUser, error) { - return internal.GetAnthroveUser(ctx, g.driver, anthroveUserID) + return graph.GetAnthroveUser(ctx, g.driver, anthroveUserID) } func (g *graphConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { - return internal.GetAllAnthroveUserIDs(ctx, g.driver) + return graph.GetAllAnthroveUserIDs(ctx, g.driver) } func (g *graphConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { - return internal.GetUserFavoriteNodeWithPagination(ctx, g.driver, anthroveUserID, skip, limit) + return graph.GetUserFavoriteNodeWithPagination(ctx, g.driver, anthroveUserID, skip, limit) } func (g *graphConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { - return internal.GetUserTagNodeWitRelationToFavedPosts(ctx, g.driver, anthroveUserID) + return graph.GetUserTagNodeWitRelationToFavedPosts(ctx, g.driver, anthroveUserID) } func (g *graphConnection) GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) { - return internal.GetTags(ctx, g.driver) + return graph.GetTags(ctx, g.driver) } func (g *graphConnection) GetAllSources(ctx context.Context) ([]models.AnthroveSource, error) { - return internal.GetAllSourceNodes(ctx, g.driver) + return graph.GetAllSourceNodes(ctx, g.driver) } func (g *graphConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*models.AnthroveSource, error) { - return internal.GetSourceNodesByURL(ctx, g.driver, sourceUrl) + return graph.GetSourceNodesByURL(ctx, g.driver, sourceUrl) } func logger(graphDebug bool) func(config *config.Config) { return func(config *config.Config) { - config.Log = internal.NewGraphLogger(graphDebug) + config.Log = graph.NewGraphLogger(graphDebug) } } From 0d5274eb27ed14c7443ac8172f193cfe4257accb Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 3 Jun 2024 21:31:44 +0200 Subject: [PATCH 003/124] feat: connecting to postgres now possible Signed-off-by: SoXX --- go.mod | 10 ++- go.sum | 22 +++++- pkg/database/database.go | 2 +- pkg/database/graph_impl.go | 2 +- pkg/database/postgresql_impl.go | 130 ++++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 pkg/database/postgresql_impl.go diff --git a/go.mod b/go.mod index 37b8e64..dc9cdf6 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,17 @@ go 1.22.0 require ( github.com/neo4j/neo4j-go-driver/v5 v5.17.0 github.com/sirupsen/logrus v1.9.3 + gorm.io/driver/postgres v1.5.7 + gorm.io/gorm v1.25.10 ) require ( + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect - gorm.io/gorm v1.25.10 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect ) diff --git a/go.sum b/go.sum index a7307ff..2c77d3a 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= +github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= @@ -12,12 +18,22 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= +gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= diff --git a/pkg/database/database.go b/pkg/database/database.go index 867e72a..62f3158 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -37,7 +37,7 @@ import ( type OtterSpace interface { // Connect sets up a connection to the OtterSpace API endpoint using the provided username and password. // It returns an error if the connection cannot be established. - Connect(ctx context.Context, endpoint string, username string, password string) error + Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error // AddUserWithRelationToSource adds a new user to the OtterSpace database and associates them with a source. // It returns the newly created user and an error if the operation fails. diff --git a/pkg/database/graph_impl.go b/pkg/database/graph_impl.go index fac6a85..a48fad6 100644 --- a/pkg/database/graph_impl.go +++ b/pkg/database/graph_impl.go @@ -21,7 +21,7 @@ func NewGraphConnection(graphDebug bool) OtterSpace { } } -func (g *graphConnection) Connect(ctx context.Context, endpoint string, username string, password string) error { +func (g *graphConnection) Connect(ctx context.Context, endpoint string, username string, password string, _ string, _ int, _ string, _ string) error { driver, err := neo4j.NewDriverWithContext(endpoint, neo4j.BasicAuth(username, password, ""), logger(g.graphDebug)) diff --git a/pkg/database/postgresql_impl.go b/pkg/database/postgresql_impl.go new file mode 100644 index 0000000..96e241f --- /dev/null +++ b/pkg/database/postgresql_impl.go @@ -0,0 +1,130 @@ +package database + +import ( + "context" + "fmt" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "gorm.io/driver/postgres" + "gorm.io/gorm" +) + +type postgresqlConnection struct { + db *gorm.DB +} + +func NewPostgresqlConnection() OtterSpace { + return &postgresqlConnection{ + db: nil, + } +} + +func (p postgresqlConnection) Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error { + + dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", endpoint, username, password, database, port, ssl, timezone) + db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) + p.db = db + if err != nil { + return err + } + return nil +} + +func (p postgresqlConnection) AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) AddSource(ctx context.Context, anthroveSource *models.AnthroveSource) error { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) AddPost(ctx context.Context, anthrovePost *models.AnthrovePost) error { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.AnthroveTag) error { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.AnthrovePostRelationship) error { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *models.AnthroveUser, anthrovePost *models.AnthrovePost) error { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.AnthrovePost) (*models.AnthrovePost, bool, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.AnthrovePost, bool, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.AnthrovePost, bool, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.AnthroveUserRelationship, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.AnthroveUserRelationship, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.AnthroveUser, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetAllSources(ctx context.Context) ([]models.AnthroveSource, error) { + //TODO implement me + panic("implement me") +} + +func (p postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*models.AnthroveSource, error) { + //TODO implement me + panic("implement me") +} From c1df01d11399a643a4eec6a9507e4e299bd3d898 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 3 Jun 2024 21:45:39 +0200 Subject: [PATCH 004/124] chore: reorganizing code Signed-off-by: SoXX --- pkg/database/{graph_impl.go => graph/graph.go} | 5 +++-- pkg/database/{postgresql_impl.go => postgres/postgres.go} | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) rename pkg/database/{graph_impl.go => graph/graph.go} (97%) rename pkg/database/{postgresql_impl.go => postgres/postgres.go} (97%) diff --git a/pkg/database/graph_impl.go b/pkg/database/graph/graph.go similarity index 97% rename from pkg/database/graph_impl.go rename to pkg/database/graph/graph.go index a48fad6..81f94a8 100644 --- a/pkg/database/graph_impl.go +++ b/pkg/database/graph/graph.go @@ -1,8 +1,9 @@ -package database +package graph import ( "context" "git.dragse.it/anthrove/otter-space-sdk/internal/graph" + "git.dragse.it/anthrove/otter-space-sdk/pkg/database" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "github.com/neo4j/neo4j-go-driver/v5/neo4j" @@ -14,7 +15,7 @@ type graphConnection struct { graphDebug bool } -func NewGraphConnection(graphDebug bool) OtterSpace { +func NewGraphConnection(graphDebug bool) database.OtterSpace { return &graphConnection{ driver: nil, graphDebug: graphDebug, diff --git a/pkg/database/postgresql_impl.go b/pkg/database/postgres/postgres.go similarity index 97% rename from pkg/database/postgresql_impl.go rename to pkg/database/postgres/postgres.go index 96e241f..bac144a 100644 --- a/pkg/database/postgresql_impl.go +++ b/pkg/database/postgres/postgres.go @@ -1,8 +1,9 @@ -package database +package postgres import ( "context" "fmt" + "git.dragse.it/anthrove/otter-space-sdk/pkg/database" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -12,7 +13,7 @@ type postgresqlConnection struct { db *gorm.DB } -func NewPostgresqlConnection() OtterSpace { +func NewPostgresqlConnection() database.OtterSpace { return &postgresqlConnection{ db: nil, } From ebc7fcc571f0d1b629089a8884931ce309cafa53 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 3 Jun 2024 22:14:50 +0200 Subject: [PATCH 005/124] feat(sources): get all source nodes Signed-off-by: SoXX --- internal/postgres/source.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 internal/postgres/source.go diff --git a/internal/postgres/source.go b/internal/postgres/source.go new file mode 100644 index 0000000..6871f45 --- /dev/null +++ b/internal/postgres/source.go @@ -0,0 +1,25 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +// GetAllSourceNodes returns a list of all models.AnthroveSource +func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]models.AnthroveSource, error) { + var sources []models.AnthroveSource + + result := db.WithContext(ctx).Find(&sources) + + if result.Error != nil { + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tag_amount": result.RowsAffected, + }).Trace("database: get all source nodes") + + return sources, nil +} From ea2958b27d406cc4b3f19914bb7a1e98c2696440 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 3 Jun 2024 22:18:02 +0200 Subject: [PATCH 006/124] feat(sources): finished implementing get all sources Signed-off-by: SoXX --- pkg/database/{graph => }/graph.go | 6 ++---- pkg/database/{postgres => }/postgres.go | 13 ++++++------- 2 files changed, 8 insertions(+), 11 deletions(-) rename pkg/database/{graph => }/graph.go (97%) rename pkg/database/{postgres => }/postgres.go (94%) diff --git a/pkg/database/graph/graph.go b/pkg/database/graph.go similarity index 97% rename from pkg/database/graph/graph.go rename to pkg/database/graph.go index 81f94a8..869f643 100644 --- a/pkg/database/graph/graph.go +++ b/pkg/database/graph.go @@ -1,10 +1,8 @@ -package graph +package database import ( "context" "git.dragse.it/anthrove/otter-space-sdk/internal/graph" - "git.dragse.it/anthrove/otter-space-sdk/pkg/database" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "github.com/neo4j/neo4j-go-driver/v5/neo4j" "github.com/neo4j/neo4j-go-driver/v5/neo4j/config" @@ -15,7 +13,7 @@ type graphConnection struct { graphDebug bool } -func NewGraphConnection(graphDebug bool) database.OtterSpace { +func NewGraphConnection(graphDebug bool) OtterSpace { return &graphConnection{ driver: nil, graphDebug: graphDebug, diff --git a/pkg/database/postgres/postgres.go b/pkg/database/postgres.go similarity index 94% rename from pkg/database/postgres/postgres.go rename to pkg/database/postgres.go index bac144a..89628e6 100644 --- a/pkg/database/postgres/postgres.go +++ b/pkg/database/postgres.go @@ -1,11 +1,11 @@ -package postgres +package database import ( "context" "fmt" - "git.dragse.it/anthrove/otter-space-sdk/pkg/database" + "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "gorm.io/driver/postgres" + gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" ) @@ -13,7 +13,7 @@ type postgresqlConnection struct { db *gorm.DB } -func NewPostgresqlConnection() database.OtterSpace { +func NewPostgresqlConnection() OtterSpace { return &postgresqlConnection{ db: nil, } @@ -22,7 +22,7 @@ func NewPostgresqlConnection() database.OtterSpace { func (p postgresqlConnection) Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error { dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", endpoint, username, password, database, port, ssl, timezone) - db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) + db, err := gorm.Open(gormPostgres.Open(dsn), &gorm.Config{}) p.db = db if err != nil { return err @@ -121,8 +121,7 @@ func (p postgresqlConnection) GetAllTags(ctx context.Context) ([]models.TagsWith } func (p postgresqlConnection) GetAllSources(ctx context.Context) ([]models.AnthroveSource, error) { - //TODO implement me - panic("implement me") + return postgres.GetAllSourceNodes(ctx, p.db) } func (p postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*models.AnthroveSource, error) { From 21b43333d068b39f5576547f96796945d3371c0e Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 3 Jun 2024 23:55:30 +0200 Subject: [PATCH 007/124] feat(sources): restructure models and first implementation of pgModel Signed-off-by: SoXX --- internal/graph/post.go | 14 +-- internal/graph/relationships.go | 6 +- internal/graph/source.go | 14 +-- internal/graph/tag.go | 12 +-- internal/graph/user.go | 64 +++++++------- internal/postgres/source.go | 6 +- pkg/database/database.go | 34 ++++---- pkg/database/graph.go | 33 +++---- pkg/database/postgres.go | 33 +++---- pkg/models/README.md | 87 +++++++++++++++++++ pkg/models/const.go | 23 +++-- pkg/models/{ => graphModels}/api.go | 2 +- pkg/models/graphModels/post.go | 8 ++ pkg/models/{ => graphModels}/relationships.go | 2 +- pkg/models/{ => graphModels}/source.go | 2 +- pkg/models/{ => graphModels}/tag.go | 2 +- pkg/models/graphModels/user.go | 8 ++ pkg/models/pgModels/orm.go | 13 +++ pkg/models/pgModels/post.go | 14 +++ pkg/models/pgModels/source.go | 8 ++ pkg/models/pgModels/tag.go | 21 +++++ pkg/models/pgModels/user.go | 6 ++ pkg/models/post.go | 6 -- pkg/models/user.go | 6 -- 24 files changed, 295 insertions(+), 129 deletions(-) create mode 100644 pkg/models/README.md rename pkg/models/{ => graphModels}/api.go (95%) create mode 100644 pkg/models/graphModels/post.go rename pkg/models/{ => graphModels}/relationships.go (94%) rename pkg/models/{ => graphModels}/source.go (87%) rename pkg/models/{ => graphModels}/tag.go (80%) create mode 100644 pkg/models/graphModels/user.go create mode 100644 pkg/models/pgModels/orm.go create mode 100644 pkg/models/pgModels/post.go create mode 100644 pkg/models/pgModels/source.go create mode 100644 pkg/models/pgModels/tag.go create mode 100644 pkg/models/pgModels/user.go delete mode 100644 pkg/models/post.go delete mode 100644 pkg/models/user.go diff --git a/internal/graph/post.go b/internal/graph/post.go index 6a39f51..d263928 100644 --- a/internal/graph/post.go +++ b/internal/graph/post.go @@ -2,13 +2,13 @@ package graph import ( "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "github.com/neo4j/neo4j-go-driver/v5/neo4j" log "github.com/sirupsen/logrus" ) -func CreateAnthrovePostNode(ctx context.Context, driver neo4j.DriverWithContext, anthrovePost *models.AnthrovePost) error { +func CreateAnthrovePostNode(ctx context.Context, driver neo4j.DriverWithContext, anthrovePost *graphModels.AnthrovePost) error { query := ` CREATE (newPostNode:AnthrovePost {post_id: $anthrove_post_id, rating: $anthrove_rating}) ` @@ -31,7 +31,7 @@ func CreateAnthrovePostNode(ctx context.Context, driver neo4j.DriverWithContext, return nil } -func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, driver neo4j.DriverWithContext, anthrovePost *models.AnthrovePost) (*models.AnthrovePost, bool, error) { +func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, driver neo4j.DriverWithContext, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { query := ` OPTIONAL MATCH (postNode:AnthrovePost {post_id: $anthrove_post_id}) RETURN postNode.post_id AS AnthrovePostID @@ -49,7 +49,7 @@ func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, driver neo4j return anthrovePost, exists, nil } -func CheckIfAnthrovePostNodeExistsBySourceURl(ctx context.Context, driver neo4j.DriverWithContext, sourceUrl string) (*models.AnthrovePost, bool, error) { +func CheckIfAnthrovePostNodeExistsBySourceURl(ctx context.Context, driver neo4j.DriverWithContext, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { query := ` OPTIONAL MATCH (postNode:AnthrovePost)<-[:REFERENCE {url: $source_url}]-() RETURN postNode.post_id AS AnthrovePostID @@ -66,7 +66,7 @@ func CheckIfAnthrovePostNodeExistsBySourceURl(ctx context.Context, driver neo4j. return anthrovePost, exists, nil } -func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, driver neo4j.DriverWithContext, sourcePostID string) (*models.AnthrovePost, bool, error) { +func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, driver neo4j.DriverWithContext, sourcePostID string) (*graphModels.AnthrovePost, bool, error) { query := ` OPTIONAL MATCH (postNode:AnthrovePost)<-[:REFERENCE {source_post_id: $source_post_id}]-() RETURN postNode.post_id AS AnthrovePostID @@ -84,9 +84,9 @@ func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, driver neo4j.D return anthrovePost, exists, nil } -func executeCheckQuery(ctx context.Context, driver neo4j.DriverWithContext, query string, params map[string]any) (*models.AnthrovePost, bool, error) { +func executeCheckQuery(ctx context.Context, driver neo4j.DriverWithContext, query string, params map[string]any) (*graphModels.AnthrovePost, bool, error) { - var anthrovePost models.AnthrovePost + var anthrovePost graphModels.AnthrovePost result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) if err != nil { diff --git a/internal/graph/relationships.go b/internal/graph/relationships.go index b77c8e6..d9ea521 100644 --- a/internal/graph/relationships.go +++ b/internal/graph/relationships.go @@ -3,13 +3,13 @@ package graph import ( "context" "fmt" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "github.com/neo4j/neo4j-go-driver/v5/neo4j" log "github.com/sirupsen/logrus" ) -func EstablishAnthrovePostToSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.AnthrovePostRelationship) error { +func EstablishAnthrovePostToSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { query := ` MATCH (sourceNode:Source {domain: $source_url}) MATCH (postNode:AnthrovePost {post_id: $anthrove_post_id}) @@ -38,7 +38,7 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, driver neo4j.DriverW return nil } -func EstablishUserToPostLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUser *models.AnthroveUser, anthrovePost *models.AnthrovePost) error { +func EstablishUserToPostLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { query := ` MATCH (user:User {user_id: $anthrove_user_id}) diff --git a/internal/graph/source.go b/internal/graph/source.go index cbdc690..5ed8fa6 100644 --- a/internal/graph/source.go +++ b/internal/graph/source.go @@ -3,13 +3,13 @@ package graph import ( "context" "fmt" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "github.com/neo4j/neo4j-go-driver/v5/neo4j" log "github.com/sirupsen/logrus" ) -func CreateSourceNode(ctx context.Context, driver neo4j.DriverWithContext, anthroveSource *models.AnthroveSource) error { +func CreateSourceNode(ctx context.Context, driver neo4j.DriverWithContext, anthroveSource *graphModels.AnthroveSource) error { query := ` MERGE (sourceNode:Source {domain: $source_url}) ON CREATE SET sourceNode.domain = $source_url, sourceNode.display_name = $source_display_name, sourceNode.icon = $source_icon @@ -34,8 +34,8 @@ func CreateSourceNode(ctx context.Context, driver neo4j.DriverWithContext, anthr return nil } -func GetAllSourceNodes(ctx context.Context, driver neo4j.DriverWithContext) ([]models.AnthroveSource, error) { - var sources []models.AnthroveSource +func GetAllSourceNodes(ctx context.Context, driver neo4j.DriverWithContext) ([]graphModels.AnthroveSource, error) { + var sources []graphModels.AnthroveSource query := ` MATCH (s:Source) @@ -60,7 +60,7 @@ func GetAllSourceNodes(ctx context.Context, driver neo4j.DriverWithContext) ([]m return nil, err } - sources = append(sources, models.AnthroveSource{ + sources = append(sources, graphModels.AnthroveSource{ DisplayName: source.Props["display_name"].(string), Domain: source.Props["domain"].(string), Icon: source.Props["icon"].(string), @@ -75,9 +75,9 @@ func GetAllSourceNodes(ctx context.Context, driver neo4j.DriverWithContext) ([]m return sources, nil } -func GetSourceNodesByURL(ctx context.Context, driver neo4j.DriverWithContext, sourceUrl string) (*models.AnthroveSource, error) { +func GetSourceNodesByURL(ctx context.Context, driver neo4j.DriverWithContext, sourceUrl string) (*graphModels.AnthroveSource, error) { - var source models.AnthroveSource + var source graphModels.AnthroveSource query := ` MATCH (s:Source {domain: $source_url}) diff --git a/internal/graph/tag.go b/internal/graph/tag.go index 0838b13..cc9142c 100644 --- a/internal/graph/tag.go +++ b/internal/graph/tag.go @@ -2,13 +2,13 @@ package graph import ( "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "github.com/neo4j/neo4j-go-driver/v5/neo4j" log "github.com/sirupsen/logrus" ) -func CreateTagNodeWitRelation(ctx context.Context, driver neo4j.DriverWithContext, anthrovePostID models.AnthrovePostID, anthroveTag *models.AnthroveTag) error { +func CreateTagNodeWitRelation(ctx context.Context, driver neo4j.DriverWithContext, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { query := ` MATCH (anthrovePost:AnthrovePost {post_id: $anthrove_post_id}) MERGE (tagNode:Tag {name: $tag_name, type: $tag_type}) @@ -34,8 +34,8 @@ func CreateTagNodeWitRelation(ctx context.Context, driver neo4j.DriverWithContex return nil } -func GetTags(ctx context.Context, driver neo4j.DriverWithContext) ([]models.TagsWithFrequency, error) { - var userTags []models.TagsWithFrequency +func GetTags(ctx context.Context, driver neo4j.DriverWithContext) ([]graphModels.TagsWithFrequency, error) { + var userTags []graphModels.TagsWithFrequency query := ` MATCH (:AnthrovePost)-[:HAS]->(t:Tag) @@ -66,9 +66,9 @@ func GetTags(ctx context.Context, driver neo4j.DriverWithContext) ([]models.Tags return nil, err } - userTags = append(userTags, models.TagsWithFrequency{ + userTags = append(userTags, graphModels.TagsWithFrequency{ Frequency: frequency, - Tags: models.AnthroveTag{ + Tags: graphModels.AnthroveTag{ Name: tag.Props["name"].(string), Type: tag.Props["type"].(string), }, diff --git a/internal/graph/user.go b/internal/graph/user.go index 7d4a8e8..a136de3 100644 --- a/internal/graph/user.go +++ b/internal/graph/user.go @@ -3,9 +3,9 @@ package graph import ( "context" "fmt" - "git.dragse.it/anthrove/otter-space-sdk/internal/utils" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "github.com/neo4j/neo4j-go-driver/v5/neo4j" log "github.com/sirupsen/logrus" ) @@ -28,13 +28,13 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, driver neo4j.DriverWi return err } - var anthroveUserRelationship []models.AnthroveUserRelationship + var anthroveUserRelationship []graphModels.AnthroveUserRelationship - anthroveUserRelationship = append(anthroveUserRelationship, models.AnthroveUserRelationship{ + anthroveUserRelationship = append(anthroveUserRelationship, graphModels.AnthroveUserRelationship{ UserID: userID, Username: username, ScrapeTimeInterval: "", - Source: models.AnthroveSource{ + Source: graphModels.AnthroveSource{ DisplayName: "", Domain: sourceDomain, Icon: "", @@ -90,9 +90,9 @@ func GetUserFavoritesCount(ctx context.Context, driver neo4j.DriverWithContext, return userFavoriteCount, nil } -func GetUserSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) (map[string]models.AnthroveUserRelationship, error) { +func GetUserSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { - userSource := make(map[string]models.AnthroveUserRelationship) + userSource := make(map[string]graphModels.AnthroveUserRelationship) query := ` MATCH (user:User{user_id: $anthrove_user_id})-[r:HAS_ACCOUNT_AT]->(s:Source) @@ -130,10 +130,10 @@ func GetUserSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anth domain := source.Props["domain"].(string) icon := source.Props["icon"].(string) - anthroveSourceUser := models.AnthroveUserRelationship{ + anthroveSourceUser := graphModels.AnthroveUserRelationship{ UserID: sourceUserID, Username: sourceUsername, - Source: models.AnthroveSource{ + Source: graphModels.AnthroveSource{ DisplayName: displayName, Domain: domain, Icon: icon, @@ -150,9 +150,9 @@ func GetUserSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anth return userSource, nil } -func GetSpecifiedUserSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.AnthroveUserRelationship, error) { +func GetSpecifiedUserSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { - userSource := make(map[string]models.AnthroveUserRelationship) + userSource := make(map[string]graphModels.AnthroveUserRelationship) query := ` MATCH (user:User{user_id: $anthrove_user_id})-[r:HAS_ACCOUNT_AT]->(s:Source{display_name: $source_display_name}) @@ -191,10 +191,10 @@ func GetSpecifiedUserSourceLink(ctx context.Context, driver neo4j.DriverWithCont domain := source.Props["domain"].(string) icon := source.Props["icon"].(string) - anthroveSourceUser := models.AnthroveUserRelationship{ + anthroveSourceUser := graphModels.AnthroveUserRelationship{ UserID: sourceUserID, Username: sourceUsername, - Source: models.AnthroveSource{ + Source: graphModels.AnthroveSource{ DisplayName: displayName, Domain: domain, Icon: icon, @@ -211,11 +211,11 @@ func GetSpecifiedUserSourceLink(ctx context.Context, driver neo4j.DriverWithCont return userSource, nil } -func GetAnthroveUser(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) (*models.AnthroveUser, error) { +func GetAnthroveUser(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { var err error - var anthroveUser models.AnthroveUser - var userSources models.AnthroveSource - userRelationships := make([]models.AnthroveUserRelationship, 0) + var anthroveUser graphModels.AnthroveUser + var userSources graphModels.AnthroveSource + userRelationships := make([]graphModels.AnthroveUserRelationship, 0) query := ` MATCH (user:User{user_id: $anthrove_user_id})-[relation:HAS_ACCOUNT_AT]->(source:Source) @@ -250,13 +250,13 @@ func GetAnthroveUser(ctx context.Context, driver neo4j.DriverWithContext, anthro return nil, err } - userRelationships = append(userRelationships, models.AnthroveUserRelationship{ + userRelationships = append(userRelationships, graphModels.AnthroveUserRelationship{ UserID: fmt.Sprintf("%v", utils.GetOrDefault(relation.Props, "user_id", "")), Username: utils.GetOrDefault(relation.Props, "username", "").(string), ScrapeTimeInterval: utils.GetOrDefault(relation.Props, "scrape_time_interval", "").(string), }) - userSources = models.AnthroveSource{ + userSources = graphModels.AnthroveSource{ DisplayName: utils.GetOrDefault(source.Props, "display_name", "").(string), Domain: utils.GetOrDefault(source.Props, "domain", "").(string), Icon: utils.GetOrDefault(source.Props, "icon", "").(string), @@ -316,9 +316,9 @@ func GetAllAnthroveUserIDs(ctx context.Context, driver neo4j.DriverWithContext) } -func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { +func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { var err error - var favoritePosts []models.FavoritePost + var favoritePosts []graphModels.FavoritePost query := ` CALL { @@ -368,22 +368,22 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverW } if len(favoritePosts) != 0 && favoritePosts[len(favoritePosts)-1].AnthrovePost.PostID == models.AnthrovePostID(anthrovePost.Props["post_id"].(string)) { - favoritePosts[len(favoritePosts)-1].Relations = append(favoritePosts[len(favoritePosts)-1].Relations, models.FavoriteRelations{ + favoritePosts[len(favoritePosts)-1].Relations = append(favoritePosts[len(favoritePosts)-1].Relations, graphModels.FavoriteRelations{ SourcesID: source.Props["display_name"].(string), - Relations: models.AnthrovePostRelationship{ + Relations: graphModels.AnthrovePostRelationship{ PostID: postRelation.Props["source_post_id"].(string), Url: postRelation.Props["url"].(string), }, }) } else { - favoritePosts = append(favoritePosts, models.FavoritePost{ - AnthrovePost: models.AnthrovePost{ + favoritePosts = append(favoritePosts, graphModels.FavoritePost{ + AnthrovePost: graphModels.AnthrovePost{ PostID: models.AnthrovePostID(anthrovePost.Props["post_id"].(string)), - Rating: models.AnthroveRating(anthrovePost.Props["rating"].(string)), + Rating: models.Rating(anthrovePost.Props["rating"].(string)), }, - Relations: []models.FavoriteRelations{{ + Relations: []graphModels.FavoriteRelations{{ SourcesID: source.Props["display_name"].(string), - Relations: models.AnthrovePostRelationship{ + Relations: graphModels.AnthrovePostRelationship{ PostID: postRelation.Props["source_post_id"].(string), Url: postRelation.Props["url"].(string), }, @@ -398,12 +398,12 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverW "anthrove_user_fav_count": len(favoritePosts), }).Trace("database: got al anthrove user favorites") - return &models.FavoriteList{Posts: favoritePosts}, nil + return &graphModels.FavoriteList{Posts: favoritePosts}, nil } -func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { - var userTags []models.TagsWithFrequency +func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { + var userTags []graphModels.TagsWithFrequency query := ` MATCH (u:User {user_id: $anthrove_user_id})-[:FAV]->(:AnthrovePost)-[:HAS]->(t:Tag) @@ -436,9 +436,9 @@ func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, driver neo4j.Dri return nil, err } - userTags = append(userTags, models.TagsWithFrequency{ + userTags = append(userTags, graphModels.TagsWithFrequency{ Frequency: frequency, - Tags: models.AnthroveTag{ + Tags: graphModels.AnthroveTag{ Name: tag.Props["name"].(string), Type: tag.Props["type"].(string), }, diff --git a/internal/postgres/source.go b/internal/postgres/source.go index 6871f45..956c53b 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -2,14 +2,14 @@ package postgres import ( "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) // GetAllSourceNodes returns a list of all models.AnthroveSource -func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]models.AnthroveSource, error) { - var sources []models.AnthroveSource +func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]graphModels.AnthroveSource, error) { + var sources []graphModels.AnthroveSource result := db.WithContext(ctx).Find(&sources) diff --git a/pkg/database/database.go b/pkg/database/database.go index 62f3158..307bc83 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -27,8 +27,8 @@ package database import ( "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" ) // OtterSpace provides an interface for interacting with the OtterSpace API. @@ -45,23 +45,23 @@ type OtterSpace interface { // AddSource adds a new source to the OtterSpace database. // It returns an error if the operation fails. - AddSource(ctx context.Context, anthroveSource *models.AnthroveSource) error + AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error // AddPost adds a new post to the OtterSpace database. // It returns an error if the operation fails. - AddPost(ctx context.Context, anthrovePost *models.AnthrovePost) error + AddPost(ctx context.Context, anthrovePost *graphModels.AnthrovePost) error // AddTagWithRelationToPost adds a new tag to the OtterSpace database and associates it with a post. // It returns an error if the operation fails. - AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.AnthroveTag) error + AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error // LinkPostWithSource establishes a link between a post and a source in the OtterSpace database. // It returns an error if the operation fails. - LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.AnthrovePostRelationship) error + LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error // LinkUserWithPost establishes a link between a user and a post in the OtterSpace database. // It returns an error if the operation fails. - LinkUserWithPost(ctx context.Context, anthroveUser *models.AnthroveUser, anthrovePost *models.AnthrovePost) error + LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error // CheckUserPostLink checks if a link between a user and a post exists in the OtterSpace database. // It returns true if the link exists, false otherwise, and an error if the operation fails. @@ -69,15 +69,15 @@ type OtterSpace interface { // CheckPostNodeExistsByAnthroveID checks if a post node exists in the OtterSpace database by its Anthrove ID. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. - CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.AnthrovePost) (*models.AnthrovePost, bool, error) + CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) // CheckPostNodeExistsBySourceURL checks if a post node exists in the OtterSpace database by its source URL. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. - CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.AnthrovePost, bool, error) + CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) // CheckPostNodeExistsBySourceID checks if a post node exists in the OtterSpace database by its source ID. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. - CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.AnthrovePost, bool, error) + CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*graphModels.AnthrovePost, bool, error) // GetUserFavoriteCount retrieves the count of a user's favorite posts from the OtterSpace database. // It returns the count and an error if the operation fails. @@ -85,32 +85,32 @@ type OtterSpace interface { // GetUserSourceLinks retrieves the links between a user and sources in the OtterSpace database. // It returns a map of source domains to user-source relationships, and an error if the operation fails. - GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.AnthroveUserRelationship, error) + GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) // GetSpecifiedUserSourceLink GetUserSourceLinks retrieves the links between a user and a specific source in the OtterSpace database. // It returns a map of source domains to user-source relationships, and an error if the operation fails. - GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.AnthroveUserRelationship, error) + GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) // GetAnthroveUser retrieves a user from the OtterSpace database by their ID. // It returns the user and an error if the operation fails. - GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.AnthroveUser, error) + GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) // GetAllAnthroveUserIDs retrieves all user IDs from the OtterSpace database. // It returns a slice of user IDs and an error if the operation fails. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) // GetUserFavoritePostsWithPagination gets all user favorites with relation and sources for the given user - GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) + GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) // GetUserTagsTroughFavedPosts returns a list of Tags that the user hs favorites through a post - GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) + GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) // GetAllTags returns a list of Tags that the user hs favorites through a post - GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) + GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) // GetAllSources returns a list of Sources in the database - GetAllSources(ctx context.Context) ([]models.AnthroveSource, error) + GetAllSources(ctx context.Context) ([]graphModels.AnthroveSource, error) // GetSourceByURL returns the Source Node based on the URL - GetSourceByURL(ctx context.Context, sourceUrl string) (*models.AnthroveSource, error) + GetSourceByURL(ctx context.Context, sourceUrl string) (*graphModels.AnthroveSource, error) } diff --git a/pkg/database/graph.go b/pkg/database/graph.go index 869f643..7fc5bf2 100644 --- a/pkg/database/graph.go +++ b/pkg/database/graph.go @@ -4,6 +4,7 @@ import ( "context" "git.dragse.it/anthrove/otter-space-sdk/internal/graph" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "github.com/neo4j/neo4j-go-driver/v5/neo4j" "github.com/neo4j/neo4j-go-driver/v5/neo4j/config" ) @@ -39,23 +40,23 @@ func (g *graphConnection) AddUserWithRelationToSource(ctx context.Context, anthr return graph.CreateUserNodeWithSourceRelation(ctx, g.driver, anthroveUserID, sourceDomain, userID, username) } -func (g *graphConnection) AddSource(ctx context.Context, anthroveSource *models.AnthroveSource) error { +func (g *graphConnection) AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error { return graph.CreateSourceNode(ctx, g.driver, anthroveSource) } -func (g *graphConnection) AddPost(ctx context.Context, anthrovePost *models.AnthrovePost) error { +func (g *graphConnection) AddPost(ctx context.Context, anthrovePost *graphModels.AnthrovePost) error { return graph.CreateAnthrovePostNode(ctx, g.driver, anthrovePost) } -func (g *graphConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.AnthroveTag) error { +func (g *graphConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { return graph.CreateTagNodeWitRelation(ctx, g.driver, anthrovePostID, anthroveTag) } -func (g *graphConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.AnthrovePostRelationship) error { +func (g *graphConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { return graph.EstablishAnthrovePostToSourceLink(ctx, g.driver, anthrovePostID, anthroveSourceDomain, anthrovePostRelationship) } -func (g *graphConnection) LinkUserWithPost(ctx context.Context, anthroveUser *models.AnthroveUser, anthrovePost *models.AnthrovePost) error { +func (g *graphConnection) LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { return graph.EstablishUserToPostLink(ctx, g.driver, anthroveUser, anthrovePost) } @@ -63,15 +64,15 @@ func (g *graphConnection) CheckUserPostLink(ctx context.Context, anthroveUserID return graph.CheckUserToPostLink(ctx, g.driver, anthroveUserID, sourcePostID, sourceUrl) } -func (g *graphConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.AnthrovePost) (*models.AnthrovePost, bool, error) { +func (g *graphConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { return graph.CheckIfAnthrovePostNodeExistsByAnthroveID(ctx, g.driver, anthrovePost) } -func (g *graphConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.AnthrovePost, bool, error) { +func (g *graphConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { return graph.CheckIfAnthrovePostNodeExistsBySourceURl(ctx, g.driver, sourceUrl) } -func (g *graphConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.AnthrovePost, bool, error) { +func (g *graphConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*graphModels.AnthrovePost, bool, error) { return graph.CheckIfAnthrovePostNodeExistsBySourceID(ctx, g.driver, sourcePostID) } @@ -79,15 +80,15 @@ func (g *graphConnection) GetUserFavoriteCount(ctx context.Context, anthroveUser return graph.GetUserFavoritesCount(ctx, g.driver, anthroveUserID) } -func (g *graphConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.AnthroveUserRelationship, error) { +func (g *graphConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { return graph.GetUserSourceLink(ctx, g.driver, anthroveUserID) } -func (g *graphConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.AnthroveUserRelationship, error) { +func (g *graphConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { return graph.GetSpecifiedUserSourceLink(ctx, g.driver, anthroveUserID, sourceDisplayName) } -func (g *graphConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.AnthroveUser, error) { +func (g *graphConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { return graph.GetAnthroveUser(ctx, g.driver, anthroveUserID) } @@ -95,23 +96,23 @@ func (g *graphConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.A return graph.GetAllAnthroveUserIDs(ctx, g.driver) } -func (g *graphConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { +func (g *graphConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { return graph.GetUserFavoriteNodeWithPagination(ctx, g.driver, anthroveUserID, skip, limit) } -func (g *graphConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { +func (g *graphConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { return graph.GetUserTagNodeWitRelationToFavedPosts(ctx, g.driver, anthroveUserID) } -func (g *graphConnection) GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) { +func (g *graphConnection) GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) { return graph.GetTags(ctx, g.driver) } -func (g *graphConnection) GetAllSources(ctx context.Context) ([]models.AnthroveSource, error) { +func (g *graphConnection) GetAllSources(ctx context.Context) ([]graphModels.AnthroveSource, error) { return graph.GetAllSourceNodes(ctx, g.driver) } -func (g *graphConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*models.AnthroveSource, error) { +func (g *graphConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*graphModels.AnthroveSource, error) { return graph.GetSourceNodesByURL(ctx, g.driver, sourceUrl) } diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 89628e6..afb0fac 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -5,6 +5,7 @@ import ( "fmt" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" ) @@ -35,27 +36,27 @@ func (p postgresqlConnection) AddUserWithRelationToSource(ctx context.Context, a panic("implement me") } -func (p postgresqlConnection) AddSource(ctx context.Context, anthroveSource *models.AnthroveSource) error { +func (p postgresqlConnection) AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error { //TODO implement me panic("implement me") } -func (p postgresqlConnection) AddPost(ctx context.Context, anthrovePost *models.AnthrovePost) error { +func (p postgresqlConnection) AddPost(ctx context.Context, anthrovePost *graphModels.AnthrovePost) error { //TODO implement me panic("implement me") } -func (p postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.AnthroveTag) error { +func (p postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { //TODO implement me panic("implement me") } -func (p postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.AnthrovePostRelationship) error { +func (p postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { //TODO implement me panic("implement me") } -func (p postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *models.AnthroveUser, anthrovePost *models.AnthrovePost) error { +func (p postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { //TODO implement me panic("implement me") } @@ -65,17 +66,17 @@ func (p postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUse panic("implement me") } -func (p postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.AnthrovePost) (*models.AnthrovePost, bool, error) { +func (p postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.AnthrovePost, bool, error) { +func (p postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.AnthrovePost, bool, error) { +func (p postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*graphModels.AnthrovePost, bool, error) { //TODO implement me panic("implement me") } @@ -85,17 +86,17 @@ func (p postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthrove panic("implement me") } -func (p postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.AnthroveUserRelationship, error) { +func (p postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.AnthroveUserRelationship, error) { +func (p postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.AnthroveUser, error) { +func (p postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { //TODO implement me panic("implement me") } @@ -105,26 +106,26 @@ func (p postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]mode panic("implement me") } -func (p postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { +func (p postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { +func (p postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) { +func (p postgresqlConnection) GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetAllSources(ctx context.Context) ([]models.AnthroveSource, error) { +func (p postgresqlConnection) GetAllSources(ctx context.Context) ([]graphModels.AnthroveSource, error) { return postgres.GetAllSourceNodes(ctx, p.db) } -func (p postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*models.AnthroveSource, error) { +func (p postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*graphModels.AnthroveSource, error) { //TODO implement me panic("implement me") } diff --git a/pkg/models/README.md b/pkg/models/README.md new file mode 100644 index 0000000..7c824d0 --- /dev/null +++ b/pkg/models/README.md @@ -0,0 +1,87 @@ +# Postgres + +https://www.dbdiagram.io/d + +```` +Table User { + id string [primary key] + created_at timestamp +} + +Table Post { + id varchar(25) [primary key] + rating Rating + body text [note: 'Content of the post'] + user_id integer + status post_status + created_at timestamp +} + +Enum Rating { + safe + questionable + explicit +} + +Table Source { + id varchar(25) [primary key] + display_name text + domain text [not null, unique] +} + +Table Tag { + name text [primary key] + type TagType +} + +Enum TagType { + general + species + character + artist + lore + meta + invalid +} + +Table TagAlias { + name text [primary key] + tag_id text +} + +Table TagGroup { + name text [primary key] + tag_id text +} + +Table UserFavorites { + user_id text [primary key] + post_id text [primary key] + created_at timestamp +} + +Table UserSource { + user_id text [primary key] + source_id text [primary key] + account_username text + account_id text +} + +Table PostReference { + post_id text [primary key] + source_id text [primary key] + url text [not null, unique] + source_post_id text +} + +Ref: Tag.name > TagAlias.tag_id +Ref: Tag.name > TagGroup.tag_id +Ref: Tag.name <> Post.id +Ref: UserFavorites.user_id > User.id +Ref: UserFavorites.post_id > Post.id +Ref: UserSource.user_id > User.id +Ref: UserSource.source_id > Source.id +Ref: PostReference.post_id > Post.id +Ref: PostReference.source_id > Source.id + +```` \ No newline at end of file diff --git a/pkg/models/const.go b/pkg/models/const.go index 9dd312e..552193d 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -2,16 +2,27 @@ package models type AnthroveUserID string type AnthrovePostID string -type AnthroveRating string +type Rating string +type TagType string const ( - SFW AnthroveRating = "s" - NSFW AnthroveRating = "e" - Questionable AnthroveRating = "q" - Unknown AnthroveRating = "unknown" + SFW Rating = "s" + NSFW Rating = "e" + Questionable Rating = "q" + Unknown Rating = "unknown" ) -func (r *AnthroveRating) Convert(e621Rating string) { +const ( + General TagType = "general" + Species TagType = "species" + Character TagType = "character" + Artist TagType = "artist" + Lore TagType = "lore" + Meta TagType = "meta" + Invalid TagType = "invalid" +) + +func (r *Rating) Convert(e621Rating string) { switch e621Rating { case "e": diff --git a/pkg/models/api.go b/pkg/models/graphModels/api.go similarity index 95% rename from pkg/models/api.go rename to pkg/models/graphModels/api.go index a30b955..7683097 100644 --- a/pkg/models/api.go +++ b/pkg/models/graphModels/api.go @@ -1,4 +1,4 @@ -package models +package graphModels type FavoriteRelations struct { SourcesID string `json:"sources_id"` diff --git a/pkg/models/graphModels/post.go b/pkg/models/graphModels/post.go new file mode 100644 index 0000000..28caa38 --- /dev/null +++ b/pkg/models/graphModels/post.go @@ -0,0 +1,8 @@ +package graphModels + +import "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + +type AnthrovePost struct { + PostID models.AnthrovePostID `json:"post_id"` + Rating models.Rating `json:"rating"` +} diff --git a/pkg/models/relationships.go b/pkg/models/graphModels/relationships.go similarity index 94% rename from pkg/models/relationships.go rename to pkg/models/graphModels/relationships.go index f62e134..639966f 100644 --- a/pkg/models/relationships.go +++ b/pkg/models/graphModels/relationships.go @@ -1,4 +1,4 @@ -package models +package graphModels type AnthroveUserRelationship struct { UserID string `json:"user_id"` diff --git a/pkg/models/source.go b/pkg/models/graphModels/source.go similarity index 87% rename from pkg/models/source.go rename to pkg/models/graphModels/source.go index 00040ae..5e3795b 100644 --- a/pkg/models/source.go +++ b/pkg/models/graphModels/source.go @@ -1,4 +1,4 @@ -package models +package graphModels type AnthroveSource struct { DisplayName string `json:"display_name"` diff --git a/pkg/models/tag.go b/pkg/models/graphModels/tag.go similarity index 80% rename from pkg/models/tag.go rename to pkg/models/graphModels/tag.go index 8d0d1e6..699a1fc 100644 --- a/pkg/models/tag.go +++ b/pkg/models/graphModels/tag.go @@ -1,4 +1,4 @@ -package models +package graphModels type AnthroveTag struct { Name string `json:"name"` diff --git a/pkg/models/graphModels/user.go b/pkg/models/graphModels/user.go new file mode 100644 index 0000000..3b74a51 --- /dev/null +++ b/pkg/models/graphModels/user.go @@ -0,0 +1,8 @@ +package graphModels + +import "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + +type AnthroveUser struct { + UserID models.AnthroveUserID `json:"user_id"` + Relationship []AnthroveUserRelationship `json:"relationship"` +} diff --git a/pkg/models/pgModels/orm.go b/pkg/models/pgModels/orm.go new file mode 100644 index 0000000..bea5f1b --- /dev/null +++ b/pkg/models/pgModels/orm.go @@ -0,0 +1,13 @@ +package pgModels + +import ( + "gorm.io/gorm" + "time" +) + +type BaseModel struct { + ID string `gorm:"primaryKey"` + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/pkg/models/pgModels/post.go b/pkg/models/pgModels/post.go new file mode 100644 index 0000000..a4cf61a --- /dev/null +++ b/pkg/models/pgModels/post.go @@ -0,0 +1,14 @@ +package pgModels + +import ( + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" +) + +// Post model +type Post struct { + BaseModel + Rating models.Rating `gorm:"type:rating"` + Body string `gorm:"type:text"` + UserID int `gorm:"index"` + Status string `gorm:"type:post_status"` +} diff --git a/pkg/models/pgModels/source.go b/pkg/models/pgModels/source.go new file mode 100644 index 0000000..73e2535 --- /dev/null +++ b/pkg/models/pgModels/source.go @@ -0,0 +1,8 @@ +package pgModels + +// Source model +type Source struct { + BaseModel + DisplayName string `gorm:"type:text"` + Domain string `gorm:"type:text;not null;unique"` +} diff --git a/pkg/models/pgModels/tag.go b/pkg/models/pgModels/tag.go new file mode 100644 index 0000000..4c246a1 --- /dev/null +++ b/pkg/models/pgModels/tag.go @@ -0,0 +1,21 @@ +package pgModels + +import "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + +// Tag models +type Tag struct { + Name string `gorm:"primaryKey"` + Type models.TagType `gorm:"type:tag_type"` +} + +// TagAlias model +type TagAlias struct { + Name string `gorm:"primaryKey"` + TagID string `gorm:"index"` +} + +// TagGroup model +type TagGroup struct { + Name string `gorm:"primaryKey"` + TagID string `gorm:"index"` +} diff --git a/pkg/models/pgModels/user.go b/pkg/models/pgModels/user.go new file mode 100644 index 0000000..be072d8 --- /dev/null +++ b/pkg/models/pgModels/user.go @@ -0,0 +1,6 @@ +package pgModels + +// User model +type User struct { + BaseModel +} diff --git a/pkg/models/post.go b/pkg/models/post.go deleted file mode 100644 index e2d4b9b..0000000 --- a/pkg/models/post.go +++ /dev/null @@ -1,6 +0,0 @@ -package models - -type AnthrovePost struct { - PostID AnthrovePostID `json:"post_id"` - Rating AnthroveRating `json:"rating"` -} diff --git a/pkg/models/user.go b/pkg/models/user.go deleted file mode 100644 index af6e36c..0000000 --- a/pkg/models/user.go +++ /dev/null @@ -1,6 +0,0 @@ -package models - -type AnthroveUser struct { - UserID AnthroveUserID `json:"user_id"` - Relationship []AnthroveUserRelationship `json:"relationship"` -} From 5a693063bbccbb90ca7699cf147e7daa029de338 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 08:49:46 +0200 Subject: [PATCH 008/124] feat(sources): finalized model with gorm annotation Signed-off-by: SoXX --- pkg/models/pgModels/post.go | 11 +++++++---- pkg/models/pgModels/postReference.go | 8 ++++++++ pkg/models/pgModels/source.go | 6 ++++-- pkg/models/pgModels/tag.go | 11 +++++++---- pkg/models/pgModels/user.go | 2 ++ pkg/models/pgModels/userFavorite.go | 9 +++++++++ pkg/models/pgModels/userSource.go | 8 ++++++++ 7 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 pkg/models/pgModels/postReference.go create mode 100644 pkg/models/pgModels/userFavorite.go create mode 100644 pkg/models/pgModels/userSource.go diff --git a/pkg/models/pgModels/post.go b/pkg/models/pgModels/post.go index a4cf61a..1ba9262 100644 --- a/pkg/models/pgModels/post.go +++ b/pkg/models/pgModels/post.go @@ -7,8 +7,11 @@ import ( // Post model type Post struct { BaseModel - Rating models.Rating `gorm:"type:rating"` - Body string `gorm:"type:text"` - UserID int `gorm:"index"` - Status string `gorm:"type:post_status"` + Rating models.Rating `gorm:"type:enum('safe','questionable','explicit')"` + Body string `gorm:"type:text"` + UserID int + Status string + Tags []Tag `gorm:"many2many:post_tags;"` + Favorites []UserFavorite `gorm:"foreignKey:PostID"` + References []PostReference `gorm:"foreignKey:PostID"` } diff --git a/pkg/models/pgModels/postReference.go b/pkg/models/pgModels/postReference.go new file mode 100644 index 0000000..ae4574c --- /dev/null +++ b/pkg/models/pgModels/postReference.go @@ -0,0 +1,8 @@ +package pgModels + +type PostReference struct { + PostID string `gorm:"primaryKey"` + SourceID string `gorm:"primaryKey"` + URL string `gorm:"not null;unique"` + SourcePostID string +} diff --git a/pkg/models/pgModels/source.go b/pkg/models/pgModels/source.go index 73e2535..22c727f 100644 --- a/pkg/models/pgModels/source.go +++ b/pkg/models/pgModels/source.go @@ -3,6 +3,8 @@ package pgModels // Source model type Source struct { BaseModel - DisplayName string `gorm:"type:text"` - Domain string `gorm:"type:text;not null;unique"` + DisplayName string + Domain string `gorm:"not null;unique"` + UserSources []UserSource `gorm:"foreignKey:SourceID"` + References []PostReference `gorm:"foreignKey:SourceID"` } diff --git a/pkg/models/pgModels/tag.go b/pkg/models/pgModels/tag.go index 4c246a1..406f744 100644 --- a/pkg/models/pgModels/tag.go +++ b/pkg/models/pgModels/tag.go @@ -4,18 +4,21 @@ import "git.dragse.it/anthrove/otter-space-sdk/pkg/models" // Tag models type Tag struct { - Name string `gorm:"primaryKey"` - Type models.TagType `gorm:"type:tag_type"` + Name string `gorm:"primaryKey"` + Type models.TagType + Aliases []TagAlias `gorm:"foreignKey:TagID"` + Groups []TagGroup `gorm:"foreignKey:TagID"` + Posts []Post `gorm:"many2many:post_tags;"` } // TagAlias model type TagAlias struct { Name string `gorm:"primaryKey"` - TagID string `gorm:"index"` + TagID string } // TagGroup model type TagGroup struct { Name string `gorm:"primaryKey"` - TagID string `gorm:"index"` + TagID string } diff --git a/pkg/models/pgModels/user.go b/pkg/models/pgModels/user.go index be072d8..7fe7e73 100644 --- a/pkg/models/pgModels/user.go +++ b/pkg/models/pgModels/user.go @@ -3,4 +3,6 @@ package pgModels // User model type User struct { BaseModel + Favorites []UserFavorite `gorm:"foreignKey:UserID"` + Sources []UserSource `gorm:"foreignKey:UserID"` } diff --git a/pkg/models/pgModels/userFavorite.go b/pkg/models/pgModels/userFavorite.go new file mode 100644 index 0000000..2e194a3 --- /dev/null +++ b/pkg/models/pgModels/userFavorite.go @@ -0,0 +1,9 @@ +package pgModels + +import "time" + +type UserFavorite struct { + UserID string `gorm:"primaryKey"` + PostID string `gorm:"primaryKey"` + CreatedAt time.Time +} diff --git a/pkg/models/pgModels/userSource.go b/pkg/models/pgModels/userSource.go new file mode 100644 index 0000000..7319994 --- /dev/null +++ b/pkg/models/pgModels/userSource.go @@ -0,0 +1,8 @@ +package pgModels + +type UserSource struct { + UserID string `gorm:"primaryKey"` + SourceID string `gorm:"primaryKey"` + AccountUsername string + AccountID string +} From b2b354c60ff6867a969b697c170e9a4689f4070f Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 09:33:35 +0200 Subject: [PATCH 009/124] feat(db): initial setup for migrations Signed-off-by: SoXX --- go.mod | 13 ++++++++---- go.sum | 40 +++++++++++++++++++++++++++++-------- pkg/database/postgres.go | 31 ++++++++++++++++++++++++++++ pkg/models/pgModels/post.go | 5 +---- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index dc9cdf6..a2ceed4 100644 --- a/go.mod +++ b/go.mod @@ -3,19 +3,24 @@ module git.dragse.it/anthrove/otter-space-sdk go 1.22.0 require ( + github.com/lib/pq v1.10.7 github.com/neo4j/neo4j-go-driver/v5 v5.17.0 + github.com/rubenv/sql-migrate v1.6.1 github.com/sirupsen/logrus v1.9.3 gorm.io/driver/postgres v1.5.7 gorm.io/gorm v1.25.10 ) require ( + github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgx/v5 v5.4.3 // indirect + github.com/jackc/pgx/v5 v5.5.5 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index 2c77d3a..7d29fd6 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,40 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= +github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= -github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= +github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/neo4j/neo4j-go-driver/v5 v5.17.0 h1:Bdqg1Y8Hd3uLYToXtBjysDYXTdMiP7zeUNUEwfbJkSo= github.com/neo4j/neo4j-go-driver/v5 v5.17.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= +github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rubenv/sql-migrate v1.6.1 h1:bo6/sjsan9HaXAsNxYP/jCEDUGibHp8JmOBw7NTGRos= +github.com/rubenv/sql-migrate v1.6.1/go.mod h1:tPzespupJS0jacLfhbwto/UjSX+8h2FdWB7ar+QlHa0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -22,14 +42,18 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index afb0fac..f151503 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -2,10 +2,14 @@ package database import ( "context" + "database/sql" "fmt" + "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" + _ "github.com/lib/pq" + migrate "github.com/rubenv/sql-migrate" gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" ) @@ -28,6 +32,13 @@ func (p postgresqlConnection) Connect(ctx context.Context, endpoint string, user if err != nil { return err } + + err = p.migrateDatabase(dsn) + + if err != nil { + return err + } + return nil } @@ -129,3 +140,23 @@ func (p postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl stri //TODO implement me panic("implement me") } + +func (p postgresqlConnection) migrateDatabase(connectionString string) error { + dialect := "postgres" + migrations := &migrate.FileMigrationSource{ + Dir: "db/migrations", + } + + db, err := sql.Open(dialect, connectionString) + if err != nil { + return err + } + + n, err := migrate.Exec(db, dialect, migrations, migrate.Up) + if err != nil { + return err + } + fmt.Printf("Applied %d migrations!\n", n) + + return nil +} diff --git a/pkg/models/pgModels/post.go b/pkg/models/pgModels/post.go index 1ba9262..d2dd980 100644 --- a/pkg/models/pgModels/post.go +++ b/pkg/models/pgModels/post.go @@ -7,10 +7,7 @@ import ( // Post model type Post struct { BaseModel - Rating models.Rating `gorm:"type:enum('safe','questionable','explicit')"` - Body string `gorm:"type:text"` - UserID int - Status string + Rating models.Rating `gorm:"type:enum('safe','questionable','explicit')"` Tags []Tag `gorm:"many2many:post_tags;"` Favorites []UserFavorite `gorm:"foreignKey:PostID"` References []PostReference `gorm:"foreignKey:PostID"` From 751f387b86a1e0b13ce79607a0f5aee47c4116fb Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 13:06:38 +0200 Subject: [PATCH 010/124] feat(db): finalizing migration statements Signed-off-by: SoXX --- db/migrations/001_create_enum_Rating_2024_06_04.sql | 9 +++++++++ .../002_create_enum_TagType_2024_06_04.sql | 13 +++++++++++++ db/migrations/003_create_table_Post_2024_06_04.sql | 10 ++++++++++ .../004_create_table_Source_2024_06_04.sql | 11 +++++++++++ db/migrations/005_create_table_Tag_2024_06_04.sql | 9 +++++++++ db/migrations/006_create_table_User_2024_06_04.sql | 9 +++++++++ .../007_create_table_PostReference_2024_06_04.sql | 12 ++++++++++++ .../008_create_table_TagAlias_2024_06_04.sql | 8 ++++++++ .../009_create_table_TagGroup_2024_06_04.sql | 9 +++++++++ .../010_create_table_UserFavorite_2024_06_04.sql | 11 +++++++++++ .../011_create_table_UserSource_2024_06_04.sql | 13 +++++++++++++ pkg/database/postgres.go | 9 ++++----- 12 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 db/migrations/001_create_enum_Rating_2024_06_04.sql create mode 100644 db/migrations/002_create_enum_TagType_2024_06_04.sql create mode 100644 db/migrations/003_create_table_Post_2024_06_04.sql create mode 100644 db/migrations/004_create_table_Source_2024_06_04.sql create mode 100644 db/migrations/005_create_table_Tag_2024_06_04.sql create mode 100644 db/migrations/006_create_table_User_2024_06_04.sql create mode 100644 db/migrations/007_create_table_PostReference_2024_06_04.sql create mode 100644 db/migrations/008_create_table_TagAlias_2024_06_04.sql create mode 100644 db/migrations/009_create_table_TagGroup_2024_06_04.sql create mode 100644 db/migrations/010_create_table_UserFavorite_2024_06_04.sql create mode 100644 db/migrations/011_create_table_UserSource_2024_06_04.sql diff --git a/db/migrations/001_create_enum_Rating_2024_06_04.sql b/db/migrations/001_create_enum_Rating_2024_06_04.sql new file mode 100644 index 0000000..0af65ae --- /dev/null +++ b/db/migrations/001_create_enum_Rating_2024_06_04.sql @@ -0,0 +1,9 @@ +-- +migrate Up +CREATE TYPE Rating AS ENUM ( + 'safe', + 'questionable', + 'explicit' + ); + +-- +migrate Down +DROP TYPE Rating; diff --git a/db/migrations/002_create_enum_TagType_2024_06_04.sql b/db/migrations/002_create_enum_TagType_2024_06_04.sql new file mode 100644 index 0000000..0a95264 --- /dev/null +++ b/db/migrations/002_create_enum_TagType_2024_06_04.sql @@ -0,0 +1,13 @@ +-- +migrate Up +CREATE TYPE TagType AS ENUM ( + 'general', + 'species', + 'character', + 'artist', + 'lore', + 'meta', + 'invalid' + ); + +-- +migrate Down +DROP TYPE TagType; diff --git a/db/migrations/003_create_table_Post_2024_06_04.sql b/db/migrations/003_create_table_Post_2024_06_04.sql new file mode 100644 index 0000000..11957e1 --- /dev/null +++ b/db/migrations/003_create_table_Post_2024_06_04.sql @@ -0,0 +1,10 @@ +-- +migrate Up +CREATE TABLE "Post" +( + id VARCHAR(25) PRIMARY KEY, + rating Rating, + created_at TIMESTAMP +); + +-- +migrate Down +DROP TYPE Post; diff --git a/db/migrations/004_create_table_Source_2024_06_04.sql b/db/migrations/004_create_table_Source_2024_06_04.sql new file mode 100644 index 0000000..c52015f --- /dev/null +++ b/db/migrations/004_create_table_Source_2024_06_04.sql @@ -0,0 +1,11 @@ +-- +migrate Up +CREATE TABLE "Source" +( + id VARCHAR(25) PRIMARY KEY, + display_name TEXT, + domain TEXT NOT NULL UNIQUE +); + + +-- +migrate Down +DROP TABLE "Source"; \ No newline at end of file diff --git a/db/migrations/005_create_table_Tag_2024_06_04.sql b/db/migrations/005_create_table_Tag_2024_06_04.sql new file mode 100644 index 0000000..9b25afe --- /dev/null +++ b/db/migrations/005_create_table_Tag_2024_06_04.sql @@ -0,0 +1,9 @@ +-- +migrate Up +CREATE TABLE "Tag" +( + name TEXT PRIMARY KEY, + type TagType +); + +-- +migrate Down +DROP TABLE "Tag"; \ No newline at end of file diff --git a/db/migrations/006_create_table_User_2024_06_04.sql b/db/migrations/006_create_table_User_2024_06_04.sql new file mode 100644 index 0000000..56216f8 --- /dev/null +++ b/db/migrations/006_create_table_User_2024_06_04.sql @@ -0,0 +1,9 @@ +-- +migrate Up +CREATE TABLE "User" +( + id TEXT PRIMARY KEY, + created_at TIMESTAMP +); + +-- +migrate Down +DROP TABLE "User"; \ No newline at end of file diff --git a/db/migrations/007_create_table_PostReference_2024_06_04.sql b/db/migrations/007_create_table_PostReference_2024_06_04.sql new file mode 100644 index 0000000..f0001e7 --- /dev/null +++ b/db/migrations/007_create_table_PostReference_2024_06_04.sql @@ -0,0 +1,12 @@ +-- +migrate Up +CREATE TABLE "PostReference" +( + post_id TEXT REFERENCES "Post" (id), + source_id TEXT REFERENCES "Source" (id), + url TEXT NOT NULL UNIQUE, + source_post_id TEXT, + PRIMARY KEY (post_id, source_id) +); + +-- +migrate Down +DROP TABLE "PostReference"; \ No newline at end of file diff --git a/db/migrations/008_create_table_TagAlias_2024_06_04.sql b/db/migrations/008_create_table_TagAlias_2024_06_04.sql new file mode 100644 index 0000000..6e69fad --- /dev/null +++ b/db/migrations/008_create_table_TagAlias_2024_06_04.sql @@ -0,0 +1,8 @@ +-- +migrate Up +CREATE TABLE "TagAlias" +( + name TEXT PRIMARY KEY, + tag_id TEXT REFERENCES "Tag" (name) +); +-- +migrate Down +DROP TABLE "TagAlias"; \ No newline at end of file diff --git a/db/migrations/009_create_table_TagGroup_2024_06_04.sql b/db/migrations/009_create_table_TagGroup_2024_06_04.sql new file mode 100644 index 0000000..da305cd --- /dev/null +++ b/db/migrations/009_create_table_TagGroup_2024_06_04.sql @@ -0,0 +1,9 @@ +-- +migrate Up +CREATE TABLE "TagGroup" +( + name TEXT PRIMARY KEY, + tag_id TEXT REFERENCES "Tag" (name) +); + +-- +migrate Down +DROP TABLE "TagGroup"; \ No newline at end of file diff --git a/db/migrations/010_create_table_UserFavorite_2024_06_04.sql b/db/migrations/010_create_table_UserFavorite_2024_06_04.sql new file mode 100644 index 0000000..2058ab1 --- /dev/null +++ b/db/migrations/010_create_table_UserFavorite_2024_06_04.sql @@ -0,0 +1,11 @@ +-- +migrate Up +CREATE TABLE "UserFavorites" +( + user_id TEXT REFERENCES "User" (id), + post_id TEXT REFERENCES "Post" (id), + created_at TIMESTAMP, + PRIMARY KEY (user_id, post_id) +); + +-- +migrate Down +DROP TABLE "UserFavorites"; \ No newline at end of file diff --git a/db/migrations/011_create_table_UserSource_2024_06_04.sql b/db/migrations/011_create_table_UserSource_2024_06_04.sql new file mode 100644 index 0000000..8ba7201 --- /dev/null +++ b/db/migrations/011_create_table_UserSource_2024_06_04.sql @@ -0,0 +1,13 @@ +-- +migrate Up +CREATE TABLE "UserSource" +( + user_id TEXT REFERENCES "User" (id), + source_id TEXT REFERENCES "Source" (id), + account_username TEXT, + account_id TEXT, + PRIMARY KEY (user_id, source_id) +); + + +-- +migrate Down +DROP TABLE "UserSource"; \ No newline at end of file diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index f151503..77870f4 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -25,16 +25,15 @@ func NewPostgresqlConnection() OtterSpace { } func (p postgresqlConnection) Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error { - dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", endpoint, username, password, database, port, ssl, timezone) - db, err := gorm.Open(gormPostgres.Open(dsn), &gorm.Config{}) - p.db = db + var err error + + err = p.migrateDatabase(dsn) if err != nil { return err } - err = p.migrateDatabase(dsn) - + p.db, err = gorm.Open(gormPostgres.Open(dsn), &gorm.Config{}) if err != nil { return err } From 549c1ca5731f2d558642f25721b7985d6d69f90d Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 13:07:18 +0200 Subject: [PATCH 011/124] docs(db): removing unused entities Signed-off-by: SoXX --- pkg/models/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/models/README.md b/pkg/models/README.md index 7c824d0..af61315 100644 --- a/pkg/models/README.md +++ b/pkg/models/README.md @@ -11,9 +11,6 @@ Table User { Table Post { id varchar(25) [primary key] rating Rating - body text [note: 'Content of the post'] - user_id integer - status post_status created_at timestamp } From b65e942f24a2e7660087d0b712ffe164eb871740 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 13:28:14 +0200 Subject: [PATCH 012/124] feat(db): embed migration files Signed-off-by: SoXX --- .../001_create_enum_Rating_2024_06_04.sql | 0 .../002_create_enum_TagType_2024_06_04.sql | 0 .../003_create_table_Post_2024_06_04.sql | 0 .../004_create_table_Source_2024_06_04.sql | 0 .../005_create_table_Tag_2024_06_04.sql | 0 .../006_create_table_User_2024_06_04.sql | 0 ..._create_table_PostReference_2024_06_04.sql | 0 .../008_create_table_TagAlias_2024_06_04.sql | 0 .../009_create_table_TagGroup_2024_06_04.sql | 0 ...0_create_table_UserFavorite_2024_06_04.sql | 0 ...011_create_table_UserSource_2024_06_04.sql | 0 pkg/database/postgres.go | 21 +++++++++++++------ 12 files changed, 15 insertions(+), 6 deletions(-) rename {db => pkg/database}/migrations/001_create_enum_Rating_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/002_create_enum_TagType_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/003_create_table_Post_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/004_create_table_Source_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/005_create_table_Tag_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/006_create_table_User_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/007_create_table_PostReference_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/008_create_table_TagAlias_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/009_create_table_TagGroup_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/010_create_table_UserFavorite_2024_06_04.sql (100%) rename {db => pkg/database}/migrations/011_create_table_UserSource_2024_06_04.sql (100%) diff --git a/db/migrations/001_create_enum_Rating_2024_06_04.sql b/pkg/database/migrations/001_create_enum_Rating_2024_06_04.sql similarity index 100% rename from db/migrations/001_create_enum_Rating_2024_06_04.sql rename to pkg/database/migrations/001_create_enum_Rating_2024_06_04.sql diff --git a/db/migrations/002_create_enum_TagType_2024_06_04.sql b/pkg/database/migrations/002_create_enum_TagType_2024_06_04.sql similarity index 100% rename from db/migrations/002_create_enum_TagType_2024_06_04.sql rename to pkg/database/migrations/002_create_enum_TagType_2024_06_04.sql diff --git a/db/migrations/003_create_table_Post_2024_06_04.sql b/pkg/database/migrations/003_create_table_Post_2024_06_04.sql similarity index 100% rename from db/migrations/003_create_table_Post_2024_06_04.sql rename to pkg/database/migrations/003_create_table_Post_2024_06_04.sql diff --git a/db/migrations/004_create_table_Source_2024_06_04.sql b/pkg/database/migrations/004_create_table_Source_2024_06_04.sql similarity index 100% rename from db/migrations/004_create_table_Source_2024_06_04.sql rename to pkg/database/migrations/004_create_table_Source_2024_06_04.sql diff --git a/db/migrations/005_create_table_Tag_2024_06_04.sql b/pkg/database/migrations/005_create_table_Tag_2024_06_04.sql similarity index 100% rename from db/migrations/005_create_table_Tag_2024_06_04.sql rename to pkg/database/migrations/005_create_table_Tag_2024_06_04.sql diff --git a/db/migrations/006_create_table_User_2024_06_04.sql b/pkg/database/migrations/006_create_table_User_2024_06_04.sql similarity index 100% rename from db/migrations/006_create_table_User_2024_06_04.sql rename to pkg/database/migrations/006_create_table_User_2024_06_04.sql diff --git a/db/migrations/007_create_table_PostReference_2024_06_04.sql b/pkg/database/migrations/007_create_table_PostReference_2024_06_04.sql similarity index 100% rename from db/migrations/007_create_table_PostReference_2024_06_04.sql rename to pkg/database/migrations/007_create_table_PostReference_2024_06_04.sql diff --git a/db/migrations/008_create_table_TagAlias_2024_06_04.sql b/pkg/database/migrations/008_create_table_TagAlias_2024_06_04.sql similarity index 100% rename from db/migrations/008_create_table_TagAlias_2024_06_04.sql rename to pkg/database/migrations/008_create_table_TagAlias_2024_06_04.sql diff --git a/db/migrations/009_create_table_TagGroup_2024_06_04.sql b/pkg/database/migrations/009_create_table_TagGroup_2024_06_04.sql similarity index 100% rename from db/migrations/009_create_table_TagGroup_2024_06_04.sql rename to pkg/database/migrations/009_create_table_TagGroup_2024_06_04.sql diff --git a/db/migrations/010_create_table_UserFavorite_2024_06_04.sql b/pkg/database/migrations/010_create_table_UserFavorite_2024_06_04.sql similarity index 100% rename from db/migrations/010_create_table_UserFavorite_2024_06_04.sql rename to pkg/database/migrations/010_create_table_UserFavorite_2024_06_04.sql diff --git a/db/migrations/011_create_table_UserSource_2024_06_04.sql b/pkg/database/migrations/011_create_table_UserSource_2024_06_04.sql similarity index 100% rename from db/migrations/011_create_table_UserSource_2024_06_04.sql rename to pkg/database/migrations/011_create_table_UserSource_2024_06_04.sql diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 77870f4..f8773e6 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -3,6 +3,7 @@ package database import ( "context" "database/sql" + "embed" "fmt" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" @@ -10,10 +11,14 @@ import ( "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" _ "github.com/lib/pq" migrate "github.com/rubenv/sql-migrate" + log "github.com/sirupsen/logrus" gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" ) +//go:embed migrations/*.sql +var embedMigrations embed.FS + type postgresqlConnection struct { db *gorm.DB } @@ -142,20 +147,24 @@ func (p postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl stri func (p postgresqlConnection) migrateDatabase(connectionString string) error { dialect := "postgres" - migrations := &migrate.FileMigrationSource{ - Dir: "db/migrations", - } + migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"} db, err := sql.Open(dialect, connectionString) if err != nil { - return err + return fmt.Errorf("postgres migration: %v", err) } n, err := migrate.Exec(db, dialect, migrations, migrate.Up) if err != nil { - return err + return fmt.Errorf("postgres migration: %v", err) + } + if n != 0 { + log.Infof("postgres migration: applied %d migrations!", n) + + } else { + log.Info("postgres migration: nothing to migrate") + } - fmt.Printf("Applied %d migrations!\n", n) return nil } From ebd25580febfed169ea398158c31f62975b9b981 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 13:35:14 +0200 Subject: [PATCH 013/124] feat(db): reduce to one migration file Signed-off-by: SoXX --- .../001_create_enum_Rating_2024_06_04.sql | 9 -- .../migrations/001_inital_database.sql | 93 +++++++++++++++++++ .../002_create_enum_TagType_2024_06_04.sql | 13 --- .../003_create_table_Post_2024_06_04.sql | 10 -- .../004_create_table_Source_2024_06_04.sql | 11 --- .../005_create_table_Tag_2024_06_04.sql | 9 -- .../006_create_table_User_2024_06_04.sql | 9 -- ..._create_table_PostReference_2024_06_04.sql | 12 --- .../008_create_table_TagAlias_2024_06_04.sql | 8 -- .../009_create_table_TagGroup_2024_06_04.sql | 9 -- ...0_create_table_UserFavorite_2024_06_04.sql | 11 --- ...011_create_table_UserSource_2024_06_04.sql | 13 --- 12 files changed, 93 insertions(+), 114 deletions(-) delete mode 100644 pkg/database/migrations/001_create_enum_Rating_2024_06_04.sql create mode 100644 pkg/database/migrations/001_inital_database.sql delete mode 100644 pkg/database/migrations/002_create_enum_TagType_2024_06_04.sql delete mode 100644 pkg/database/migrations/003_create_table_Post_2024_06_04.sql delete mode 100644 pkg/database/migrations/004_create_table_Source_2024_06_04.sql delete mode 100644 pkg/database/migrations/005_create_table_Tag_2024_06_04.sql delete mode 100644 pkg/database/migrations/006_create_table_User_2024_06_04.sql delete mode 100644 pkg/database/migrations/007_create_table_PostReference_2024_06_04.sql delete mode 100644 pkg/database/migrations/008_create_table_TagAlias_2024_06_04.sql delete mode 100644 pkg/database/migrations/009_create_table_TagGroup_2024_06_04.sql delete mode 100644 pkg/database/migrations/010_create_table_UserFavorite_2024_06_04.sql delete mode 100644 pkg/database/migrations/011_create_table_UserSource_2024_06_04.sql diff --git a/pkg/database/migrations/001_create_enum_Rating_2024_06_04.sql b/pkg/database/migrations/001_create_enum_Rating_2024_06_04.sql deleted file mode 100644 index 0af65ae..0000000 --- a/pkg/database/migrations/001_create_enum_Rating_2024_06_04.sql +++ /dev/null @@ -1,9 +0,0 @@ --- +migrate Up -CREATE TYPE Rating AS ENUM ( - 'safe', - 'questionable', - 'explicit' - ); - --- +migrate Down -DROP TYPE Rating; diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql new file mode 100644 index 0000000..896c850 --- /dev/null +++ b/pkg/database/migrations/001_inital_database.sql @@ -0,0 +1,93 @@ +-- +migrate Up +CREATE TYPE Rating AS ENUM ( + 'safe', + 'questionable', + 'explicit' + ); + +CREATE TYPE TagType AS ENUM ( + 'general', + 'species', + 'character', + 'artist', + 'lore', + 'meta', + 'invalid' + ); + +CREATE TABLE "Post" +( + id VARCHAR(25) PRIMARY KEY, + rating Rating, + created_at TIMESTAMP +); + +CREATE TABLE "Source" +( + id VARCHAR(25) PRIMARY KEY, + display_name TEXT, + domain TEXT NOT NULL UNIQUE +); + +CREATE TABLE "Tag" +( + name TEXT PRIMARY KEY, + type TagType +); + +CREATE TABLE "User" +( + id TEXT PRIMARY KEY, + created_at TIMESTAMP +); + +CREATE TABLE "PostReference" +( + post_id TEXT REFERENCES "Post" (id), + source_id TEXT REFERENCES "Source" (id), + url TEXT NOT NULL UNIQUE, + source_post_id TEXT, + PRIMARY KEY (post_id, source_id) +); + +CREATE TABLE "TagAlias" +( + name TEXT PRIMARY KEY, + tag_id TEXT REFERENCES "Tag" (name) +); + +CREATE TABLE "TagGroup" +( + name TEXT PRIMARY KEY, + tag_id TEXT REFERENCES "Tag" (name) +); + +CREATE TABLE "UserFavorites" +( + user_id TEXT REFERENCES "User" (id), + post_id TEXT REFERENCES "Post" (id), + created_at TIMESTAMP, + PRIMARY KEY (user_id, post_id) +); + +CREATE TABLE "UserSource" +( + user_id TEXT REFERENCES "User" (id), + source_id TEXT REFERENCES "Source" (id), + account_username TEXT, + account_id TEXT, + PRIMARY KEY (user_id, source_id) +); + +-- +migrate Down +DROP TYPE Rating; +DROP TYPE TagType; +DROP TYPE Post; +DROP TYPE Source; +DROP TYPE Tag; +DROP TYPE User; +DROP TYPE PostReference; +DROP TYPE TagAlias; +DROP TYPE TagGroup; +DROP TYPE UserFavorites; +DROP TYPE UserSource; \ No newline at end of file diff --git a/pkg/database/migrations/002_create_enum_TagType_2024_06_04.sql b/pkg/database/migrations/002_create_enum_TagType_2024_06_04.sql deleted file mode 100644 index 0a95264..0000000 --- a/pkg/database/migrations/002_create_enum_TagType_2024_06_04.sql +++ /dev/null @@ -1,13 +0,0 @@ --- +migrate Up -CREATE TYPE TagType AS ENUM ( - 'general', - 'species', - 'character', - 'artist', - 'lore', - 'meta', - 'invalid' - ); - --- +migrate Down -DROP TYPE TagType; diff --git a/pkg/database/migrations/003_create_table_Post_2024_06_04.sql b/pkg/database/migrations/003_create_table_Post_2024_06_04.sql deleted file mode 100644 index 11957e1..0000000 --- a/pkg/database/migrations/003_create_table_Post_2024_06_04.sql +++ /dev/null @@ -1,10 +0,0 @@ --- +migrate Up -CREATE TABLE "Post" -( - id VARCHAR(25) PRIMARY KEY, - rating Rating, - created_at TIMESTAMP -); - --- +migrate Down -DROP TYPE Post; diff --git a/pkg/database/migrations/004_create_table_Source_2024_06_04.sql b/pkg/database/migrations/004_create_table_Source_2024_06_04.sql deleted file mode 100644 index c52015f..0000000 --- a/pkg/database/migrations/004_create_table_Source_2024_06_04.sql +++ /dev/null @@ -1,11 +0,0 @@ --- +migrate Up -CREATE TABLE "Source" -( - id VARCHAR(25) PRIMARY KEY, - display_name TEXT, - domain TEXT NOT NULL UNIQUE -); - - --- +migrate Down -DROP TABLE "Source"; \ No newline at end of file diff --git a/pkg/database/migrations/005_create_table_Tag_2024_06_04.sql b/pkg/database/migrations/005_create_table_Tag_2024_06_04.sql deleted file mode 100644 index 9b25afe..0000000 --- a/pkg/database/migrations/005_create_table_Tag_2024_06_04.sql +++ /dev/null @@ -1,9 +0,0 @@ --- +migrate Up -CREATE TABLE "Tag" -( - name TEXT PRIMARY KEY, - type TagType -); - --- +migrate Down -DROP TABLE "Tag"; \ No newline at end of file diff --git a/pkg/database/migrations/006_create_table_User_2024_06_04.sql b/pkg/database/migrations/006_create_table_User_2024_06_04.sql deleted file mode 100644 index 56216f8..0000000 --- a/pkg/database/migrations/006_create_table_User_2024_06_04.sql +++ /dev/null @@ -1,9 +0,0 @@ --- +migrate Up -CREATE TABLE "User" -( - id TEXT PRIMARY KEY, - created_at TIMESTAMP -); - --- +migrate Down -DROP TABLE "User"; \ No newline at end of file diff --git a/pkg/database/migrations/007_create_table_PostReference_2024_06_04.sql b/pkg/database/migrations/007_create_table_PostReference_2024_06_04.sql deleted file mode 100644 index f0001e7..0000000 --- a/pkg/database/migrations/007_create_table_PostReference_2024_06_04.sql +++ /dev/null @@ -1,12 +0,0 @@ --- +migrate Up -CREATE TABLE "PostReference" -( - post_id TEXT REFERENCES "Post" (id), - source_id TEXT REFERENCES "Source" (id), - url TEXT NOT NULL UNIQUE, - source_post_id TEXT, - PRIMARY KEY (post_id, source_id) -); - --- +migrate Down -DROP TABLE "PostReference"; \ No newline at end of file diff --git a/pkg/database/migrations/008_create_table_TagAlias_2024_06_04.sql b/pkg/database/migrations/008_create_table_TagAlias_2024_06_04.sql deleted file mode 100644 index 6e69fad..0000000 --- a/pkg/database/migrations/008_create_table_TagAlias_2024_06_04.sql +++ /dev/null @@ -1,8 +0,0 @@ --- +migrate Up -CREATE TABLE "TagAlias" -( - name TEXT PRIMARY KEY, - tag_id TEXT REFERENCES "Tag" (name) -); --- +migrate Down -DROP TABLE "TagAlias"; \ No newline at end of file diff --git a/pkg/database/migrations/009_create_table_TagGroup_2024_06_04.sql b/pkg/database/migrations/009_create_table_TagGroup_2024_06_04.sql deleted file mode 100644 index da305cd..0000000 --- a/pkg/database/migrations/009_create_table_TagGroup_2024_06_04.sql +++ /dev/null @@ -1,9 +0,0 @@ --- +migrate Up -CREATE TABLE "TagGroup" -( - name TEXT PRIMARY KEY, - tag_id TEXT REFERENCES "Tag" (name) -); - --- +migrate Down -DROP TABLE "TagGroup"; \ No newline at end of file diff --git a/pkg/database/migrations/010_create_table_UserFavorite_2024_06_04.sql b/pkg/database/migrations/010_create_table_UserFavorite_2024_06_04.sql deleted file mode 100644 index 2058ab1..0000000 --- a/pkg/database/migrations/010_create_table_UserFavorite_2024_06_04.sql +++ /dev/null @@ -1,11 +0,0 @@ --- +migrate Up -CREATE TABLE "UserFavorites" -( - user_id TEXT REFERENCES "User" (id), - post_id TEXT REFERENCES "Post" (id), - created_at TIMESTAMP, - PRIMARY KEY (user_id, post_id) -); - --- +migrate Down -DROP TABLE "UserFavorites"; \ No newline at end of file diff --git a/pkg/database/migrations/011_create_table_UserSource_2024_06_04.sql b/pkg/database/migrations/011_create_table_UserSource_2024_06_04.sql deleted file mode 100644 index 8ba7201..0000000 --- a/pkg/database/migrations/011_create_table_UserSource_2024_06_04.sql +++ /dev/null @@ -1,13 +0,0 @@ --- +migrate Up -CREATE TABLE "UserSource" -( - user_id TEXT REFERENCES "User" (id), - source_id TEXT REFERENCES "Source" (id), - account_username TEXT, - account_id TEXT, - PRIMARY KEY (user_id, source_id) -); - - --- +migrate Down -DROP TABLE "UserSource"; \ No newline at end of file From f0bd89759cbf17bb9a383da023f6cad586dc4f7c Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 13:44:15 +0200 Subject: [PATCH 014/124] refactor(db): logging & tracing Signed-off-by: SoXX --- pkg/database/postgres.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index f8773e6..cff9d4e 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -38,11 +38,15 @@ func (p postgresqlConnection) Connect(ctx context.Context, endpoint string, user return err } + log.Infof("OtterSpace: migration compleate") + p.db, err = gorm.Open(gormPostgres.Open(dsn), &gorm.Config{}) if err != nil { return err } + log.Infof("OtterSpace: postgres connection established") + return nil } @@ -159,10 +163,10 @@ func (p postgresqlConnection) migrateDatabase(connectionString string) error { return fmt.Errorf("postgres migration: %v", err) } if n != 0 { - log.Infof("postgres migration: applied %d migrations!", n) + log.Tracef("postgres migration: applied %d migrations!", n) } else { - log.Info("postgres migration: nothing to migrate") + log.Trace("postgres migration: nothing to migrate") } From ccb7cff4fca3ea7b0c4ae74cf5dbc76f0b5d113a Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 13:59:38 +0200 Subject: [PATCH 015/124] refactor(db): removed unused context Signed-off-by: SoXX --- pkg/database/postgres.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index cff9d4e..7680441 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -29,7 +29,7 @@ func NewPostgresqlConnection() OtterSpace { } } -func (p postgresqlConnection) Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error { +func (p postgresqlConnection) Connect(_ context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error { dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", endpoint, username, password, database, port, ssl, timezone) var err error From 5aa1542074899e46a3e269a5460742f2359433b8 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 14:00:00 +0200 Subject: [PATCH 016/124] feat(db): corrected tables Signed-off-by: SoXX --- pkg/database/migrations/001_inital_database.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index 896c850..a3c1146 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -17,14 +17,14 @@ CREATE TYPE TagType AS ENUM ( CREATE TABLE "Post" ( - id VARCHAR(25) PRIMARY KEY, + id VARCHAR(25) UNIQUE PRIMARY KEY, rating Rating, - created_at TIMESTAMP + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE "Source" ( - id VARCHAR(25) PRIMARY KEY, + id VARCHAR(25) UNIQUE PRIMARY KEY, display_name TEXT, domain TEXT NOT NULL UNIQUE ); @@ -37,8 +37,8 @@ CREATE TABLE "Tag" CREATE TABLE "User" ( - id TEXT PRIMARY KEY, - created_at TIMESTAMP + id TEXT UNIQUE PRIMARY KEY, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE "PostReference" @@ -66,7 +66,7 @@ CREATE TABLE "UserFavorites" ( user_id TEXT REFERENCES "User" (id), post_id TEXT REFERENCES "Post" (id), - created_at TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, post_id) ); From 8f87eb6ce8d325b7bbbd86ed75d9f3a9c93edd08 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 15:16:37 +0200 Subject: [PATCH 017/124] feat(db): start implementing sources & fixing issues that come along the way Signed-off-by: SoXX --- internal/postgres/source.go | 45 ++++++++++-- internal/utils/modelConvert.go | 27 ++++++++ .../migrations/001_inital_database.sql | 9 ++- pkg/database/postgres.go | 69 +++++++++++-------- pkg/models/pgModels/source.go | 5 ++ 5 files changed, 120 insertions(+), 35 deletions(-) create mode 100644 internal/utils/modelConvert.go diff --git a/internal/postgres/source.go b/internal/postgres/source.go index 956c53b..3d2cdca 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -2,14 +2,33 @@ package postgres import ( "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" + + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) -// GetAllSourceNodes returns a list of all models.AnthroveSource -func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]graphModels.AnthroveSource, error) { - var sources []graphModels.AnthroveSource +// CreateSourceNode creates a pgModels.Source +func CreateSourceNode(ctx context.Context, db *gorm.DB, anthroveSource *pgModels.Source) error { + + result := db.WithContext(ctx).Create(anthroveSource) + + if result.Error != nil { + return result.Error + } + + log.WithFields(log.Fields{ + "node_source_url": anthroveSource.Domain, + "node_source_displayName": anthroveSource.DisplayName, + "node_source_icon": anthroveSource.Icon, + }).Trace("database: created source node") + + return nil +} + +// GetAllSourceNodes returns a list of all pgModels.Source +func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]pgModels.Source, error) { + var sources []pgModels.Source result := db.WithContext(ctx).Find(&sources) @@ -23,3 +42,21 @@ func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]graphModels.Anthrove return sources, nil } + +// GetSourceNodesByURL returns the first source it finds based on the domain +func GetSourceNodesByURL(ctx context.Context, db *gorm.DB, domain string) (*pgModels.Source, error) { + + var sources *pgModels.Source + + result := db.WithContext(ctx).Where("domain = ?", domain).First(&sources) + + if result.Error != nil { + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tag_amount": result.RowsAffected, + }).Trace("database: get all source nodes") + + return sources, nil +} diff --git a/internal/utils/modelConvert.go b/internal/utils/modelConvert.go new file mode 100644 index 0000000..cc75258 --- /dev/null +++ b/internal/utils/modelConvert.go @@ -0,0 +1,27 @@ +package utils + +import ( + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" +) + +// GraphConvertSource converts a graphModels.AnthroveSource to a pgModels.Source +func GraphConvertSource(graphSource *graphModels.AnthroveSource) *pgModels.Source { + pgSource := &pgModels.Source{ + DisplayName: graphSource.DisplayName, + Domain: graphSource.Domain, + Icon: graphSource.Icon, + } + return pgSource +} + +// PostgresConvertToAnthroveSource converts a pgModels.Source to a graphModels.AnthroveSource +func PostgresConvertToAnthroveSource(pgSource *pgModels.Source) *graphModels.AnthroveSource { + graphSource := &graphModels.AnthroveSource{ + DisplayName: pgSource.DisplayName, + Domain: pgSource.Domain, + Icon: pgSource.Icon, + } + + return graphSource +} diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index a3c1146..00fcf9c 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -1,3 +1,9 @@ +-- TODO: Add the following fields where its defined in the model +-- created_at +-- updated_at +-- deleted_at + + -- +migrate Up CREATE TYPE Rating AS ENUM ( 'safe', @@ -24,8 +30,9 @@ CREATE TABLE "Post" CREATE TABLE "Source" ( - id VARCHAR(25) UNIQUE PRIMARY KEY, + id VARCHAR(25) UNIQUE PRIMARY KEY, display_name TEXT, + icon TEXT, domain TEXT NOT NULL UNIQUE ); diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 7680441..5ed0afe 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -7,6 +7,7 @@ import ( "fmt" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" + "git.dragse.it/anthrove/otter-space-sdk/internal/utils" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" _ "github.com/lib/pq" @@ -29,7 +30,7 @@ func NewPostgresqlConnection() OtterSpace { } } -func (p postgresqlConnection) Connect(_ context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error { +func (p *postgresqlConnection) Connect(_ context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error { dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", endpoint, username, password, database, port, ssl, timezone) var err error @@ -40,7 +41,8 @@ func (p postgresqlConnection) Connect(_ context.Context, endpoint string, userna log.Infof("OtterSpace: migration compleate") - p.db, err = gorm.Open(gormPostgres.Open(dsn), &gorm.Config{}) + db, err := gorm.Open(gormPostgres.Open(dsn), &gorm.Config{}) + p.db = db if err != nil { return err } @@ -50,106 +52,113 @@ func (p postgresqlConnection) Connect(_ context.Context, endpoint string, userna return nil } -func (p postgresqlConnection) AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { +func (p *postgresqlConnection) AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { //TODO implement me panic("implement me") } -func (p postgresqlConnection) AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error { +func (p *postgresqlConnection) AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error { + source := utils.GraphConvertSource(anthroveSource) + return postgres.CreateSourceNode(ctx, p.db, source) +} + +func (p *postgresqlConnection) AddPost(ctx context.Context, anthrovePost *graphModels.AnthrovePost) error { //TODO implement me panic("implement me") } -func (p postgresqlConnection) AddPost(ctx context.Context, anthrovePost *graphModels.AnthrovePost) error { +func (p *postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { //TODO implement me panic("implement me") } -func (p postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { +func (p *postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { //TODO implement me panic("implement me") } -func (p postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { +func (p *postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { //TODO implement me panic("implement me") } -func (p postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { +func (p *postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { +func (p *postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { +func (p *postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { +func (p *postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*graphModels.AnthrovePost, bool, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*graphModels.AnthrovePost, bool, error) { +func (p *postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { +func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { +func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { +func (p *postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { +func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { +func (p *postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { +func (p *postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { +func (p *postgresqlConnection) GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) { //TODO implement me panic("implement me") } -func (p postgresqlConnection) GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) { - //TODO implement me - panic("implement me") +func (p *postgresqlConnection) GetAllSources(ctx context.Context) ([]graphModels.AnthroveSource, error) { + var anthroveSources []graphModels.AnthroveSource + source, err := postgres.GetAllSourceNodes(ctx, p.db) + + for _, v := range source { + anthroveSource := utils.PostgresConvertToAnthroveSource(&v) + anthroveSources = append(anthroveSources, *anthroveSource) + } + return nil, err } -func (p postgresqlConnection) GetAllSources(ctx context.Context) ([]graphModels.AnthroveSource, error) { - return postgres.GetAllSourceNodes(ctx, p.db) +func (p *postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*graphModels.AnthroveSource, error) { + source, err := postgres.GetSourceNodesByURL(ctx, p.db, sourceUrl) + return utils.PostgresConvertToAnthroveSource(source), err } -func (p postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*graphModels.AnthroveSource, error) { - //TODO implement me - panic("implement me") -} - -func (p postgresqlConnection) migrateDatabase(connectionString string) error { +func (p *postgresqlConnection) migrateDatabase(connectionString string) error { dialect := "postgres" migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"} diff --git a/pkg/models/pgModels/source.go b/pkg/models/pgModels/source.go index 22c727f..7159ea5 100644 --- a/pkg/models/pgModels/source.go +++ b/pkg/models/pgModels/source.go @@ -5,6 +5,11 @@ type Source struct { BaseModel DisplayName string Domain string `gorm:"not null;unique"` + Icon string `gorm:"not null"` UserSources []UserSource `gorm:"foreignKey:SourceID"` References []PostReference `gorm:"foreignKey:SourceID"` } + +func (Source) TableName() string { + return "Source" +} From b248cbf0c798043c09cd7d7923ac535815d4561d Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 4 Jun 2024 23:14:02 +0200 Subject: [PATCH 018/124] feat(db): start implementing sources & fixing issues that come along the way Signed-off-by: SoXX --- go.mod | 1 + go.sum | 2 + internal/postgres/tag.go | 38 ++++++++++ internal/utils/modelConvert.go | 20 +++++ .../migrations/001_inital_database.sql | 76 +++++++++++-------- pkg/database/postgres.go | 3 +- pkg/models/pgModels/orm.go | 12 +++ pkg/models/pgModels/post.go | 4 + pkg/models/pgModels/tag.go | 22 ++++-- 9 files changed, 140 insertions(+), 38 deletions(-) create mode 100644 internal/postgres/tag.go diff --git a/go.mod b/go.mod index a2ceed4..9dcb619 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/matoous/go-nanoid/v2 v2.1.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.18.0 // indirect diff --git a/go.sum b/go.sum index 7d29fd6..f00d304 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/matoous/go-nanoid/v2 v2.1.0 h1:P64+dmq21hhWdtvZfEAofnvJULaRR1Yib0+PnU669bE= +github.com/matoous/go-nanoid/v2 v2.1.0/go.mod h1:KlbGNQ+FhrUNIHUxZdL63t7tl4LaPkZNpUULS8H4uVM= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/neo4j/neo4j-go-driver/v5 v5.17.0 h1:Bdqg1Y8Hd3uLYToXtBjysDYXTdMiP7zeUNUEwfbJkSo= diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go new file mode 100644 index 0000000..1dc97b1 --- /dev/null +++ b/internal/postgres/tag.go @@ -0,0 +1,38 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.AnthrovePostID, tag *pgModels.Tag) error { + + resultTag := db.WithContext(ctx).Where(tag).FirstOrCreate(tag) + + if resultTag.Error != nil { + return resultTag.Error + } + + pgPost := pgModels.Post{ + BaseModel: pgModels.BaseModel{ + ID: string(PostID), + }, + } + + err := db.WithContext(ctx).Model(pgPost).Association("Tags").Append(tag) + + if err != nil { + return err + } + + log.WithFields(log.Fields{ + "anthrove_post_id": PostID, + "tag_name": tag.Name, + "tag_type": tag.Type, + }).Trace("database: created tag node") + + return nil +} diff --git a/internal/utils/modelConvert.go b/internal/utils/modelConvert.go index cc75258..080af20 100644 --- a/internal/utils/modelConvert.go +++ b/internal/utils/modelConvert.go @@ -1,6 +1,7 @@ package utils import ( + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" ) @@ -25,3 +26,22 @@ func PostgresConvertToAnthroveSource(pgSource *pgModels.Source) *graphModels.Ant return graphSource } + +// GraphConvertTag converts a graphModels.AnthroveTag to a pgModels.Tag +func GraphConvertTag(graphTag *graphModels.AnthroveTag) *pgModels.Tag { + pgTag := &pgModels.Tag{ + Name: graphTag.Name, + Type: models.TagType(graphTag.Type), + } + return pgTag +} + +// PostgresConvertToAnthroveTag converts a pgModels.Tag to a graphModels.AnthroveTag +func PostgresConvertToAnthroveTag(pgTag *pgModels.Tag) *graphModels.AnthroveTag { + graphTag := &graphModels.AnthroveTag{ + Name: pgTag.Name, + Type: string(pgTag.Type), + } + + return graphTag +} diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index 00fcf9c..66770a1 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -1,9 +1,3 @@ --- TODO: Add the following fields where its defined in the model --- created_at --- updated_at --- deleted_at - - -- +migrate Up CREATE TYPE Rating AS ENUM ( 'safe', @@ -23,29 +17,39 @@ CREATE TYPE TagType AS ENUM ( CREATE TABLE "Post" ( - id VARCHAR(25) UNIQUE PRIMARY KEY, + id CHAR(25) UNIQUE PRIMARY KEY, rating Rating, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP NULL NULL ); CREATE TABLE "Source" ( - id VARCHAR(25) UNIQUE PRIMARY KEY, - display_name TEXT, - icon TEXT, - domain TEXT NOT NULL UNIQUE + id CHAR(25) UNIQUE PRIMARY KEY, + display_name TEXT NULL, + icon TEXT NULL, + domain TEXT NOT NULL UNIQUE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP NULL ); CREATE TABLE "Tag" ( - name TEXT PRIMARY KEY, - type TagType + name TEXT PRIMARY KEY, + tag_type TagType, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP NULL ); CREATE TABLE "User" ( id TEXT UNIQUE PRIMARY KEY, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP NULL ); CREATE TABLE "PostReference" @@ -59,20 +63,22 @@ CREATE TABLE "PostReference" CREATE TABLE "TagAlias" ( - name TEXT PRIMARY KEY, - tag_id TEXT REFERENCES "Tag" (name) + name TEXT PRIMARY KEY, + tag_id TEXT REFERENCES "Tag" (name), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE "TagGroup" ( - name TEXT PRIMARY KEY, - tag_id TEXT REFERENCES "Tag" (name) + name TEXT PRIMARY KEY, + tag_id TEXT REFERENCES "Tag" (name), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE "UserFavorites" ( - user_id TEXT REFERENCES "User" (id), - post_id TEXT REFERENCES "Post" (id), + user_id TEXT UNIQUE REFERENCES "User" (id), + post_id TEXT UNIQUE REFERENCES "Post" (id), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, post_id) ); @@ -83,18 +89,26 @@ CREATE TABLE "UserSource" source_id TEXT REFERENCES "Source" (id), account_username TEXT, account_id TEXT, - PRIMARY KEY (user_id, source_id) + PRIMARY KEY (user_id, source_id), + UNIQUE (account_username, account_id) +); + +CREATE TABLE "post_tags" +( + post_id TEXT REFERENCES "Post" (id), + tag_name TEXT REFERENCES "Tag" (name), + PRIMARY KEY (post_id, tag_name) ); -- +migrate Down DROP TYPE Rating; DROP TYPE TagType; -DROP TYPE Post; -DROP TYPE Source; -DROP TYPE Tag; -DROP TYPE User; -DROP TYPE PostReference; -DROP TYPE TagAlias; -DROP TYPE TagGroup; -DROP TYPE UserFavorites; -DROP TYPE UserSource; \ No newline at end of file +DROP TABLE Post; +DROP TABLE Source; +DROP TABLE Tag; +DROP TABLE User; +DROP TABLE PostReference; +DROP TABLE TagAlias; +DROP TABLE TagGroup; +DROP TABLE UserFavorites; +DROP TABLE UserSource; \ No newline at end of file diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 5ed0afe..f1d8402 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -68,8 +68,7 @@ func (p *postgresqlConnection) AddPost(ctx context.Context, anthrovePost *graphM } func (p *postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { - //TODO implement me - panic("implement me") + return postgres.CreateTagNodeWitRelation(ctx, p.db, anthrovePostID, utils.GraphConvertTag(anthroveTag)) } func (p *postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { diff --git a/pkg/models/pgModels/orm.go b/pkg/models/pgModels/orm.go index bea5f1b..11aafa4 100644 --- a/pkg/models/pgModels/orm.go +++ b/pkg/models/pgModels/orm.go @@ -1,6 +1,7 @@ package pgModels import ( + gonanoid "github.com/matoous/go-nanoid/v2" "gorm.io/gorm" "time" ) @@ -11,3 +12,14 @@ type BaseModel struct { UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } + +func (base *BaseModel) BeforeCreate(db *gorm.DB) error { + id, err := gonanoid.New() + if err != nil { + return err + } + + base.ID = id + + return nil +} diff --git a/pkg/models/pgModels/post.go b/pkg/models/pgModels/post.go index d2dd980..d5ea588 100644 --- a/pkg/models/pgModels/post.go +++ b/pkg/models/pgModels/post.go @@ -12,3 +12,7 @@ type Post struct { Favorites []UserFavorite `gorm:"foreignKey:PostID"` References []PostReference `gorm:"foreignKey:PostID"` } + +func (Post) TableName() string { + return "Post" +} diff --git a/pkg/models/pgModels/tag.go b/pkg/models/pgModels/tag.go index 406f744..7538ac9 100644 --- a/pkg/models/pgModels/tag.go +++ b/pkg/models/pgModels/tag.go @@ -4,11 +4,15 @@ import "git.dragse.it/anthrove/otter-space-sdk/pkg/models" // Tag models type Tag struct { - Name string `gorm:"primaryKey"` - Type models.TagType - Aliases []TagAlias `gorm:"foreignKey:TagID"` - Groups []TagGroup `gorm:"foreignKey:TagID"` - Posts []Post `gorm:"many2many:post_tags;"` + Name string `gorm:"primaryKey"` + Type models.TagType `gorm:"column:tag_type"` + Aliases []TagAlias `gorm:"foreignKey:TagID"` + Groups []TagGroup `gorm:"foreignKey:TagID"` + Posts []Post `gorm:"many2many:post_tags;"` +} + +func (Tag) TableName() string { + return "Tag" } // TagAlias model @@ -17,8 +21,16 @@ type TagAlias struct { TagID string } +func (TagAlias) TableName() string { + return "TagAlias" +} + // TagGroup model type TagGroup struct { Name string `gorm:"primaryKey"` TagID string } + +func (TagGroup) TableName() string { + return "TagGroup" +} From a60805fccfcaf0454cf235565687e921ad7cc2c2 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 12:06:58 +0200 Subject: [PATCH 019/124] feat(postgres): added console debug option --- pkg/database/postgres.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index f1d8402..e4ee38a 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -5,7 +5,6 @@ import ( "database/sql" "embed" "fmt" - "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" "git.dragse.it/anthrove/otter-space-sdk/internal/utils" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" @@ -21,12 +20,14 @@ import ( var embedMigrations embed.FS type postgresqlConnection struct { - db *gorm.DB + db *gorm.DB + debug bool } -func NewPostgresqlConnection() OtterSpace { +func NewPostgresqlConnection(debugOutput bool) OtterSpace { return &postgresqlConnection{ - db: nil, + db: nil, + debug: debugOutput, } } @@ -170,12 +171,15 @@ func (p *postgresqlConnection) migrateDatabase(connectionString string) error { if err != nil { return fmt.Errorf("postgres migration: %v", err) } - if n != 0 { - log.Tracef("postgres migration: applied %d migrations!", n) - } else { - log.Trace("postgres migration: nothing to migrate") + if p.debug { + if n != 0 { + log.Infof("postgres migration: applied %d migrations!", n) + } else { + log.Info("postgres migration: nothing to migrate") + + } } return nil From aae7fc78e00ccb7a6b72922b76e3697e6e76dc46 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 12:24:14 +0200 Subject: [PATCH 020/124] feat(postgres): added image urls to the database --- .../migrations/001_inital_database.sql | 21 +++++++++++-------- pkg/models/pgModels/postReference.go | 11 ++++++---- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index 66770a1..c78c150 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -27,9 +27,9 @@ CREATE TABLE "Post" CREATE TABLE "Source" ( id CHAR(25) UNIQUE PRIMARY KEY, - display_name TEXT NULL, - icon TEXT NULL, - domain TEXT NOT NULL UNIQUE, + display_name TEXT NULL, + icon TEXT NULL, + domain TEXT NOT NULL UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, deleted_at TIMESTAMP NULL @@ -54,10 +54,13 @@ CREATE TABLE "User" CREATE TABLE "PostReference" ( - post_id TEXT REFERENCES "Post" (id), - source_id TEXT REFERENCES "Source" (id), - url TEXT NOT NULL UNIQUE, - source_post_id TEXT, + post_id TEXT REFERENCES "Post" (id), + source_id TEXT REFERENCES "Source" (id), + url TEXT NOT NULL UNIQUE, + full_file_url TEXT, + preview_file_url TEXT, + sample_file_url TEXT, + source_post_id TEXT, PRIMARY KEY (post_id, source_id) ); @@ -77,8 +80,8 @@ CREATE TABLE "TagGroup" CREATE TABLE "UserFavorites" ( - user_id TEXT UNIQUE REFERENCES "User" (id), - post_id TEXT UNIQUE REFERENCES "Post" (id), + user_id TEXT UNIQUE REFERENCES "User" (id), + post_id TEXT UNIQUE REFERENCES "Post" (id), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, post_id) ); diff --git a/pkg/models/pgModels/postReference.go b/pkg/models/pgModels/postReference.go index ae4574c..1163731 100644 --- a/pkg/models/pgModels/postReference.go +++ b/pkg/models/pgModels/postReference.go @@ -1,8 +1,11 @@ package pgModels type PostReference struct { - PostID string `gorm:"primaryKey"` - SourceID string `gorm:"primaryKey"` - URL string `gorm:"not null;unique"` - SourcePostID string + PostID string `gorm:"primaryKey"` + SourceID string `gorm:"primaryKey"` + URL string `gorm:"not null;unique"` + SourcePostID string + FullFileURL string + PreviewFileURL string + SampleFileURL string } From 011f4d1c2a39e78e0def2a8795939fa88cd5717f Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 13:05:07 +0200 Subject: [PATCH 021/124] feat(postgres): added tag create and function to get all tags --- go.mod | 3 ++- go.sum | 6 ++++-- internal/postgres/tag.go | 14 ++++++++++++++ internal/utils/modelConvert.go | 13 +++++++++++++ pkg/database/postgres.go | 5 +++-- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 9dcb619..4b598af 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,9 @@ module git.dragse.it/anthrove/otter-space-sdk go 1.22.0 require ( + github.com/brianvoe/gofakeit/v7 v7.0.3 github.com/lib/pq v1.10.7 + github.com/matoous/go-nanoid/v2 v2.1.0 github.com/neo4j/neo4j-go-driver/v5 v5.17.0 github.com/rubenv/sql-migrate v1.6.1 github.com/sirupsen/logrus v1.9.3 @@ -19,7 +21,6 @@ require ( github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/matoous/go-nanoid/v2 v2.1.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.18.0 // indirect diff --git a/go.sum b/go.sum index f00d304..9cd0cd1 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/brianvoe/gofakeit/v7 v7.0.3 h1:tGCt+eYfhTMWE1ko5G2EO1f/yE44yNpIwUb4h32O0wo= +github.com/brianvoe/gofakeit/v7 v7.0.3/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -42,8 +44,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 1dc97b1..d873506 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -36,3 +36,17 @@ func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.An return nil } + +func GetTags(ctx context.Context, db *gorm.DB) ([]pgModels.Tag, error) { + var tags []pgModels.Tag + result := db.WithContext(ctx).Find(&tags) + if result.Error != nil { + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tag_amount": len(tags), + }).Trace("database: got tags") + + return tags, nil +} diff --git a/internal/utils/modelConvert.go b/internal/utils/modelConvert.go index 080af20..29a4995 100644 --- a/internal/utils/modelConvert.go +++ b/internal/utils/modelConvert.go @@ -45,3 +45,16 @@ func PostgresConvertToAnthroveTag(pgTag *pgModels.Tag) *graphModels.AnthroveTag return graphTag } + +func ConvertToTagsWithFrequency(tags []pgModels.Tag) []graphModels.TagsWithFrequency { + var tagsWithFrequency []graphModels.TagsWithFrequency + for _, tag := range tags { + graphTag := PostgresConvertToAnthroveTag(&tag) + tagsWithFrequency = append(tagsWithFrequency, graphModels.TagsWithFrequency{ + Frequency: 0, + Tags: *graphTag, + }) + } + + return tagsWithFrequency +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index e4ee38a..887a62a 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -138,8 +138,9 @@ func (p *postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, } func (p *postgresqlConnection) GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) { - //TODO implement me - panic("implement me") + tags, err := postgres.GetTags(ctx, p.db) + + return utils.ConvertToTagsWithFrequency(tags), err } func (p *postgresqlConnection) GetAllSources(ctx context.Context) ([]graphModels.AnthroveSource, error) { From 8d655e991fbca1792bef9ecd80b93ef9d04f598a Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 13:19:55 +0200 Subject: [PATCH 022/124] feat(postgres): added LinkPostWithSource --- internal/postgres/relationships.go | 39 ++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 internal/postgres/relationships.go diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go new file mode 100644 index 0000000..b3170d4 --- /dev/null +++ b/internal/postgres/relationships.go @@ -0,0 +1,39 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string) error { + var post pgModels.Post + var source pgModels.Source + + // Find the post + err := db.WithContext(ctx).Where("id = ?", anthrovePostID).First(&post).Error + if err != nil { + return err + } + + // Find the source + err = db.WithContext(ctx).Where("domain = ?", anthroveSourceDomain).First(&source).Error + if err != nil { + return err + } + + // Establish the relationship + err = db.WithContext(ctx).Model(&post).Association("Sources").Append(&source) + if err != nil { + return err + } + + log.WithFields(log.Fields{ + "anthrove_post_id": anthrovePostID, + "anthrove_source_domain": anthroveSourceDomain, + }).Trace("database: created anthrove post to source link") + + return nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 887a62a..bd57a64 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -73,8 +73,7 @@ func (p *postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, ant } func (p *postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { - //TODO implement me - panic("implement me") + return postgres.EstablishAnthrovePostToSourceLink(ctx, p.db, anthrovePostID, anthroveSourceDomain) } func (p *postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { From a430c3b5820ecd31a446ea335d42e76f83f04081 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 13:22:52 +0200 Subject: [PATCH 023/124] feat(postgres): added LinkUserWithPost --- internal/postgres/relationships.go | 19 +++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index b3170d4..1a07396 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -37,3 +37,22 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrov return nil } + +func EstablishUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { + userFavorite := pgModels.UserFavorite{ + UserID: string(anthroveUserID), + PostID: string(anthrovePostID), + } + + err := db.WithContext(ctx).Create(&userFavorite).Error + if err != nil { + return err + } + + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + "anthrove_post_id": anthrovePostID, + }).Trace("database: created user to post link") + + return nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index bd57a64..a4a9008 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -77,8 +77,7 @@ func (p *postgresqlConnection) LinkPostWithSource(ctx context.Context, anthroveP } func (p *postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { - //TODO implement me - panic("implement me") + return postgres.EstablishUserToPostLink(ctx, p.db, anthroveUser.UserID, anthrovePost.PostID) } func (p *postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { From ad3a43366be52cd2359cff75bcaff830d93d267a Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 13:25:54 +0200 Subject: [PATCH 024/124] feat(postgres): added CheckUserPostLink --- internal/postgres/relationships.go | 18 ++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index 1a07396..fd855eb 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -56,3 +56,21 @@ func EstablishUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID mo return nil } + +func CheckUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { + var count int64 + err := db.WithContext(ctx).Model(&pgModels.UserFavorite{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count).Error + if err != nil { + return false, err + } + + exists := count > 0 + + log.WithFields(log.Fields{ + "relationship_exists": exists, + "relationship_anthrove_user_id": anthroveUserID, + "relationship_anthrove_post_id": anthrovePostID, + }).Trace("database: checked user post relationship") + + return exists, nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index a4a9008..661a884 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -81,8 +81,7 @@ func (p *postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUse } func (p *postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { - //TODO implement me - panic("implement me") + return postgres.CheckUserToPostLink(ctx, p.db, anthroveUserID, models.AnthrovePostID(sourcePostID)) } func (p *postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { From bd22ed3f7933a9990be34164f259b5fb1f9121f0 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 13:29:53 +0200 Subject: [PATCH 025/124] feat(postgres): added AddPost --- internal/postgres/post.go | 30 ++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 internal/postgres/post.go diff --git a/internal/postgres/post.go b/internal/postgres/post.go new file mode 100644 index 0000000..ff3d0d3 --- /dev/null +++ b/internal/postgres/post.go @@ -0,0 +1,30 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +func CreateAnthrovePostNode(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, anthroveRating models.Rating) error { + post := pgModels.Post{ + BaseModel: pgModels.BaseModel{ + ID: string(anthrovePostID), + }, + Rating: anthroveRating, + } + + err := db.WithContext(ctx).Create(&post).Error + if err != nil { + return err + } + + log.WithFields(log.Fields{ + "anthrove_post_id": anthrovePostID, + "anthrove_post_rating": anthroveRating, + }).Trace("database: created anthrove post") + + return nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 661a884..bc4b494 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -64,8 +64,7 @@ func (p *postgresqlConnection) AddSource(ctx context.Context, anthroveSource *gr } func (p *postgresqlConnection) AddPost(ctx context.Context, anthrovePost *graphModels.AnthrovePost) error { - //TODO implement me - panic("implement me") + return postgres.CreateAnthrovePostNode(ctx, p.db, anthrovePost.PostID, anthrovePost.Rating) } func (p *postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { From 78777ce7be48fb302784e7f93b1107cd42b4b80a Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 13:57:03 +0200 Subject: [PATCH 026/124] feat(postgres): partially added Check heckPostNodeExistsBy --- internal/postgres/post.go | 30 ++++++++++++++++++++++++++++++ pkg/database/postgres.go | 16 ++++++++++------ pkg/models/pgModels/orm.go | 13 ++++++++----- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index ff3d0d3..02ac938 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -28,3 +28,33 @@ func CreateAnthrovePostNode(ctx context.Context, db *gorm.DB, anthrovePostID mod return nil } + +func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID) (bool, error) { + return executeCheckQuery(ctx, db, "id = ?", string(anthrovePostID)) +} + +func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (bool, error) { + return executeCheckQuery(ctx, db, "url = ?", sourceURL) +} + +func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, db *gorm.DB, sourceID string) (bool, error) { + return executeCheckQuery(ctx, db, "source_id = ?", sourceID) +} + +func executeCheckQuery(ctx context.Context, db *gorm.DB, query string, args ...interface{}) (bool, error) { + var count int64 + err := db.WithContext(ctx).Model(&pgModels.Post{}).Where(query, args...).Count(&count).Error + if err != nil { + return false, err + } + + exists := count > 0 + + log.WithFields(log.Fields{ + "query": query, + "args": args, + "exists": exists, + }).Trace("database: executed check query") + + return exists, nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index bc4b494..a37c2e0 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -84,18 +84,22 @@ func (p *postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUs } func (p *postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { - //TODO implement me - panic("implement me") + exists, err := postgres.CheckIfAnthrovePostNodeExistsByAnthroveID(ctx, p.db, anthrovePost.PostID) + return anthrovePost, exists, err } +// CheckPostNodeExistsBySourceURL NOT WORKING! TODO! func (p *postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { - //TODO implement me - panic("implement me") + var post graphModels.AnthrovePost + exists, err := postgres.CheckIfAnthrovePostNodeExistsBySourceURL(ctx, p.db, sourceUrl) + return &post, exists, err } +// CheckPostNodeExistsBySourceID NOT WORKING! TODO! func (p *postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*graphModels.AnthrovePost, bool, error) { - //TODO implement me - panic("implement me") + var post graphModels.AnthrovePost + exists, err := postgres.CheckIfAnthrovePostNodeExistsBySourceID(ctx, p.db, sourcePostID) + return &post, exists, err } func (p *postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { diff --git a/pkg/models/pgModels/orm.go b/pkg/models/pgModels/orm.go index 11aafa4..c637fa5 100644 --- a/pkg/models/pgModels/orm.go +++ b/pkg/models/pgModels/orm.go @@ -14,12 +14,15 @@ type BaseModel struct { } func (base *BaseModel) BeforeCreate(db *gorm.DB) error { - id, err := gonanoid.New() - if err != nil { - return err - } - base.ID = id + if base.ID == "" { + id, err := gonanoid.New() + if err != nil { + return err + } + + base.ID = id + } return nil } From c04e382ee5f5b2b2a752969f1c00855e75f0e03b Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 14:48:23 +0200 Subject: [PATCH 027/124] feat(postgres): added AddUserWithRelationToSource --- internal/postgres/user.go | 61 +++++++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +- 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 internal/postgres/user.go diff --git a/internal/postgres/user.go b/internal/postgres/user.go new file mode 100644 index 0000000..f24191d --- /dev/null +++ b/internal/postgres/user.go @@ -0,0 +1,61 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { + user := pgModels.User{ + BaseModel: pgModels.BaseModel{ + ID: string(anthroveUserID), + }, + } + + if err := db.WithContext(ctx).FirstOrCreate(&user).Error; err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + }).Error("database: failed to find or create user") + return err + } + + source := pgModels.Source{ + Domain: sourceDomain, + } + + if err := db.WithContext(ctx).Where(&source).First(&source).Error; err != nil { + log.WithFields(log.Fields{ + "source_domain": sourceDomain, + }).Error("database: failed to find source") + return err + } + + userSource := pgModels.UserSource{ + UserID: user.ID, + SourceID: source.ID, + AccountUsername: username, + AccountID: userID, + } + + if err := db.WithContext(ctx).Create(&userSource).Error; err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + "source_domain": sourceDomain, + "account_username": username, + "account_id": userID, + }).Error("database: failed to create user-source relationship") + return err + } + + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + "source_domain": sourceDomain, + "account_username": username, + "account_id": userID, + }).Trace("database: created user-source relationship") + + return nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index a37c2e0..13fe10d 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -54,8 +54,7 @@ func (p *postgresqlConnection) Connect(_ context.Context, endpoint string, usern } func (p *postgresqlConnection) AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { - //TODO implement me - panic("implement me") + return postgres.CreateUserNodeWithSourceRelation(ctx, p.db, anthroveUserID, userID, sourceDomain, userID) } func (p *postgresqlConnection) AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error { From 4f8e54f09a0b3dc05784d535c8f1e375a82d67a7 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 14:50:29 +0200 Subject: [PATCH 028/124] feat(postgres): added GetUserFavoriteCount --- internal/postgres/user.go | 18 ++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index f24191d..acd9695 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -59,3 +59,21 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthrove return nil } + +func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (int64, error) { + var count int64 + err := db.WithContext(ctx).Model(&pgModels.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Count(&count).Error + if err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + }).Error("database: failed to get user favorites count") + return 0, err + } + + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + "anthrove_user_fav_count": count, + }).Trace("database: got user favorite count") + + return count, nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 13fe10d..883de13 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -102,8 +102,7 @@ func (p *postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context } func (p *postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { - //TODO implement me - panic("implement me") + return postgres.GetUserFavoritesCount(ctx, p.db, anthroveUserID) } func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { From 16d5a381df9ba7c041bfdd9c55f2c7203c5e35f5 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 15:03:34 +0200 Subject: [PATCH 029/124] feat(postgres): added GetUserSourceLinks --- internal/postgres/user.go | 41 +++++++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index acd9695..a2e60fe 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -3,6 +3,7 @@ package postgres import ( "context" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -77,3 +78,43 @@ func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID mode return count, nil } + +func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { + var userSources []pgModels.UserSource + userSourceMap := make(map[string]graphModels.AnthroveUserRelationship) + + err := db.WithContext(ctx).Model(&pgModels.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error + if err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + }).Error("database: failed to get user source link") + return nil, err + } + + for _, userSource := range userSources { + var source pgModels.Source + err = db.WithContext(ctx).Model(&pgModels.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error + if err != nil { + log.WithFields(log.Fields{ + "source_id": userSource.SourceID, + }).Error("database: failed to get source") + return nil, err + } + + userSourceMap[source.DisplayName] = graphModels.AnthroveUserRelationship{ + UserID: userSource.AccountID, + Username: userSource.AccountUsername, + Source: graphModels.AnthroveSource{ + DisplayName: source.DisplayName, + Domain: source.Domain, + Icon: source.Icon, + }, + } + } + + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + }).Trace("database: got user source link") + + return userSourceMap, nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 883de13..7d095b0 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -106,8 +106,7 @@ func (p *postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthrov } func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { - //TODO implement me - panic("implement me") + return postgres.GetUserSourceLink(ctx, p.db, anthroveUserID) } func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { From bbd08b9a2f17aa77342a70280730aa05878ac965 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 15:04:45 +0200 Subject: [PATCH 030/124] feat(postgres): added GetSpecifiedUserSourceLink --- internal/postgres/user.go | 42 +++++++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index a2e60fe..b27f55b 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -118,3 +118,45 @@ func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.A return userSourceMap, nil } + +func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { + var userSources []pgModels.UserSource + userSourceMap := make(map[string]graphModels.AnthroveUserRelationship) + + err := db.WithContext(ctx).Model(&pgModels.UserSource{}).Joins("Source").Where("user_id = ? AND display_name = ?", string(anthroveUserID), sourceDisplayName).Find(&userSources).Error + if err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + "source_display_name": sourceDisplayName, + }).Error("database: failed to get specified user source link") + return nil, err + } + + for _, userSource := range userSources { + var source pgModels.Source + err = db.WithContext(ctx).Model(&pgModels.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error + if err != nil { + log.WithFields(log.Fields{ + "source_id": userSource.SourceID, + }).Error("database: failed to get source") + return nil, err + } + + userSourceMap[source.DisplayName] = graphModels.AnthroveUserRelationship{ + UserID: userSource.AccountID, + Username: userSource.AccountUsername, + Source: graphModels.AnthroveSource{ + DisplayName: source.DisplayName, + Domain: source.Domain, + Icon: source.Icon, + }, + } + } + + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + "source_display_name": sourceDisplayName, + }).Trace("database: got specified user source link") + + return userSourceMap, nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 7d095b0..b738d79 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -110,8 +110,7 @@ func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveU } func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { - //TODO implement me - panic("implement me") + return postgres.GetSpecifiedUserSourceLink(ctx, p.db, anthroveUserID, sourceDisplayName) } func (p *postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { From 4cdd4450d52f5874e6549efdf76dd36b7ba65540 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 15:07:23 +0200 Subject: [PATCH 031/124] feat(postgres): added GetAnthroveUser --- internal/postgres/user.go | 51 +++++++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index b27f55b..d250f1f 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -160,3 +160,54 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID return userSourceMap, nil } + +func GetAnthroveUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { + var user pgModels.User + var userSources []pgModels.UserSource + anthroveUser := &graphModels.AnthroveUser{ + UserID: anthroveUserID, + } + + err := db.WithContext(ctx).First(&user, "id = ?", string(anthroveUserID)).Error + if err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + }).Error("database: failed to get user") + return nil, err + } + + err = db.WithContext(ctx).Model(&pgModels.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error + if err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + }).Error("database: failed to get user sources") + return nil, err + } + + for _, userSource := range userSources { + var source pgModels.Source + err = db.WithContext(ctx).Model(&pgModels.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error + if err != nil { + log.WithFields(log.Fields{ + "source_id": userSource.SourceID, + }).Error("database: failed to get source") + return nil, err + } + + anthroveUser.Relationship = append(anthroveUser.Relationship, graphModels.AnthroveUserRelationship{ + UserID: userSource.AccountID, + Username: userSource.AccountUsername, + Source: graphModels.AnthroveSource{ + DisplayName: source.DisplayName, + Domain: source.Domain, + Icon: source.Icon, + }, + }) + } + + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + }).Trace("database: got anthrove user") + + return anthroveUser, nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index b738d79..eea7600 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -114,8 +114,7 @@ func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, a } func (p *postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { - //TODO implement me - panic("implement me") + return postgres.GetAnthroveUser(ctx, p.db, anthroveUserID) } func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { From 6268a594cf7cace2e110fd7ab08e93cdc05cab76 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 15:09:11 +0200 Subject: [PATCH 032/124] feat(postgres): added GetAllAnthroveUserIDs --- internal/postgres/user.go | 21 +++++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index d250f1f..f149d14 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -211,3 +211,24 @@ func GetAnthroveUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Ant return anthroveUser, nil } + +func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveUserID, error) { + var users []pgModels.User + var userIDs []models.AnthroveUserID + + err := db.WithContext(ctx).Model(&pgModels.User{}).Find(&users).Error + if err != nil { + log.Error("database: failed to get all anthrove user IDs") + return nil, err + } + + for _, user := range users { + userIDs = append(userIDs, models.AnthroveUserID(user.ID)) + } + + log.WithFields(log.Fields{ + "anthrove_user_id_count": len(userIDs), + }).Trace("database: got all anthrove user IDs") + + return userIDs, nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index eea7600..7395bdf 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -118,8 +118,7 @@ func (p *postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUser } func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { - //TODO implement me - panic("implement me") + return postgres.GetAllAnthroveUserIDs(ctx, p.db) } func (p *postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { From 8cde1235ad034b43a679727aa9eb9f0498050557 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 15:11:13 +0200 Subject: [PATCH 033/124] feat(postgres): added GetUserFavoritePostsWithPagination --- internal/postgres/user.go | 40 +++++++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index f149d14..676bfa4 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -232,3 +232,43 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU return userIDs, nil } + +func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { + var userFavorites []pgModels.UserFavorite + var favoritePosts []graphModels.FavoritePost + + err := db.WithContext(ctx).Model(&pgModels.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error + if err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + "skip": skip, + "limit": limit, + }).Error("database: failed to get user favorites with pagination") + return nil, err + } + + for _, userFavorite := range userFavorites { + var post pgModels.Post + err = db.WithContext(ctx).Model(&pgModels.Post{}).Where("id = ?", userFavorite.PostID).First(&post).Error + if err != nil { + log.WithFields(log.Fields{ + "post_id": userFavorite.PostID, + }).Error("database: failed to get post") + return nil, err + } + + favoritePosts = append(favoritePosts, graphModels.FavoritePost{ + AnthrovePost: graphModels.AnthrovePost{ + PostID: models.AnthrovePostID(post.ID), + Rating: post.Rating, + }, + }) + } + + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + "anthrove_user_fav_count": len(favoritePosts), + }).Trace("database: got all anthrove user favorites") + + return &graphModels.FavoriteList{Posts: favoritePosts}, nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 7395bdf..a13f15d 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -122,8 +122,7 @@ func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]mod } func (p *postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { - //TODO implement me - panic("implement me") + return postgres.GetUserFavoriteNodeWithPagination(ctx, p.db, anthroveUserID, skip, limit) } func (p *postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { From 1da21024d74e6c62b64a32f6d8c0e33cfb0a3b45 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 15:16:31 +0200 Subject: [PATCH 034/124] feat(postgres): added GetUserTagsTroughFavedPosts --- internal/postgres/user.go | 44 +++++++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 676bfa4..f15b077 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -272,3 +272,47 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthrov return &graphModels.FavoriteList{Posts: favoritePosts}, nil } + +func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { + var userFavorites []pgModels.UserFavorite + err := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites).Error + if err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + }).Error("database: failed to get user favorites") + return nil, err + } + + tagFrequency := make(map[string]int) + for _, userFavorite := range userFavorites { + var postTags []pgModels.Tag + err = db.WithContext(ctx).Model(&pgModels.Post{}).Where("id = ?", userFavorite.PostID).Association("Tags").Find(&postTags) + if err != nil { + log.WithFields(log.Fields{ + "post_id": userFavorite.PostID, + }).Error("database: failed to get post tags") + return nil, err + } + + for _, tag := range postTags { + tagFrequency[tag.Name]++ + } + } + + var tagsWithFrequency []graphModels.TagsWithFrequency + for tagName, frequency := range tagFrequency { + tagsWithFrequency = append(tagsWithFrequency, graphModels.TagsWithFrequency{ + Frequency: int64(frequency), + Tags: graphModels.AnthroveTag{ + Name: tagName, + }, + }) + } + + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + "tag_amount": len(tagsWithFrequency), + }).Trace("database: got user tag node with relation to faved posts") + + return tagsWithFrequency, nil +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index a13f15d..c283bea 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -126,8 +126,7 @@ func (p *postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Co } func (p *postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { - //TODO implement me - panic("implement me") + return postgres.GetUserTagNodeWitRelationToFavedPosts(ctx, p.db, anthroveUserID) } func (p *postgresqlConnection) GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) { From 5a242c69898abe72db784148126c580b87233c1e Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 14 Jun 2024 15:43:40 +0200 Subject: [PATCH 035/124] docs(postgres): updated readme --- README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 732fd42..ffd7f3f 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,19 @@ import ( ) func main() { - client := graph.NewGraphConnection() - err := client.Connect(context.Background(), "your-endpoint", "your-username", "your-password") + var err error + dbDebug := false + ctx := context.Background() + + pgClient := database.NewPostgresqlConnection(dbDebug) + err = pgClient.Connect(ctx, "your-endpoint", "your-username", "your-password", "anthrove", 5432, "disable", "Europe/Berlin") + if err != nil { + fmt.Println(err) + return + } + + graphClient := database.NewGraphConnection(dbDebug) + err = graphClient.Connect(ctx, "your-endpoint", "your-username", "your-password", "NOT USED",0,"NOT USED","NOT USED") if err != nil { fmt.Println(err) return From 03ce8b52ae8c8e6e73fbdece6205571ec9519e3d Mon Sep 17 00:00:00 2001 From: soxx Date: Wed, 19 Jun 2024 23:32:42 +0200 Subject: [PATCH 036/124] test(postgres): added first tests and already fixed bugs --- go.mod | 57 ++++- go.sum | 178 ++++++++++++++- internal/postgres/post.go | 6 + internal/postgres/post_test.go | 136 ++++++++++++ internal/postgres/relationships.go | 19 +- internal/postgres/relationships_test.go | 280 ++++++++++++++++++++++++ internal/postgres/tag.go | 2 +- internal/postgres/user.go | 19 ++ pkg/models/const.go | 6 +- pkg/models/pgModels/postReference.go | 4 + pkg/models/pgModels/user.go | 4 + pkg/models/pgModels/userFavorite.go | 4 + test/helper.go | 77 +++++++ test/tag_test.go | 104 +++++++++ 14 files changed, 875 insertions(+), 21 deletions(-) create mode 100644 internal/postgres/post_test.go create mode 100644 internal/postgres/relationships_test.go create mode 100644 test/helper.go create mode 100644 test/tag_test.go diff --git a/go.mod b/go.mod index 4b598af..a25e991 100644 --- a/go.mod +++ b/go.mod @@ -4,25 +4,76 @@ go 1.22.0 require ( github.com/brianvoe/gofakeit/v7 v7.0.3 - github.com/lib/pq v1.10.7 + github.com/lib/pq v1.10.9 github.com/matoous/go-nanoid/v2 v2.1.0 github.com/neo4j/neo4j-go-driver/v5 v5.17.0 github.com/rubenv/sql-migrate v1.6.1 github.com/sirupsen/logrus v1.9.3 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.31.0 + github.com/testcontainers/testcontainers-go/modules/postgres v0.31.0 gorm.io/driver/postgres v1.5.7 gorm.io/gorm v1.25.10 ) require ( + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/containerd/containerd v1.7.15 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.5.0 // indirect + github.com/docker/docker v25.0.5+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.5.5 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - golang.org/x/crypto v0.21.0 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/mod v0.16.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.13.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d // indirect + google.golang.org/grpc v1.58.3 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9cd0cd1..3b9b10a 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,61 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/brianvoe/gofakeit/v7 v7.0.3 h1:tGCt+eYfhTMWE1ko5G2EO1f/yE44yNpIwUb4h32O0wo= github.com/brianvoe/gofakeit/v7 v7.0.3/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/containerd/containerd v1.7.15 h1:afEHXdil9iAm03BmhjzKyXnnEBtjaLJefdU7DV0IFes= +github.com/containerd/containerd v1.7.15/go.mod h1:ISzRRTMF8EXNpJlTzyr2XMhN+j9K302C21/+cr3kUnY= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= +github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v25.0.5+incompatible h1:UmQydMduGkrD5nQde1mecF/YnSbTOaPeFIeP5C4W+DE= +github.com/docker/docker v25.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -19,42 +68,157 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/matoous/go-nanoid/v2 v2.1.0 h1:P64+dmq21hhWdtvZfEAofnvJULaRR1Yib0+PnU669bE= github.com/matoous/go-nanoid/v2 v2.1.0/go.mod h1:KlbGNQ+FhrUNIHUxZdL63t7tl4LaPkZNpUULS8H4uVM= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/neo4j/neo4j-go-driver/v5 v5.17.0 h1:Bdqg1Y8Hd3uLYToXtBjysDYXTdMiP7zeUNUEwfbJkSo= github.com/neo4j/neo4j-go-driver/v5 v5.17.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rubenv/sql-migrate v1.6.1 h1:bo6/sjsan9HaXAsNxYP/jCEDUGibHp8JmOBw7NTGRos= github.com/rubenv/sql-migrate v1.6.1/go.mod h1:tPzespupJS0jacLfhbwto/UjSX+8h2FdWB7ar+QlHa0= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +github.com/testcontainers/testcontainers-go v0.31.0 h1:W0VwIhcEVhRflwL9as3dhY6jXjVCA27AkmbnZ+UTh3U= +github.com/testcontainers/testcontainers-go v0.31.0/go.mod h1:D2lAoA0zUFiSY+eAflqK5mcUx/A5hrrORaEQrd0SefI= +github.com/testcontainers/testcontainers-go/modules/postgres v0.31.0 h1:isAwFS3KNKRbJMbWv+wolWqOFUECmjYZ+sIRZCIBc/E= +github.com/testcontainers/testcontainers-go/modules/postgres v0.31.0/go.mod h1:ZNYY8vumNCEG9YI59A9d6/YaMY49uwRhmeU563EzFGw= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d h1:pgIUhmqwKOUlnKna4r6amKdUngdL8DrkpFeV8+VBElY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -65,3 +229,5 @@ gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 02ac938..1cd4472 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -2,6 +2,7 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" @@ -30,6 +31,10 @@ func CreateAnthrovePostNode(ctx context.Context, db *gorm.DB, anthrovePostID mod } func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID) (bool, error) { + if anthrovePostID == "" { + return false, fmt.Errorf("anthrovePostID is required") + } + return executeCheckQuery(ctx, db, "id = ?", string(anthrovePostID)) } @@ -43,6 +48,7 @@ func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, db *gorm.DB, s func executeCheckQuery(ctx context.Context, db *gorm.DB, query string, args ...interface{}) (bool, error) { var count int64 + err := db.WithContext(ctx).Model(&pgModels.Post{}).Where(query, args...).Count(&count).Error if err != nil { return false, err diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go new file mode 100644 index 0000000..20444e7 --- /dev/null +++ b/internal/postgres/post_test.go @@ -0,0 +1,136 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/test" + _ "github.com/lib/pq" + "gorm.io/gorm" + "testing" +) + +func TestCreateAnthrovePostNode(t *testing.T) { + + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + type args struct { + ctx context.Context + db *gorm.DB + anthrovePostID models.AnthrovePostID + anthroveRating models.Rating + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthrovePostID and Rating", + args: args{ + ctx: context.Background(), + db: gormDB, + anthrovePostID: "1234", + anthroveRating: models.Rating("safe"), + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthrovePostID and Rating", + args: args{ + ctx: context.Background(), + db: gormDB, + anthrovePostID: "", + anthroveRating: "a4dsa4d", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CreateAnthrovePostNode(tt.args.ctx, tt.args.db, tt.args.anthrovePostID, tt.args.anthroveRating); (err != nil) != tt.wantErr { + t.Errorf("CreateAnthrovePostNode() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestCheckIfAnthrovePostNodeExistsByAnthroveID(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") + if err != nil { + t.Fatal(err) + } + + // Test + + type args struct { + ctx context.Context + db *gorm.DB + anthrovePostID models.AnthrovePostID + } + tests := []struct { + name string + args args + want bool + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveID", + args: args{ + ctx: ctx, + db: gormDB, + anthrovePostID: "1234", + }, + want: true, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveID", + args: args{ + ctx: ctx, + db: gormDB, + anthrovePostID: "123456", + }, + want: false, + wantErr: false, + }, + { + name: "Test 3: No AnthroveID", + args: args{ + ctx: ctx, + db: gormDB, + anthrovePostID: "", + }, + want: false, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := CheckIfAnthrovePostNodeExistsByAnthroveID(tt.args.ctx, tt.args.db, tt.args.anthrovePostID) + if (err != nil) != tt.wantErr { + t.Errorf("CheckIfAnthrovePostNodeExistsByAnthroveID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("CheckIfAnthrovePostNodeExistsByAnthroveID() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index fd855eb..7ee9fd7 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -2,6 +2,7 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" @@ -9,14 +10,8 @@ import ( ) func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string) error { - var post pgModels.Post var source pgModels.Source - - // Find the post - err := db.WithContext(ctx).Where("id = ?", anthrovePostID).First(&post).Error - if err != nil { - return err - } + var err error // Find the source err = db.WithContext(ctx).Where("domain = ?", anthroveSourceDomain).First(&source).Error @@ -25,7 +20,11 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrov } // Establish the relationship - err = db.WithContext(ctx).Model(&post).Association("Sources").Append(&source) + err = db.WithContext(ctx).Create(pgModels.PostReference{ + PostID: string(anthrovePostID), + SourceID: source.ID, + }).Error + if err != nil { return err } @@ -66,6 +65,10 @@ func CheckUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID models exists := count > 0 + if !exists { + return false, fmt.Errorf("no post link exists") + } + log.WithFields(log.Fields{ "relationship_exists": exists, "relationship_anthrove_user_id": anthroveUserID, diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go new file mode 100644 index 0000000..d5033d9 --- /dev/null +++ b/internal/postgres/relationships_test.go @@ -0,0 +1,280 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" + "git.dragse.it/anthrove/otter-space-sdk/test" + "gorm.io/gorm" + "testing" +) + +func TestEstablishAnthrovePostToSourceLink(t *testing.T) { + + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") + if err != nil { + t.Fatal(err) + } + + source := &pgModels.Source{ + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + } + err = CreateSourceNode(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + // Test + + type args struct { + ctx context.Context + db *gorm.DB + anthrovePostID models.AnthrovePostID + anthroveSourceDomain string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthrovePostID and anthroveSourceDomain", + args: args{ + ctx: ctx, + db: gormDB, + anthrovePostID: "1234", + anthroveSourceDomain: "e621.net", + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthrovePostID and Valid anthroveSourceDomain", + args: args{ + ctx: ctx, + db: gormDB, + anthrovePostID: "123456", + anthroveSourceDomain: "e621.net", + }, + wantErr: true, + }, + { + name: "Test 3: Invalid anthroveSourceDomain and Valid AnthrovePostID", + args: args{ + ctx: ctx, + db: gormDB, + anthrovePostID: "1234", + anthroveSourceDomain: "fa.banana", + }, + wantErr: true, + }, + { + name: "Test 4: Invalid anthroveSourceDomain and Invalid AnthrovePostID", + args: args{ + ctx: ctx, + db: gormDB, + anthrovePostID: "696969", + anthroveSourceDomain: "hehe.funny.number", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := EstablishAnthrovePostToSourceLink(tt.args.ctx, tt.args.db, tt.args.anthrovePostID, tt.args.anthroveSourceDomain); (err != nil) != tt.wantErr { + t.Errorf("EstablishAnthrovePostToSourceLink() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestEstablishUserToPostLink(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + err = CreateUser(ctx, gormDB, "1") + if err != nil { + t.Fatal(err) + } + + err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + anthrovePostID models.AnthrovePostID + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveUserID and AnthrovePostID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + anthrovePostID: "1234", + }, + wantErr: false, + }, + { + name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + anthrovePostID: "123456", + }, + wantErr: true, + }, + { + name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "123", + anthrovePostID: "1234", + }, + wantErr: true, + }, + { + name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "123", + anthrovePostID: "123456", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := EstablishUserToPostLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID); (err != nil) != tt.wantErr { + t.Errorf("EstablishUserToPostLink() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestCheckUserToPostLink(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + err = CreateUser(ctx, gormDB, "1") + if err != nil { + t.Fatal(err) + } + + err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") + if err != nil { + t.Fatal(err) + } + + err = EstablishUserToPostLink(ctx, gormDB, "1", "1234") + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + anthrovePostID models.AnthrovePostID + } + tests := []struct { + name string + args args + want bool + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveUserID and AnthrovePostID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + anthrovePostID: "1234", + }, + want: true, + wantErr: false, + }, + { + name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + anthrovePostID: "123456", + }, + want: false, + wantErr: true, + }, + { + name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "123", + anthrovePostID: "1234", + }, + want: false, + wantErr: true, + }, + { + name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "123", + anthrovePostID: "123456", + }, + want: false, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := CheckUserToPostLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) + if (err != nil) != tt.wantErr { + t.Errorf("CheckUserToPostLink() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("CheckUserToPostLink() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index d873506..02072c2 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -22,7 +22,7 @@ func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.An }, } - err := db.WithContext(ctx).Model(pgPost).Association("Tags").Append(tag) + err := db.WithContext(ctx).Model(&pgPost).Association("Tags").Append(tag) if err != nil { return err diff --git a/internal/postgres/user.go b/internal/postgres/user.go index f15b077..472625a 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -9,6 +9,25 @@ import ( "gorm.io/gorm" ) +func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { + + user := pgModels.User{ + BaseModel: pgModels.BaseModel{ + ID: string(anthroveUserID), + }, + } + + err := db.WithContext(ctx).Create(&user).Error + if err != nil { + log.WithFields(log.Fields{ + "anthrove_user_id": anthroveUserID, + }).Error("database: failed to create user") + return err + } + + return nil +} + func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { user := pgModels.User{ BaseModel: pgModels.BaseModel{ diff --git a/pkg/models/const.go b/pkg/models/const.go index 552193d..0b7d944 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -6,9 +6,9 @@ type Rating string type TagType string const ( - SFW Rating = "s" - NSFW Rating = "e" - Questionable Rating = "q" + SFW Rating = "safe" + NSFW Rating = "explicit" + Questionable Rating = "questionable" Unknown Rating = "unknown" ) diff --git a/pkg/models/pgModels/postReference.go b/pkg/models/pgModels/postReference.go index 1163731..8ab7797 100644 --- a/pkg/models/pgModels/postReference.go +++ b/pkg/models/pgModels/postReference.go @@ -9,3 +9,7 @@ type PostReference struct { PreviewFileURL string SampleFileURL string } + +func (PostReference) TableName() string { + return "PostReference" +} diff --git a/pkg/models/pgModels/user.go b/pkg/models/pgModels/user.go index 7fe7e73..1120ae7 100644 --- a/pkg/models/pgModels/user.go +++ b/pkg/models/pgModels/user.go @@ -6,3 +6,7 @@ type User struct { Favorites []UserFavorite `gorm:"foreignKey:UserID"` Sources []UserSource `gorm:"foreignKey:UserID"` } + +func (User) TableName() string { + return "User" +} diff --git a/pkg/models/pgModels/userFavorite.go b/pkg/models/pgModels/userFavorite.go index 2e194a3..e01093f 100644 --- a/pkg/models/pgModels/userFavorite.go +++ b/pkg/models/pgModels/userFavorite.go @@ -7,3 +7,7 @@ type UserFavorite struct { PostID string `gorm:"primaryKey"` CreatedAt time.Time } + +func (UserFavorite) TableName() string { + return "UserFavorites" +} diff --git a/test/helper.go b/test/helper.go new file mode 100644 index 0000000..4f50991 --- /dev/null +++ b/test/helper.go @@ -0,0 +1,77 @@ +package test + +import ( + "context" + "database/sql" + migrate "github.com/rubenv/sql-migrate" + postgrescontainer "github.com/testcontainers/testcontainers-go/modules/postgres" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "time" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +const ( + databaseName = "anthrove" + databaseUser = "anthrove" + databasePassword = "anthrove" + migrationSource = "../../pkg/database/migrations" +) + +func StartPostgresContainer(ctx context.Context) (*postgrescontainer.PostgresContainer, *gorm.DB, error) { + + pgContainer, err := postgrescontainer.RunContainer(ctx, + testcontainers.WithImage("postgres:alpine"), + postgrescontainer.WithDatabase(databaseName), + postgrescontainer.WithUsername(databaseUser), + postgrescontainer.WithPassword(databasePassword), + testcontainers.WithWaitStrategy( + wait.ForLog("database system is ready to accept connections"). + WithOccurrence(2).WithStartupTimeout(5*time.Second)), + ) + if err != nil { + return nil, nil, err + } + + connectionString, err := pgContainer.ConnectionString(ctx, "sslmode=disable") + if err != nil { + return nil, nil, err + } + + err = migrateDatabase(connectionString) + if err != nil { + return nil, nil, err + + } + + gormDB, err := getGormDB(connectionString) + if err != nil { + return nil, nil, err + } + return pgContainer, gormDB, nil +} + +func migrateDatabase(connectionString string) error { + db, err := sql.Open("postgres", connectionString) + if err != nil { + return err + } + + migrations := &migrate.FileMigrationSource{ + Dir: migrationSource, + } + + _, err = migrate.Exec(db, "postgres", migrations, migrate.Up) + if err != nil { + return err + } + + return nil + +} + +func getGormDB(connectionString string) (*gorm.DB, error) { + return gorm.Open(postgres.Open(connectionString), &gorm.Config{}) +} diff --git a/test/tag_test.go b/test/tag_test.go new file mode 100644 index 0000000..3c9c4f8 --- /dev/null +++ b/test/tag_test.go @@ -0,0 +1,104 @@ +package test + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/database" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" + "log" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +type CustomerRepoTestSuite struct { + suite.Suite + database database.OtterSpace + pgContainer *PostgresContainer + ctx context.Context +} + +func (suite *CustomerRepoTestSuite) SetupSuite() { + suite.ctx = context.Background() + pgContainer, err := CreatePostgresContainer(suite.ctx) + if err != nil { + log.Fatal(err) + } + suite.pgContainer = pgContainer + + databaseClient := database.NewPostgresqlConnection(true) + containerInspect, _ := suite.pgContainer.Inspect(suite.ctx) + dbPortMap := containerInspect.NetworkSettings.Ports + var dbPortStr string + for _, v := range dbPortMap { + for _, n := range v { + dbPortStr = n.HostPort + } + } + dbPort, err := strconv.Atoi(dbPortStr) + if err != nil { + log.Fatal(err) + } + err = databaseClient.Connect(suite.ctx, "localhost", suite.pgContainer.DatabaseUser, suite.pgContainer.DatabasePassword, suite.pgContainer.DatabaseName, dbPort, "disable", "Europe/Berlin") + if err != nil { + log.Fatal(err) + } + suite.database = databaseClient + +} + +func (suite *CustomerRepoTestSuite) TearDownSuite() { + if err := suite.pgContainer.Terminate(suite.ctx); err != nil { + log.Fatalf("error terminating postgres container: %s", err) + } +} + +func (suite *CustomerRepoTestSuite) TestCreateTagNodeWitRelation() { + t := suite.T() + post := graphModels.AnthrovePost{ + PostID: "1234", + Rating: models.SFW, + } + + tag := &graphModels.AnthroveTag{ + Name: "test_tag", + Type: "general", + } + + err := suite.database.AddPost(suite.ctx, &post) + + if err != nil { + t.Fatal(err) + } + + err = suite.database.AddTagWithRelationToPost(suite.ctx, "1234", tag) + + assert.NoError(t, err) +} + +func (suite *CustomerRepoTestSuite) TestGetTags() { + t := suite.T() + + expectedTag := []graphModels.TagsWithFrequency{ + { + Frequency: 0, + Tags: graphModels.AnthroveTag{ + Name: "test_tag", + Type: "general", + }, + }, + } + + tag, err := suite.database.GetAllTags(suite.ctx) + + assert.NoError(t, err) + assert.Equal(t, expectedTag, tag) + assert.Len(t, tag, 1) + +} + +func TestCustomerRepoTestSuite(t *testing.T) { + suite.Run(t, new(CustomerRepoTestSuite)) +} From e7cf655362fb56491ee60fb049f4b5432af142f8 Mon Sep 17 00:00:00 2001 From: soxx Date: Thu, 20 Jun 2024 00:13:39 +0200 Subject: [PATCH 037/124] test(postgres): added sources and fixed bugs --- internal/postgres/source.go | 12 +- internal/postgres/source_test.go | 259 +++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 internal/postgres/source_test.go diff --git a/internal/postgres/source.go b/internal/postgres/source.go index 3d2cdca..1b013da 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -2,6 +2,7 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" @@ -11,6 +12,10 @@ import ( // CreateSourceNode creates a pgModels.Source func CreateSourceNode(ctx context.Context, db *gorm.DB, anthroveSource *pgModels.Source) error { + if anthroveSource.Domain == "" { + return fmt.Errorf("anthroveSource domain is required") + } + result := db.WithContext(ctx).Create(anthroveSource) if result.Error != nil { @@ -45,8 +50,11 @@ func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]pgModels.Source, err // GetSourceNodesByURL returns the first source it finds based on the domain func GetSourceNodesByURL(ctx context.Context, db *gorm.DB, domain string) (*pgModels.Source, error) { + var sources pgModels.Source - var sources *pgModels.Source + if domain == "" { + return nil, fmt.Errorf("domain is required") + } result := db.WithContext(ctx).Where("domain = ?", domain).First(&sources) @@ -58,5 +66,5 @@ func GetSourceNodesByURL(ctx context.Context, db *gorm.DB, domain string) (*pgMo "tag_amount": result.RowsAffected, }).Trace("database: get all source nodes") - return sources, nil + return &sources, nil } diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go new file mode 100644 index 0000000..2bde71b --- /dev/null +++ b/internal/postgres/source_test.go @@ -0,0 +1,259 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" + "git.dragse.it/anthrove/otter-space-sdk/test" + "gorm.io/gorm" + "testing" +) + +func TestCreateSourceNode(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validAnthroveSource := &pgModels.Source{ + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + } + + invalidAnthroveSource := &pgModels.Source{ + Domain: "", + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveSource *pgModels.Source + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid anthroveSource", + args: args{ + ctx: ctx, + db: gormDB, + anthroveSource: validAnthroveSource, + }, + wantErr: false, + }, + { + name: "Test 2: inValid anthroveSource", + args: args{ + ctx: ctx, + db: gormDB, + anthroveSource: invalidAnthroveSource, + }, + wantErr: true, + }, + { + name: "Test 3: unique anthroveSource", + args: args{ + ctx: ctx, + db: gormDB, + anthroveSource: validAnthroveSource, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CreateSourceNode(tt.args.ctx, tt.args.db, tt.args.anthroveSource); (err != nil) != tt.wantErr { + t.Errorf("CreateSourceNode() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestGetAllSourceNodes(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + sources := []pgModels.Source{ + { + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + }, + { + DisplayName: "furaffinity", + Domain: "furaffinity.net", + Icon: "icon.furaffinity.net", + }, + { + DisplayName: "fenpaws", + Domain: "fenpa.ws", + Icon: "icon.fenpa.ws", + }, + } + + for _, source := range sources { + err = CreateSourceNode(ctx, gormDB, &source) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + } + tests := []struct { + name string + args args + want []pgModels.Source + wantErr bool + }{ + { + name: "Test 1: Get all entries", + args: args{ + ctx: ctx, + db: gormDB, + }, + want: sources, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllSourceNodes(tt.args.ctx, tt.args.db) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllSourceNodes() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkSourcesNode(got, tt.want) { + t.Errorf("GetAllSourceNodes() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetSourceNodesByURL(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + source := &pgModels.Source{ + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + } + + err = CreateSourceNode(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + domain string + } + tests := []struct { + name string + args args + want *pgModels.Source + wantErr bool + }{ + { + name: "Test 1: Valid URL", + args: args{ + ctx: ctx, + db: gormDB, + domain: "e621.net", + }, + want: source, + wantErr: false, + }, + { + name: "Test 2: Invalid URL", + args: args{ + ctx: ctx, + db: gormDB, + domain: "eeeee.net", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 2: No URL", + args: args{ + ctx: ctx, + db: gormDB, + domain: "", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetSourceNodesByURL(tt.args.ctx, tt.args.db, tt.args.domain) + if (err != nil) != tt.wantErr { + t.Errorf("GetSourceNodesByURL() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkSourceNode(got, tt.want) { + t.Errorf("GetSourceNodesByURL() got = %v, want %v", got, tt.want) + } + }) + } +} + +func checkSourcesNode(got []pgModels.Source, want []pgModels.Source) bool { + for i, source := range want { + if source.DisplayName != got[i].DisplayName { + return false + } + if source.Domain != got[i].Domain { + return false + } + if source.Icon != got[i].Icon { + return false + } + } + + return true + +} + +func checkSourceNode(got *pgModels.Source, want *pgModels.Source) bool { + + if want == nil && got == nil { + return true + } + + if got.Domain != want.Domain { + return false + } + + return true + +} From e6931570c3b98ec2f354b73e0cdd7bc68f07c6a2 Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 19 Jun 2024 22:16:42 +0000 Subject: [PATCH 038/124] chore(postgres): removed dead code --- test/tag_test.go | 104 ----------------------------------------------- 1 file changed, 104 deletions(-) delete mode 100644 test/tag_test.go diff --git a/test/tag_test.go b/test/tag_test.go deleted file mode 100644 index 3c9c4f8..0000000 --- a/test/tag_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package test - -import ( - "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/database" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "log" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" -) - -type CustomerRepoTestSuite struct { - suite.Suite - database database.OtterSpace - pgContainer *PostgresContainer - ctx context.Context -} - -func (suite *CustomerRepoTestSuite) SetupSuite() { - suite.ctx = context.Background() - pgContainer, err := CreatePostgresContainer(suite.ctx) - if err != nil { - log.Fatal(err) - } - suite.pgContainer = pgContainer - - databaseClient := database.NewPostgresqlConnection(true) - containerInspect, _ := suite.pgContainer.Inspect(suite.ctx) - dbPortMap := containerInspect.NetworkSettings.Ports - var dbPortStr string - for _, v := range dbPortMap { - for _, n := range v { - dbPortStr = n.HostPort - } - } - dbPort, err := strconv.Atoi(dbPortStr) - if err != nil { - log.Fatal(err) - } - err = databaseClient.Connect(suite.ctx, "localhost", suite.pgContainer.DatabaseUser, suite.pgContainer.DatabasePassword, suite.pgContainer.DatabaseName, dbPort, "disable", "Europe/Berlin") - if err != nil { - log.Fatal(err) - } - suite.database = databaseClient - -} - -func (suite *CustomerRepoTestSuite) TearDownSuite() { - if err := suite.pgContainer.Terminate(suite.ctx); err != nil { - log.Fatalf("error terminating postgres container: %s", err) - } -} - -func (suite *CustomerRepoTestSuite) TestCreateTagNodeWitRelation() { - t := suite.T() - post := graphModels.AnthrovePost{ - PostID: "1234", - Rating: models.SFW, - } - - tag := &graphModels.AnthroveTag{ - Name: "test_tag", - Type: "general", - } - - err := suite.database.AddPost(suite.ctx, &post) - - if err != nil { - t.Fatal(err) - } - - err = suite.database.AddTagWithRelationToPost(suite.ctx, "1234", tag) - - assert.NoError(t, err) -} - -func (suite *CustomerRepoTestSuite) TestGetTags() { - t := suite.T() - - expectedTag := []graphModels.TagsWithFrequency{ - { - Frequency: 0, - Tags: graphModels.AnthroveTag{ - Name: "test_tag", - Type: "general", - }, - }, - } - - tag, err := suite.database.GetAllTags(suite.ctx) - - assert.NoError(t, err) - assert.Equal(t, expectedTag, tag) - assert.Len(t, tag, 1) - -} - -func TestCustomerRepoTestSuite(t *testing.T) { - suite.Run(t, new(CustomerRepoTestSuite)) -} From 83a5c894384d718c1b10905c4b8eae41b9ae976d Mon Sep 17 00:00:00 2001 From: SoXX Date: Thu, 20 Jun 2024 14:54:06 +0200 Subject: [PATCH 039/124] test(postgres): added tag and fixed bugs Signed-off-by: soxx --- internal/postgres/tag.go | 21 ++++ internal/postgres/tag_test.go | 175 ++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 internal/postgres/tag_test.go diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 02072c2..4249069 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -2,14 +2,35 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) +func CreateTag(ctx context.Context, db *gorm.DB, tag *pgModels.Tag) error { + + resultTag := db.WithContext(ctx).Where(tag).Create(tag) + + if resultTag.Error != nil { + return resultTag.Error + } + + log.WithFields(log.Fields{ + "tag_name": tag.Name, + "tag_type": tag.Type, + }).Trace("database: created tag node") + + return nil +} + func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.AnthrovePostID, tag *pgModels.Tag) error { + if PostID == "" { + return fmt.Errorf("PostID is empty") + } + resultTag := db.WithContext(ctx).Where(tag).FirstOrCreate(tag) if resultTag.Error != nil { diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go new file mode 100644 index 0000000..347754e --- /dev/null +++ b/internal/postgres/tag_test.go @@ -0,0 +1,175 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" + "git.dragse.it/anthrove/otter-space-sdk/test" + "gorm.io/gorm" + "testing" +) + +func TestCreateTagNodeWitRelation(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") + if err != nil { + t.Fatal(err) + } + + tag := &pgModels.Tag{ + Name: "JayTheFerret", + Type: "artist", + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + PostID models.AnthrovePostID + tag *pgModels.Tag + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid PostID and Tag", + args: args{ + ctx: ctx, + db: gormDB, + PostID: "1234", + tag: tag, + }, + wantErr: false, + }, + { + name: "Test 2: Valid PostID and invalid Tag", + args: args{ + ctx: ctx, + db: gormDB, + PostID: "1234", + tag: nil, + }, + wantErr: true, + }, + { + name: "Test 3: Invalid PostID and valid Tag", + args: args{ + ctx: ctx, + db: gormDB, + PostID: "123456", + tag: tag, + }, + wantErr: true, + }, + { + name: "Test 4: No PostID and valid Tag", + args: args{ + ctx: ctx, + db: gormDB, + PostID: "", + tag: tag, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CreateTagNodeWitRelation(tt.args.ctx, tt.args.db, tt.args.PostID, tt.args.tag); (err != nil) != tt.wantErr { + t.Errorf("CreateTagNodeWitRelation() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestGetTags(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + tags := []pgModels.Tag{ + { + Name: "JayTheFerret", + Type: "artist", + }, + { + Name: "anthro", + Type: "general", + }, + { + Name: "soxx", + Type: "character", + }, + } + + for _, tag := range tags { + err = CreateTag(ctx, gormDB, &tag) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + } + tests := []struct { + name string + args args + want []pgModels.Tag + wantErr bool + }{ + { + name: "Test 1: Get Tags", + args: args{ + ctx: ctx, + db: gormDB, + }, + want: tags, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetTags(tt.args.ctx, tt.args.db) + if (err != nil) != tt.wantErr { + t.Errorf("GetTags() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkTag(got, tt.want) { + t.Errorf("GetTags() got = %v, want %v", got, tt.want) + } + }) + } +} + +func checkTag(got []pgModels.Tag, want []pgModels.Tag) bool { + for i, tag := range want { + if tag.Type != got[i].Type { + return false + } + if tag.Name != got[i].Name { + return false + } + } + + return true + +} From 947a77d13fd6b6d1dbbfa6afa4f597c0ee1fd3b8 Mon Sep 17 00:00:00 2001 From: soxx Date: Thu, 20 Jun 2024 15:24:55 +0200 Subject: [PATCH 040/124] test(postgres): added first tests for user and fixed bugs Signed-off-by: soxx --- internal/postgres/user.go | 15 + internal/postgres/user_test.go | 453 ++++++++++++++++++++++++++++++ pkg/models/pgModels/userSource.go | 4 + 3 files changed, 472 insertions(+) create mode 100644 internal/postgres/user_test.go diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 472625a..5181cbe 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -2,6 +2,7 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" @@ -11,6 +12,10 @@ import ( func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { + if anthroveUserID == "" { + return fmt.Errorf("anthroveUserID cannot be empty") + } + user := pgModels.User{ BaseModel: pgModels.BaseModel{ ID: string(anthroveUserID), @@ -29,6 +34,11 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove } func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { + + if anthroveUserID == "" || username == "" || userID == "" { + return fmt.Errorf("anthroveUserID cannot be empty") + } + user := pgModels.User{ BaseModel: pgModels.BaseModel{ ID: string(anthroveUserID), @@ -181,6 +191,11 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID } func GetAnthroveUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { + + if anthroveUserID == "" { + return nil, fmt.Errorf("anthroveUserID cannot be empty") + } + var user pgModels.User var userSources []pgModels.UserSource anthroveUser := &graphModels.AnthroveUser{ diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go new file mode 100644 index 0000000..26f316f --- /dev/null +++ b/internal/postgres/user_test.go @@ -0,0 +1,453 @@ +package postgres + +import ( + "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" + "git.dragse.it/anthrove/otter-space-sdk/test" + "gorm.io/gorm" + "reflect" + "testing" +) + +func TestCreateUser(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CreateUser(tt.args.ctx, tt.args.db, tt.args.anthroveUserID); (err != nil) != tt.wantErr { + t.Errorf("CreateUser() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestCreateUserNodeWithSourceRelation(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + source := &pgModels.Source{ + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + } + err = CreateSourceNode(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + sourceDomain string + userID string + username string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid anthroveUserID, sourceDomain, userID, username", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceDomain: "e621.net", + userID: "e1", + username: "marius", + }, + wantErr: false, + }, + { + name: "Test 2: Invalid anthroveUserID, valid sourceDomain, userID, username", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "2", + sourceDomain: "e621.net", + userID: "e1", + username: "marius", + }, + wantErr: true, + }, + { + name: "Test 3: Empty anthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + sourceDomain: "e621.net", + userID: "e1", + username: "marius", + }, + wantErr: true, + }, + { + name: "Test 4: invalid sourceDomain", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceDomain: "fa.net", + userID: "e1", + username: "marius", + }, + wantErr: true, + }, + { + name: "Test 5: no userID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceDomain: "e621.net", + userID: "", + username: "marius", + }, + wantErr: true, + }, + { + name: "Test 6: no username", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceDomain: "e621.net", + userID: "aa", + username: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CreateUserNodeWithSourceRelation(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceDomain, tt.args.userID, tt.args.username); (err != nil) != tt.wantErr { + t.Errorf("CreateUserNodeWithSourceRelation() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestGetAllAnthroveUserIDs(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + users := []models.AnthroveUserID{"1", "2", "3"} + + for _, user := range users { + err = CreateUser(ctx, gormDB, user) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + } + tests := []struct { + name string + args args + want []models.AnthroveUserID + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + db: gormDB, + }, + want: users, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllAnthroveUserIDs(tt.args.ctx, tt.args.db) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllAnthroveUserIDs() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllAnthroveUserIDs() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetAnthroveUser(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + user := graphModels.AnthroveUser{ + UserID: "1", + } + err = CreateUser(ctx, gormDB, user.UserID) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + } + tests := []struct { + name string + args args + want *graphModels.AnthroveUser + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + }, + want: &user, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "2", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: No AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAnthroveUser(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) + if (err != nil) != tt.wantErr { + t.Errorf("GetAnthroveUser() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAnthroveUser() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetSpecifiedUserSourceLink(t *testing.T) { + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + sourceDisplayName string + } + tests := []struct { + name string + args args + want map[string]graphModels.AnthroveUserRelationship + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetSpecifiedUserSourceLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceDisplayName) + if (err != nil) != tt.wantErr { + t.Errorf("GetSpecifiedUserSourceLink() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetSpecifiedUserSourceLink() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetUserFavoriteNodeWithPagination(t *testing.T) { + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + skip int + limit int + } + tests := []struct { + name string + args args + want *graphModels.FavoriteList + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetUserFavoriteNodeWithPagination(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) + if (err != nil) != tt.wantErr { + t.Errorf("GetUserFavoriteNodeWithPagination() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetUserFavoriteNodeWithPagination() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetUserFavoritesCount(t *testing.T) { + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + } + tests := []struct { + name string + args args + want int64 + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetUserFavoritesCount(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) + if (err != nil) != tt.wantErr { + t.Errorf("GetUserFavoritesCount() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetUserFavoritesCount() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetUserSourceLink(t *testing.T) { + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + } + tests := []struct { + name string + args args + want map[string]graphModels.AnthroveUserRelationship + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetUserSourceLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) + if (err != nil) != tt.wantErr { + t.Errorf("GetUserSourceLink() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetUserSourceLink() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + } + tests := []struct { + name string + args args + want []graphModels.TagsWithFrequency + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetUserTagNodeWitRelationToFavedPosts(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) + if (err != nil) != tt.wantErr { + t.Errorf("GetUserTagNodeWitRelationToFavedPosts() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetUserTagNodeWitRelationToFavedPosts() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/models/pgModels/userSource.go b/pkg/models/pgModels/userSource.go index 7319994..a87494f 100644 --- a/pkg/models/pgModels/userSource.go +++ b/pkg/models/pgModels/userSource.go @@ -6,3 +6,7 @@ type UserSource struct { AccountUsername string AccountID string } + +func (UserSource) TableName() string { + return "UserSource" +} From 84aee5c2dda5d203ebf2eadfd4bf1ceb01d2de14 Mon Sep 17 00:00:00 2001 From: soxx Date: Thu, 20 Jun 2024 22:45:03 +0200 Subject: [PATCH 041/124] test(postgres): finished tests for user and fixed bugs Signed-off-by: soxx --- internal/postgres/user.go | 31 +- internal/postgres/user_test.go | 474 +++++++++++++++++- .../migrations/001_inital_database.sql | 10 +- pkg/models/pgModels/orm.go | 2 +- pkg/models/pgModels/userSource.go | 1 + test/helper.go | 5 +- 6 files changed, 502 insertions(+), 21 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 5181cbe..921af51 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -91,6 +91,10 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthrove } func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (int64, error) { + if anthroveUserID == "" { + return 0, fmt.Errorf("anthroveUserID cannot be empty") + } + var count int64 err := db.WithContext(ctx).Model(&pgModels.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Count(&count).Error if err != nil { @@ -149,10 +153,14 @@ func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.A } func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { + if anthroveUserID == "" || sourceDisplayName == "" { + return nil, fmt.Errorf("anthroveUserID or sourceDisplayName is empty") + } + var userSources []pgModels.UserSource userSourceMap := make(map[string]graphModels.AnthroveUserRelationship) - err := db.WithContext(ctx).Model(&pgModels.UserSource{}).Joins("Source").Where("user_id = ? AND display_name = ?", string(anthroveUserID), sourceDisplayName).Find(&userSources).Error + err := db.WithContext(ctx).Model(&pgModels.UserSource{}).InnerJoins("Source", db.Where("display_name = ?", sourceDisplayName)).Where("user_id = ?", string(anthroveUserID)).First(&userSources).Error if err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, @@ -317,10 +325,13 @@ func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, ant return nil, err } - tagFrequency := make(map[string]int) + tagFrequency := make(map[struct { + name string + typeName string + }]int) for _, userFavorite := range userFavorites { - var postTags []pgModels.Tag - err = db.WithContext(ctx).Model(&pgModels.Post{}).Where("id = ?", userFavorite.PostID).Association("Tags").Find(&postTags) + var post pgModels.Post + err = db.WithContext(ctx).Preload("Tags").First(&post, "id = ?", userFavorite.PostID).Error if err != nil { log.WithFields(log.Fields{ "post_id": userFavorite.PostID, @@ -328,17 +339,21 @@ func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, ant return nil, err } - for _, tag := range postTags { - tagFrequency[tag.Name]++ + for _, tag := range post.Tags { + tagFrequency[struct { + name string + typeName string + }{name: tag.Name, typeName: string(tag.Type)}]++ } } var tagsWithFrequency []graphModels.TagsWithFrequency - for tagName, frequency := range tagFrequency { + for data, frequency := range tagFrequency { tagsWithFrequency = append(tagsWithFrequency, graphModels.TagsWithFrequency{ Frequency: int64(frequency), Tags: graphModels.AnthroveTag{ - Name: tagName, + Name: data.name, + Type: data.typeName, }, }) } diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 26f316f..531e13e 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -2,6 +2,7 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" @@ -310,6 +311,40 @@ func TestGetAnthroveUser(t *testing.T) { } func TestGetSpecifiedUserSourceLink(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + source := &pgModels.Source{ + DisplayName: "e621", + Domain: "e621.net", + } + err = CreateSourceNode(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + expectedResult := make(map[string]graphModels.AnthroveUserRelationship) + expectedResult["e621"] = graphModels.AnthroveUserRelationship{ + UserID: "e1", + Username: "euser", + Source: graphModels.AnthroveSource{ + DisplayName: source.DisplayName, + Domain: source.Domain, + }, + } + + err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", source.Domain, expectedResult["e621"].UserID, expectedResult["e621"].Username) + if err != nil { + t.Fatal(err) + } + // Test + type args struct { ctx context.Context db *gorm.DB @@ -322,7 +357,72 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { want map[string]graphModels.AnthroveUserRelationship wantErr bool }{ - // TODO: Add test cases. + { + name: "Test 1: Valid AnthroveUserID and SourceDisplayName", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceDisplayName: "e621", + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveUserID and valid SourceDisplayName", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "22", + sourceDisplayName: "e621", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: Valid AnthroveUserID and invalid SourceDisplayName", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceDisplayName: "fa", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 4: No AnthroveUserID and Valid SourceDisplayName", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + sourceDisplayName: "e621", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 5: Valid AnthroveUserID and No SourceDisplayName", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceDisplayName: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 6: No AnthroveUserID and No SourceDisplayName", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + sourceDisplayName: "", + }, + want: nil, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -332,13 +432,115 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetSpecifiedUserSourceLink() got = %v, want %v", got, tt.want) + t.Errorf("GetSpecifiedUserSourceLink() got = %v, expectedResult %v", got, tt.want) } }) } } func TestGetUserFavoriteNodeWithPagination(t *testing.T) { + // Setup trow away containert + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + expectedResultPostsGraph := []graphModels.FavoritePost{ + { + AnthrovePost: graphModels.AnthrovePost{ + PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post1")), + Rating: "safe", + }, + }, + { + AnthrovePost: graphModels.AnthrovePost{ + PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post2")), + Rating: "safe", + }, + }, + { + AnthrovePost: graphModels.AnthrovePost{ + PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post3")), + Rating: "explicit", + }, + }, + { + AnthrovePost: graphModels.AnthrovePost{ + PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post4")), + Rating: "explicit", + }, + }, + { + AnthrovePost: graphModels.AnthrovePost{ + PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post5")), + Rating: "questionable", + }, + }, + { + AnthrovePost: graphModels.AnthrovePost{ + PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post6")), + Rating: "safe", + }, + }, + } + expectedResult := &graphModels.FavoriteList{ + Posts: expectedResultPostsGraph, + } + expectedResult2 := &graphModels.FavoriteList{ + Posts: expectedResultPostsGraph[2:], + } + expectedResult3 := &graphModels.FavoriteList{ + Posts: expectedResultPostsGraph[:3], + } + + err = CreateUser(ctx, gormDB, "1") + if err != nil { + t.Fatal(err) + } + + expectedResultPostsPg := []pgModels.Post{ + { + BaseModel: pgModels.BaseModel{ID: "Post1"}, + Rating: "safe", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post2"}, + Rating: "safe", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post3"}, + Rating: "explicit", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post4"}, + Rating: "explicit", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post5"}, + Rating: "questionable", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post6"}, + Rating: "safe", + }, + } + + for _, expectedResultPost := range expectedResultPostsPg { + err = CreateAnthrovePostNode(ctx, gormDB, models.AnthrovePostID(expectedResultPost.ID), expectedResultPost.Rating) + if err != nil { + t.Fatal(err) + } + err = EstablishUserToPostLink(ctx, gormDB, "1", models.AnthrovePostID(expectedResultPost.ID)) + if err != nil { + t.Fatal(err) + } + } + + // Test type args struct { ctx context.Context db *gorm.DB @@ -352,7 +554,42 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { want *graphModels.FavoriteList wantErr bool }{ - // TODO: Add test cases. + { + name: "Test 1: Valid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + skip: 0, + limit: 2000, + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: Skip first two", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + skip: 2, + limit: 2000, + }, + want: expectedResult2, + wantErr: false, + }, + { + name: "Test 3: Limit of 3", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + skip: 0, + limit: 3, + }, + want: expectedResult3, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -369,6 +606,60 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { } func TestGetUserFavoritesCount(t *testing.T) { + // Setup trow away containert + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + err = CreateUser(ctx, gormDB, "1") + if err != nil { + t.Fatal(err) + } + + expectedResultPostsPg := []pgModels.Post{ + { + BaseModel: pgModels.BaseModel{ID: "Post1"}, + Rating: "safe", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post2"}, + Rating: "safe", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post3"}, + Rating: "explicit", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post4"}, + Rating: "explicit", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post5"}, + Rating: "questionable", + }, + { + BaseModel: pgModels.BaseModel{ID: "Post6"}, + Rating: "safe", + }, + } + + for _, expectedResultPost := range expectedResultPostsPg { + err = CreateAnthrovePostNode(ctx, gormDB, models.AnthrovePostID(expectedResultPost.ID), expectedResultPost.Rating) + if err != nil { + t.Fatal(err) + } + err = EstablishUserToPostLink(ctx, gormDB, "1", models.AnthrovePostID(expectedResultPost.ID)) + if err != nil { + t.Fatal(err) + } + } + + // Test type args struct { ctx context.Context db *gorm.DB @@ -380,7 +671,36 @@ func TestGetUserFavoritesCount(t *testing.T) { want int64 wantErr bool }{ - // TODO: Add test cases. + { + name: "Test 1: Valid anthroveUserID and 6 favorite posts", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + }, + want: 6, + wantErr: false, + }, + { + name: "Test 2: Invalid anthroveUserID and 6 favorite posts", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "2", + }, + want: 0, + wantErr: false, + }, + { + name: "Test 3: no anthroveUserID and 6 favorite posts", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + }, + want: 0, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -397,6 +717,61 @@ func TestGetUserFavoritesCount(t *testing.T) { } func TestGetUserSourceLink(t *testing.T) { + // Setup trow away containert + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + esource := &pgModels.Source{ + DisplayName: "e621", + Domain: "e621.net", + } + err = CreateSourceNode(ctx, gormDB, esource) + if err != nil { + t.Fatal(err) + } + + fasource := &pgModels.Source{ + DisplayName: "fa", + Domain: "fa.net", + } + err = CreateSourceNode(ctx, gormDB, fasource) + if err != nil { + t.Fatal(err) + } + + expectedResult := make(map[string]graphModels.AnthroveUserRelationship) + expectedResult["e621"] = graphModels.AnthroveUserRelationship{ + UserID: "e1", + Username: "euser", + Source: graphModels.AnthroveSource{ + DisplayName: esource.DisplayName, + Domain: esource.Domain, + }, + } + expectedResult["fa"] = graphModels.AnthroveUserRelationship{ + UserID: "fa1", + Username: "fauser", + Source: graphModels.AnthroveSource{ + DisplayName: fasource.DisplayName, + Domain: fasource.Domain, + }, + } + + err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", esource.Domain, expectedResult["e621"].UserID, expectedResult["e621"].Username) + if err != nil { + t.Fatal(err) + } + err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", fasource.Domain, expectedResult["fa"].UserID, expectedResult["fa"].Username) + if err != nil { + t.Fatal(err) + } + // Test type args struct { ctx context.Context db *gorm.DB @@ -408,7 +783,16 @@ func TestGetUserSourceLink(t *testing.T) { want map[string]graphModels.AnthroveUserRelationship wantErr bool }{ - // TODO: Add test cases. + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + }, + want: expectedResult, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -425,6 +809,75 @@ func TestGetUserSourceLink(t *testing.T) { } func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { + // Setup trow away containert + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + err = CreateUser(ctx, gormDB, "1") + if err != nil { + t.Fatal(err) + } + + posts := []pgModels.Post{ + {BaseModel: pgModels.BaseModel{ID: fmt.Sprintf("%-25s", "Post1")}, Rating: "safe"}, + {BaseModel: pgModels.BaseModel{ID: fmt.Sprintf("%-25s", "Post2")}, Rating: "safe"}, + {BaseModel: pgModels.BaseModel{ID: fmt.Sprintf("%-25s", "Post3")}, Rating: "explicit"}, + } + + for _, post := range posts { + err = CreateAnthrovePostNode(ctx, gormDB, models.AnthrovePostID(post.ID), post.Rating) + if err != nil { + t.Fatal(err) + } + err = EstablishUserToPostLink(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) + if err != nil { + t.Fatal(err) + } + } + + tags := []pgModels.Tag{ + {Name: "JayTheFerret", Type: "artist"}, + {Name: "Ferret", Type: "species"}, + {Name: "Jay", Type: "character"}, + } + + for i, tag := range tags { + err = CreateTagNodeWitRelation(ctx, gormDB, models.AnthrovePostID(posts[i].ID), &tag) + if err != nil { + t.Fatal(err) + } + } + + expectedResult := []graphModels.TagsWithFrequency{ + { + Frequency: 1, + Tags: graphModels.AnthroveTag{ + Name: tags[0].Name, + Type: string(tags[0].Type), + }, + }, + { + Frequency: 1, + Tags: graphModels.AnthroveTag{ + Name: tags[1].Name, + Type: string(tags[1].Type), + }, + }, + { + Frequency: 1, + Tags: graphModels.AnthroveTag{ + Name: tags[2].Name, + Type: string(tags[2].Type), + }, + }, + } + + // Test type args struct { ctx context.Context db *gorm.DB @@ -436,7 +889,16 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { want []graphModels.TagsWithFrequency wantErr bool }{ - // TODO: Add test cases. + { + name: "", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + }, + want: expectedResult, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index c78c150..7e16f9b 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -17,7 +17,7 @@ CREATE TYPE TagType AS ENUM ( CREATE TABLE "Post" ( - id CHAR(25) UNIQUE PRIMARY KEY, + id CHAR(25) PRIMARY KEY, rating Rating, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, @@ -26,7 +26,7 @@ CREATE TABLE "Post" CREATE TABLE "Source" ( - id CHAR(25) UNIQUE PRIMARY KEY, + id CHAR(25) PRIMARY KEY, display_name TEXT NULL, icon TEXT NULL, domain TEXT NOT NULL UNIQUE, @@ -46,7 +46,7 @@ CREATE TABLE "Tag" CREATE TABLE "User" ( - id TEXT UNIQUE PRIMARY KEY, + id TEXT PRIMARY KEY, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, deleted_at TIMESTAMP NULL @@ -80,8 +80,8 @@ CREATE TABLE "TagGroup" CREATE TABLE "UserFavorites" ( - user_id TEXT UNIQUE REFERENCES "User" (id), - post_id TEXT UNIQUE REFERENCES "Post" (id), + user_id TEXT REFERENCES "User" (id), + post_id TEXT REFERENCES "Post" (id), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, post_id) ); diff --git a/pkg/models/pgModels/orm.go b/pkg/models/pgModels/orm.go index c637fa5..4fd79bb 100644 --- a/pkg/models/pgModels/orm.go +++ b/pkg/models/pgModels/orm.go @@ -16,7 +16,7 @@ type BaseModel struct { func (base *BaseModel) BeforeCreate(db *gorm.DB) error { if base.ID == "" { - id, err := gonanoid.New() + id, err := gonanoid.New(25) if err != nil { return err } diff --git a/pkg/models/pgModels/userSource.go b/pkg/models/pgModels/userSource.go index a87494f..04371fe 100644 --- a/pkg/models/pgModels/userSource.go +++ b/pkg/models/pgModels/userSource.go @@ -2,6 +2,7 @@ package pgModels type UserSource struct { UserID string `gorm:"primaryKey"` + Source Source `gorm:"foreignKey:ID;references:SourceID"` SourceID string `gorm:"primaryKey"` AccountUsername string AccountID string diff --git a/test/helper.go b/test/helper.go index 4f50991..501ac62 100644 --- a/test/helper.go +++ b/test/helper.go @@ -7,6 +7,7 @@ import ( postgrescontainer "github.com/testcontainers/testcontainers-go/modules/postgres" "gorm.io/driver/postgres" "gorm.io/gorm" + "gorm.io/gorm/logger" "time" "github.com/testcontainers/testcontainers-go" @@ -73,5 +74,7 @@ func migrateDatabase(connectionString string) error { } func getGormDB(connectionString string) (*gorm.DB, error) { - return gorm.Open(postgres.Open(connectionString), &gorm.Config{}) + return gorm.Open(postgres.Open(connectionString), &gorm.Config{ + Logger: logger.Default.LogMode(logger.Info), + }) } From 40ce69567a3dead4f7d84e2acadf6a03c2972fe7 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 14:16:03 +0200 Subject: [PATCH 042/124] dix(postgres): wrong parameters Signed-off-by: soxx --- pkg/database/postgres.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index c283bea..14c4003 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -54,7 +54,7 @@ func (p *postgresqlConnection) Connect(_ context.Context, endpoint string, usern } func (p *postgresqlConnection) AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { - return postgres.CreateUserNodeWithSourceRelation(ctx, p.db, anthroveUserID, userID, sourceDomain, userID) + return postgres.CreateUserNodeWithSourceRelation(ctx, p.db, anthroveUserID, sourceDomain, userID, userID) } func (p *postgresqlConnection) AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error { From d4bec1d8c7c35f66a059e8b4e01ab9807c8965d3 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 14:36:38 +0200 Subject: [PATCH 043/124] fix(postgres): removed unneeded code that breaks the thing Signed-off-by: soxx --- internal/postgres/relationships.go | 5 ----- internal/postgres/relationships_test.go | 6 +++--- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index 7ee9fd7..b9919a1 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -2,7 +2,6 @@ package postgres import ( "context" - "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" @@ -65,10 +64,6 @@ func CheckUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID models exists := count > 0 - if !exists { - return false, fmt.Errorf("no post link exists") - } - log.WithFields(log.Fields{ "relationship_exists": exists, "relationship_anthrove_user_id": anthroveUserID, diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go index d5033d9..29b29ba 100644 --- a/internal/postgres/relationships_test.go +++ b/internal/postgres/relationships_test.go @@ -240,7 +240,7 @@ func TestCheckUserToPostLink(t *testing.T) { anthrovePostID: "123456", }, want: false, - wantErr: true, + wantErr: false, }, { name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", @@ -251,7 +251,7 @@ func TestCheckUserToPostLink(t *testing.T) { anthrovePostID: "1234", }, want: false, - wantErr: true, + wantErr: false, }, { name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", @@ -262,7 +262,7 @@ func TestCheckUserToPostLink(t *testing.T) { anthrovePostID: "123456", }, want: false, - wantErr: true, + wantErr: false, }, } for _, tt := range tests { From 795bcbdac3c335e274dbc431e6ba2d3a078b70de Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 14:56:11 +0200 Subject: [PATCH 044/124] feat(postgres): added new each function Signed-off-by: soxx --- internal/postgres/post.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 1cd4472..1706b44 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -39,7 +39,14 @@ func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, } func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (bool, error) { - return executeCheckQuery(ctx, db, "url = ?", sourceURL) + var size int64 + err := db.WithContext(ctx).Model(&pgModels.PostReference{}).Where("url = ?", sourceURL).Count(&size).Error + + if err != nil { + return false, err + } + + return size > 0, nil } func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, db *gorm.DB, sourceID string) (bool, error) { From 2515fc50811328f43cf9cd21a4ac831d320f9562 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 15:08:42 +0200 Subject: [PATCH 045/124] fix(postgres): check if source exists before creating Signed-off-by: soxx --- internal/postgres/source.go | 2 +- internal/postgres/source_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/postgres/source.go b/internal/postgres/source.go index 1b013da..0e60a5e 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -16,7 +16,7 @@ func CreateSourceNode(ctx context.Context, db *gorm.DB, anthroveSource *pgModels return fmt.Errorf("anthroveSource domain is required") } - result := db.WithContext(ctx).Create(anthroveSource) + result := db.WithContext(ctx).Where(pgModels.Source{Domain: anthroveSource.Domain}).FirstOrCreate(anthroveSource) if result.Error != nil { return result.Error diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go index 2bde71b..d0514c2 100644 --- a/internal/postgres/source_test.go +++ b/internal/postgres/source_test.go @@ -65,7 +65,7 @@ func TestCreateSourceNode(t *testing.T) { db: gormDB, anthroveSource: validAnthroveSource, }, - wantErr: true, + wantErr: false, }, } for _, tt := range tests { @@ -249,7 +249,7 @@ func checkSourceNode(got *pgModels.Source, want *pgModels.Source) bool { if want == nil && got == nil { return true } - + if got.Domain != want.Domain { return false } From 4690ce135d7470c660dfe3c464ba8cc57279babd Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 15:15:20 +0200 Subject: [PATCH 046/124] fix(postgres): added url to SourceLink Signed-off-by: soxx --- internal/postgres/relationships.go | 4 +++- pkg/database/postgres.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index b9919a1..a109fdb 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -3,12 +3,13 @@ package postgres import ( "context" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) -func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string) error { +func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { var source pgModels.Source var err error @@ -22,6 +23,7 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrov err = db.WithContext(ctx).Create(pgModels.PostReference{ PostID: string(anthrovePostID), SourceID: source.ID, + URL: anthrovePostRelationship.Url, }).Error if err != nil { diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 14c4003..dbba6f5 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -71,7 +71,7 @@ func (p *postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, ant } func (p *postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { - return postgres.EstablishAnthrovePostToSourceLink(ctx, p.db, anthrovePostID, anthroveSourceDomain) + return postgres.EstablishAnthrovePostToSourceLink(ctx, p.db, anthrovePostID, anthroveSourceDomain, anthrovePostRelationship) } func (p *postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { From e09d39dd02dc568e5510030e18f006ce7d62b954 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 15:18:40 +0200 Subject: [PATCH 047/124] feat(postgres): added copyright as enum Signed-off-by: soxx --- pkg/database/migrations/001_inital_database.sql | 3 ++- pkg/models/const.go | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index 7e16f9b..5c669b6 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -12,7 +12,8 @@ CREATE TYPE TagType AS ENUM ( 'artist', 'lore', 'meta', - 'invalid' + 'invalid', + 'copyright' ); CREATE TABLE "Post" diff --git a/pkg/models/const.go b/pkg/models/const.go index 0b7d944..a9c3cf6 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -20,6 +20,7 @@ const ( Lore TagType = "lore" Meta TagType = "meta" Invalid TagType = "invalid" + Copyright TagType = "copyright" ) func (r *Rating) Convert(e621Rating string) { From 8a2803276a3345f039d8afd87253fabef294fd04 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 15:25:22 +0200 Subject: [PATCH 048/124] fix(migration):add url to primary key Signed-off-by: soxx --- pkg/database/migrations/001_inital_database.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index 5c669b6..a8749bf 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -62,7 +62,7 @@ CREATE TABLE "PostReference" preview_file_url TEXT, sample_file_url TEXT, source_post_id TEXT, - PRIMARY KEY (post_id, source_id) + PRIMARY KEY (post_id, source_id, url) ); CREATE TABLE "TagAlias" From f5360d2757c247a863bc63866dc31c637a65ddb1 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 15:52:59 +0200 Subject: [PATCH 049/124] fix(migration):remove unique key for url Signed-off-by: soxx --- pkg/database/migrations/001_inital_database.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index a8749bf..70ae07a 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -57,7 +57,7 @@ CREATE TABLE "PostReference" ( post_id TEXT REFERENCES "Post" (id), source_id TEXT REFERENCES "Source" (id), - url TEXT NOT NULL UNIQUE, + url TEXT NOT NULL, full_file_url TEXT, preview_file_url TEXT, sample_file_url TEXT, From aea99da4847eb1f1aa21a073bea4f536b2fbe64f Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 17:50:31 +0200 Subject: [PATCH 050/124] fix(postgres): fix creating issue Signed-off-by: soxx --- internal/postgres/user.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 921af51..10b343c 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -70,7 +70,7 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthrove AccountID: userID, } - if err := db.WithContext(ctx).Create(&userSource).Error; err != nil { + if err := db.WithContext(ctx).FirstOrCreate(&userSource).Error; err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, "source_domain": sourceDomain, From b86c6671567e8d421ff9587702341ee0b933662b Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 22:54:47 +0200 Subject: [PATCH 051/124] fix(postgres): CheckIfAnthrovePostNodeExistsBySourceURL now working as intended Signed-off-by: soxx --- internal/postgres/post.go | 23 ++++++++++++++++++----- pkg/database/postgres.go | 3 +-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 1706b44..cf7a58c 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -2,8 +2,10 @@ package postgres import ( "context" + "errors" "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -38,15 +40,26 @@ func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, return executeCheckQuery(ctx, db, "id = ?", string(anthrovePostID)) } -func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (bool, error) { - var size int64 - err := db.WithContext(ctx).Model(&pgModels.PostReference{}).Where("url = ?", sourceURL).Count(&size).Error +func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*graphModels.AnthrovePost, bool, error) { + var post pgModels.Post + err := db.WithContext(ctx).Model(&pgModels.Post{}).InnerJoins("References", db.Where("url = ?", sourceURL)).First(&post).Error if err != nil { - return false, err + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, false, nil + } + return nil, false, err } - return size > 0, nil + pgPost := &graphModels.AnthrovePost{ + PostID: models.AnthrovePostID(post.ID), + Rating: post.Rating, + } + + //TODO Now test it! :D + // Naaa + // D: + return pgPost, true, nil } func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, db *gorm.DB, sourceID string) (bool, error) { diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index dbba6f5..aec5911 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -89,8 +89,7 @@ func (p *postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Conte // CheckPostNodeExistsBySourceURL NOT WORKING! TODO! func (p *postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { - var post graphModels.AnthrovePost - exists, err := postgres.CheckIfAnthrovePostNodeExistsBySourceURL(ctx, p.db, sourceUrl) + post, exists, err := postgres.CheckIfAnthrovePostNodeExistsBySourceURL(ctx, p.db, sourceUrl) return &post, exists, err } From 5e501b20036f533c5ffcadfff1c1f0e8d0f6dde8 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 22:57:05 +0200 Subject: [PATCH 052/124] fix(postgres): ** whyy Signed-off-by: soxx --- internal/postgres/post.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index cf7a58c..3fc9ec1 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -40,7 +40,7 @@ func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, return executeCheckQuery(ctx, db, "id = ?", string(anthrovePostID)) } -func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*graphModels.AnthrovePost, bool, error) { +func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (graphModels.AnthrovePost, bool, error) { var post pgModels.Post err := db.WithContext(ctx).Model(&pgModels.Post{}).InnerJoins("References", db.Where("url = ?", sourceURL)).First(&post).Error @@ -51,7 +51,7 @@ func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, return nil, false, err } - pgPost := &graphModels.AnthrovePost{ + pgPost := graphModels.AnthrovePost{ PostID: models.AnthrovePostID(post.ID), Rating: post.Rating, } From 0b7b6beccdccda09ebebc93b3c5d016ce3123225 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 22:58:52 +0200 Subject: [PATCH 053/124] fix(postgres): Update CheckIfAnthrovePostNodeExistsBySourceURL to return pointer instead of value Signed-off-by: soxx --- internal/postgres/post.go | 4 ++-- pkg/database/postgres.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 3fc9ec1..d8158d9 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -40,7 +40,7 @@ func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, return executeCheckQuery(ctx, db, "id = ?", string(anthrovePostID)) } -func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (graphModels.AnthrovePost, bool, error) { +func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*graphModels.AnthrovePost, bool, error) { var post pgModels.Post err := db.WithContext(ctx).Model(&pgModels.Post{}).InnerJoins("References", db.Where("url = ?", sourceURL)).First(&post).Error @@ -59,7 +59,7 @@ func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, //TODO Now test it! :D // Naaa // D: - return pgPost, true, nil + return &pgPost, true, nil } func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, db *gorm.DB, sourceID string) (bool, error) { diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index aec5911..62a4d2c 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -90,7 +90,7 @@ func (p *postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Conte // CheckPostNodeExistsBySourceURL NOT WORKING! TODO! func (p *postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { post, exists, err := postgres.CheckIfAnthrovePostNodeExistsBySourceURL(ctx, p.db, sourceUrl) - return &post, exists, err + return post, exists, err } // CheckPostNodeExistsBySourceID NOT WORKING! TODO! From c359b4636ef13939bff7e710bd18663fa278210c Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 23:18:33 +0200 Subject: [PATCH 054/124] fix(postgres): prefilled posts with empty Signed-off-by: soxx --- internal/postgres/post.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index d8158d9..c5983dc 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -41,7 +41,7 @@ func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, } func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*graphModels.AnthrovePost, bool, error) { - var post pgModels.Post + post := pgModels.Post{} err := db.WithContext(ctx).Model(&pgModels.Post{}).InnerJoins("References", db.Where("url = ?", sourceURL)).First(&post).Error if err != nil { From c07fd69f4f206c21a9e71a3c1e2577d004c56bfa Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 23:25:55 +0200 Subject: [PATCH 055/124] fix(postgres): CheckIfAnthrovePostNodeExistsBySourceURL function to use PostReference model Signed-off-by: soxx --- internal/postgres/post.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index c5983dc..3ed43a5 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -41,8 +41,8 @@ func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, } func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*graphModels.AnthrovePost, bool, error) { - post := pgModels.Post{} - err := db.WithContext(ctx).Model(&pgModels.Post{}).InnerJoins("References", db.Where("url = ?", sourceURL)).First(&post).Error + postRef := pgModels.PostReference{} + err := db.WithContext(ctx).Model(&pgModels.PostReference{}).Where("url = ?", sourceURL).First(&postRef).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -51,6 +51,13 @@ func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, return nil, false, err } + var post pgModels.Post + err = db.WithContext(ctx).First(&post, "id = ?", postRef.PostID).Error + + if err != nil { + return nil, false, err + } + pgPost := graphModels.AnthrovePost{ PostID: models.AnthrovePostID(post.ID), Rating: post.Rating, From 3c17c6043972501546d0a0c0281958db42ac1ac9 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 23:35:41 +0200 Subject: [PATCH 056/124] fix(postgres): Update postgres.go to use silent logger for GORM configuration Signed-off-by: soxx --- pkg/database/postgres.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 62a4d2c..ab22d85 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -14,6 +14,7 @@ import ( log "github.com/sirupsen/logrus" gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" + logger2 "gorm.io/gorm/logger" ) //go:embed migrations/*.sql @@ -42,7 +43,9 @@ func (p *postgresqlConnection) Connect(_ context.Context, endpoint string, usern log.Infof("OtterSpace: migration compleate") - db, err := gorm.Open(gormPostgres.Open(dsn), &gorm.Config{}) + db, err := gorm.Open(gormPostgres.Open(dsn), &gorm.Config{ + Logger: logger2.Default.LogMode(logger2.Silent), + }) p.db = db if err != nil { return err From 536f7c044327a8f1432c1c1ec7a870e063c8a9f1 Mon Sep 17 00:00:00 2001 From: soxx Date: Fri, 21 Jun 2024 23:48:18 +0200 Subject: [PATCH 057/124] fix(postgres): Update database logger in postgres.go to include slow queries and error handling Signed-off-by: soxx --- pkg/database/postgres.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index ab22d85..ff4eb16 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -15,6 +15,9 @@ import ( gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" logger2 "gorm.io/gorm/logger" + log2 "log" + "os" + "time" ) //go:embed migrations/*.sql @@ -43,8 +46,15 @@ func (p *postgresqlConnection) Connect(_ context.Context, endpoint string, usern log.Infof("OtterSpace: migration compleate") + dbLogger := logger2.New(log2.New(os.Stdout, "\r\n", log2.LstdFlags), logger2.Config{ + SlowThreshold: 200 * time.Millisecond, + LogLevel: logger2.Warn, + IgnoreRecordNotFoundError: true, + Colorful: true, + }) + db, err := gorm.Open(gormPostgres.Open(dsn), &gorm.Config{ - Logger: logger2.Default.LogMode(logger2.Silent), + Logger: dbLogger, }) p.db = db if err != nil { From 58dcf94d492739221d1e08eee80172756a51d21f Mon Sep 17 00:00:00 2001 From: soxx Date: Sat, 22 Jun 2024 22:06:36 +0200 Subject: [PATCH 058/124] refactor(postgres): removed old graph related code Signed-off-by: soxx --- internal/graph/logger.go | 46 -- internal/graph/post.go | 116 ----- internal/graph/relationships.go | 100 ---- internal/graph/source.go | 113 ----- internal/graph/tag.go | 84 ---- internal/graph/user.go | 454 ------------------ internal/postgres/post.go | 13 +- internal/postgres/relationships.go | 9 +- internal/postgres/relationships_test.go | 3 +- internal/postgres/source.go | 14 +- internal/postgres/source_test.go | 20 +- internal/postgres/tag.go | 13 +- internal/postgres/tag_test.go | 11 +- internal/postgres/user.go | 57 ++- internal/postgres/user_test.go | 83 ++-- internal/utils/modelConvert.go | 60 --- pkg/database/database.go | 58 +-- pkg/database/graph.go | 123 ----- .../migrations/001_inital_database.sql | 8 +- pkg/models/README.md | 84 ---- pkg/models/{pgModels => }/orm.go | 2 +- pkg/models/pgModels/userSource.go | 13 - pkg/models/{pgModels => }/post.go | 8 +- pkg/models/{pgModels => }/postReference.go | 2 +- pkg/models/{pgModels => }/source.go | 2 +- pkg/models/{pgModels => }/tag.go | 19 +- pkg/models/{pgModels => }/user.go | 2 +- pkg/models/{pgModels => }/userFavorite.go | 6 +- pkg/models/userSource.go | 14 + 29 files changed, 164 insertions(+), 1373 deletions(-) delete mode 100644 internal/graph/logger.go delete mode 100644 internal/graph/post.go delete mode 100644 internal/graph/relationships.go delete mode 100644 internal/graph/source.go delete mode 100644 internal/graph/tag.go delete mode 100644 internal/graph/user.go delete mode 100644 internal/utils/modelConvert.go delete mode 100644 pkg/database/graph.go delete mode 100644 pkg/models/README.md rename pkg/models/{pgModels => }/orm.go (95%) delete mode 100644 pkg/models/pgModels/userSource.go rename pkg/models/{pgModels => }/post.go (65%) rename pkg/models/{pgModels => }/postReference.go (95%) rename pkg/models/{pgModels => }/source.go (95%) rename pkg/models/{pgModels => }/tag.go (53%) rename pkg/models/{pgModels => }/user.go (92%) rename pkg/models/{pgModels => }/userFavorite.go (69%) create mode 100644 pkg/models/userSource.go diff --git a/internal/graph/logger.go b/internal/graph/logger.go deleted file mode 100644 index 914db3a..0000000 --- a/internal/graph/logger.go +++ /dev/null @@ -1,46 +0,0 @@ -package graph - -import ( - "fmt" - - neo4jLog "github.com/neo4j/neo4j-go-driver/v5/neo4j/log" - log "github.com/sirupsen/logrus" -) - -type graphLogger struct { - graphDebug bool -} - -func NewGraphLogger(graphDebug bool) neo4jLog.Logger { - return &graphLogger{graphDebug: graphDebug} -} - -func (n graphLogger) Error(name string, id string, err error) { - log.WithFields(log.Fields{ - "name": name, - "id": id, - }).Errorf("database: %s", err) -} - -func (n graphLogger) Warnf(name string, id string, msg string, args ...any) { - log.WithFields(log.Fields{ - "name": name, - "id": id, - }).Warnf("database: %v", fmt.Sprintf(msg, args...)) -} - -func (n graphLogger) Infof(name string, id string, msg string, args ...any) { - log.WithFields(log.Fields{ - "name": name, - "id": id, - }).Infof("database: %v", fmt.Sprintf(msg, args...)) -} - -func (n graphLogger) Debugf(name string, id string, msg string, args ...any) { - if n.graphDebug { - log.WithFields(log.Fields{ - "name": name, - "id": id, - }).Debugf("database: %v", fmt.Sprintf(msg, args...)) - } -} diff --git a/internal/graph/post.go b/internal/graph/post.go deleted file mode 100644 index d263928..0000000 --- a/internal/graph/post.go +++ /dev/null @@ -1,116 +0,0 @@ -package graph - -import ( - "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "github.com/neo4j/neo4j-go-driver/v5/neo4j" - log "github.com/sirupsen/logrus" -) - -func CreateAnthrovePostNode(ctx context.Context, driver neo4j.DriverWithContext, anthrovePost *graphModels.AnthrovePost) error { - query := ` - CREATE (newPostNode:AnthrovePost {post_id: $anthrove_post_id, rating: $anthrove_rating}) - ` - - params := map[string]any{ - "anthrove_post_id": anthrovePost.PostID, - "anthrove_rating": anthrovePost.Rating, - } - - _, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return err - } - - log.WithFields(log.Fields{ - "anthrove_post_id": anthrovePost.PostID, - "anthrove_post_rating": anthrovePost.Rating, - }).Trace("database: created anthrove post") - - return nil -} - -func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, driver neo4j.DriverWithContext, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { - query := ` - OPTIONAL MATCH (postNode:AnthrovePost {post_id: $anthrove_post_id}) - RETURN postNode.post_id AS AnthrovePostID - ` - - params := map[string]any{ - "anthrove_post_id": anthrovePost.PostID, - } - - anthrovePost, exists, err := executeCheckQuery(ctx, driver, query, params) - if err != nil { - return nil, false, err - } - - return anthrovePost, exists, nil -} - -func CheckIfAnthrovePostNodeExistsBySourceURl(ctx context.Context, driver neo4j.DriverWithContext, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { - query := ` - OPTIONAL MATCH (postNode:AnthrovePost)<-[:REFERENCE {url: $source_url}]-() - RETURN postNode.post_id AS AnthrovePostID - ` - - params := map[string]any{ - "source_url": sourceUrl, - } - anthrovePost, exists, err := executeCheckQuery(ctx, driver, query, params) - if err != nil { - return nil, false, err - } - - return anthrovePost, exists, nil -} - -func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, driver neo4j.DriverWithContext, sourcePostID string) (*graphModels.AnthrovePost, bool, error) { - query := ` - OPTIONAL MATCH (postNode:AnthrovePost)<-[:REFERENCE {source_post_id: $source_post_id}]-() - RETURN postNode.post_id AS AnthrovePostID - ` - - params := map[string]any{ - "source_post_id": sourcePostID, - } - - anthrovePost, exists, err := executeCheckQuery(ctx, driver, query, params) - if err != nil { - return nil, false, err - } - - return anthrovePost, exists, nil -} - -func executeCheckQuery(ctx context.Context, driver neo4j.DriverWithContext, query string, params map[string]any) (*graphModels.AnthrovePost, bool, error) { - - var anthrovePost graphModels.AnthrovePost - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return &anthrovePost, false, err - } - - record := result.Records - - anthrovePostID, isNil, err := neo4j.GetRecordValue[string](record[0], "AnthrovePostID") - exists := !isNil - if err != nil { - return &anthrovePost, exists, err - } - - anthrovePost.PostID = models.AnthrovePostID(anthrovePostID) - - log.WithFields(log.Fields{ - "anthrove_post_id": anthrovePost.PostID, - "anthrove_post_exists": exists, - }).Trace("database: checked if post exists") - - if !exists { - return nil, exists, nil - } - - return &anthrovePost, exists, nil -} diff --git a/internal/graph/relationships.go b/internal/graph/relationships.go deleted file mode 100644 index d9ea521..0000000 --- a/internal/graph/relationships.go +++ /dev/null @@ -1,100 +0,0 @@ -package graph - -import ( - "context" - "fmt" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "github.com/neo4j/neo4j-go-driver/v5/neo4j" - log "github.com/sirupsen/logrus" -) - -func EstablishAnthrovePostToSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { - query := ` - MATCH (sourceNode:Source {domain: $source_url}) - MATCH (postNode:AnthrovePost {post_id: $anthrove_post_id}) - MERGE (sourceNode)-[:REFERENCE {url: $source_post_url, source_post_id: $source_post_id}]->(postNode) - ` - - params := map[string]any{ - "source_url": anthroveSourceDomain, - "anthrove_post_id": anthrovePostID, - "source_post_url": anthrovePostRelationship.Url, - "source_post_id": anthrovePostRelationship.PostID, - } - - _, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return err - } - - log.WithFields(log.Fields{ - "source_url": anthroveSourceDomain, - "anthrove_post_id": anthrovePostID, - "source_post_url": anthrovePostRelationship.Url, - "source_post_id": anthrovePostRelationship.PostID, - }).Trace("database: creating anthrove post to source link") - - return nil -} - -func EstablishUserToPostLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { - - query := ` - MATCH (user:User {user_id: $anthrove_user_id}) - MATCH (anthrovePost:AnthrovePost {post_id: $anthrove_post_id}) - MERGE (user)-[:FAV]->(anthrovePost) - ` - - params := map[string]any{ - "anthrove_post_id": anthrovePost.PostID, - "anthrove_user_id": anthroveUser.UserID, - } - - _, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return err - } - - log.WithFields(log.Fields{ - "anthrove_post_id": anthrovePost.PostID, - "anthrove_user_id": anthroveUser.UserID, - }).Trace("database: created user to post link") - - return nil -} - -func CheckUserToPostLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { - query := ` - OPTIONAL MATCH (:User {user_id: $anthrove_user_id})-[f:FAV]->(:AnthrovePost)<-[:REFERENCE{source_post_id: $source_post_id}]-(:Source{domain: $source_domain}) - RETURN COUNT(f) > 0 AS hasRelationship - ` - - params := map[string]any{ - "anthrove_user_id": anthroveUserID, - "source_post_id": sourcePostID, - "source_domain": sourceUrl, - } - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return false, err - } - - if len(result.Records) == 0 { - return false, fmt.Errorf("no records found") - } - - exists, _, err := neo4j.GetRecordValue[bool](result.Records[0], "hasRelationship") - if err != nil { - return false, err - } - - log.WithFields(log.Fields{ - "relationship_exists": exists, - "relationship_anthrove_user_id": anthroveUserID, - "relationship_e621_post_id": "", - }).Trace("database: checked user post relationship") - - return exists, nil -} diff --git a/internal/graph/source.go b/internal/graph/source.go deleted file mode 100644 index 5ed8fa6..0000000 --- a/internal/graph/source.go +++ /dev/null @@ -1,113 +0,0 @@ -package graph - -import ( - "context" - "fmt" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - - "github.com/neo4j/neo4j-go-driver/v5/neo4j" - log "github.com/sirupsen/logrus" -) - -func CreateSourceNode(ctx context.Context, driver neo4j.DriverWithContext, anthroveSource *graphModels.AnthroveSource) error { - query := ` - MERGE (sourceNode:Source {domain: $source_url}) - ON CREATE SET sourceNode.domain = $source_url, sourceNode.display_name = $source_display_name, sourceNode.icon = $source_icon - ` - params := map[string]any{ - "source_url": anthroveSource.Domain, - "source_display_name": anthroveSource.DisplayName, - "source_icon": anthroveSource.Icon, - } - - _, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return fmt.Errorf("database: %w", err) - } - - log.WithFields(log.Fields{ - "node_source_url": anthroveSource.Domain, - "node_source_displayName": anthroveSource.DisplayName, - "node_source_icon": anthroveSource.Icon, - }).Trace("database: created source node") - - return nil -} - -func GetAllSourceNodes(ctx context.Context, driver neo4j.DriverWithContext) ([]graphModels.AnthroveSource, error) { - var sources []graphModels.AnthroveSource - - query := ` - MATCH (s:Source) - RETURN s as source - ` - params := map[string]any{} - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return nil, err - } - - if len(result.Records) == 0 { - return nil, nil - } - - for i := range result.Records { - record := result.Records[i] - - source, _, err := neo4j.GetRecordValue[neo4j.Node](record, "source") - if err != nil { - return nil, err - } - - sources = append(sources, graphModels.AnthroveSource{ - DisplayName: source.Props["display_name"].(string), - Domain: source.Props["domain"].(string), - Icon: source.Props["icon"].(string), - }) - - } - - log.WithFields(log.Fields{ - "tag_amount": len(sources), - }).Trace("database: created tag node") - - return sources, nil -} - -func GetSourceNodesByURL(ctx context.Context, driver neo4j.DriverWithContext, sourceUrl string) (*graphModels.AnthroveSource, error) { - - var source graphModels.AnthroveSource - - query := ` - MATCH (s:Source {domain: $source_url}) - RETURN s as source - ` - params := map[string]any{ - "source_url": sourceUrl, - } - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return nil, err - } - - if len(result.Records) == 0 { - return nil, fmt.Errorf("source not found") - } - - record, _, err := neo4j.GetRecordValue[neo4j.Node](result.Records[0], "source") - if err != nil { - return nil, err - } - - source.DisplayName = record.Props["display_name"].(string) - source.Domain = record.Props["domain"].(string) - source.Icon = record.Props["icon"].(string) - - log.WithFields(log.Fields{ - "source_url": sourceUrl, - }).Trace("database: got source node") - - return &source, nil -} diff --git a/internal/graph/tag.go b/internal/graph/tag.go deleted file mode 100644 index cc9142c..0000000 --- a/internal/graph/tag.go +++ /dev/null @@ -1,84 +0,0 @@ -package graph - -import ( - "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "github.com/neo4j/neo4j-go-driver/v5/neo4j" - log "github.com/sirupsen/logrus" -) - -func CreateTagNodeWitRelation(ctx context.Context, driver neo4j.DriverWithContext, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { - query := ` - MATCH (anthrovePost:AnthrovePost {post_id: $anthrove_post_id}) - MERGE (tagNode:Tag {name: $tag_name, type: $tag_type}) - MERGE (anthrovePost)-[:HAS]->(tagNode) - ` - params := map[string]interface{}{ - "tag_name": anthroveTag.Name, - "tag_type": anthroveTag.Type, - "anthrove_post_id": anthrovePostID, - } - - _, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return err - } - - log.WithFields(log.Fields{ - "anthrove_post_id": anthrovePostID, - "tag_name": anthroveTag.Name, - "tag_type": anthroveTag.Type, - }).Trace("database: created tag node") - - return nil -} - -func GetTags(ctx context.Context, driver neo4j.DriverWithContext) ([]graphModels.TagsWithFrequency, error) { - var userTags []graphModels.TagsWithFrequency - - query := ` - MATCH (:AnthrovePost)-[:HAS]->(t:Tag) - RETURN t as tag, COUNT(t) AS frequency - ORDER BY frequency DESC - ` - params := map[string]any{} - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return nil, err - } - - if len(result.Records) == 0 { - return nil, nil - } - - for i := range result.Records { - record := result.Records[i] - - tag, _, err := neo4j.GetRecordValue[neo4j.Node](record, "tag") - if err != nil { - return nil, err - } - - frequency, _, err := neo4j.GetRecordValue[int64](record, "frequency") - if err != nil { - return nil, err - } - - userTags = append(userTags, graphModels.TagsWithFrequency{ - Frequency: frequency, - Tags: graphModels.AnthroveTag{ - Name: tag.Props["name"].(string), - Type: tag.Props["type"].(string), - }, - }) - - } - - log.WithFields(log.Fields{ - "tag_amount": len(userTags), - }).Trace("database: created tag node") - - return userTags, nil -} diff --git a/internal/graph/user.go b/internal/graph/user.go deleted file mode 100644 index a136de3..0000000 --- a/internal/graph/user.go +++ /dev/null @@ -1,454 +0,0 @@ -package graph - -import ( - "context" - "fmt" - "git.dragse.it/anthrove/otter-space-sdk/internal/utils" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "github.com/neo4j/neo4j-go-driver/v5/neo4j" - log "github.com/sirupsen/logrus" -) - -func CreateUserNodeWithSourceRelation(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { - query := ` - MATCH (userNode:User {user_id: $anthrove_user_id}) - MATCH (sourceNode:Source {domain: $source_domain}) - MERGE (userNode)-[r:HAS_ACCOUNT_AT {username: $source_user_name, user_id: $source_user_id}]->(sourceNode) - ` - params := map[string]any{ - "anthrove_user_id": anthroveUserID, - "source_user_id": userID, - "source_user_name": username, - "source_domain": sourceDomain, - } - - _, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return err - } - - var anthroveUserRelationship []graphModels.AnthroveUserRelationship - - anthroveUserRelationship = append(anthroveUserRelationship, graphModels.AnthroveUserRelationship{ - UserID: userID, - Username: username, - ScrapeTimeInterval: "", - Source: graphModels.AnthroveSource{ - DisplayName: "", - Domain: sourceDomain, - Icon: "", - }, - }) - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "source_user_id": userID, - "source_user_name": username, - "source_domain": sourceDomain, - }).Trace("database: crated user with relationship") - - return nil -} - -func GetUserFavoritesCount(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) (int64, error) { - var userFavoriteCount int64 - - query := ` - MATCH (userNode:User {user_id: $anthrove_user_id}) - MATCH (userNode)-[:FAV]->(favPost:AnthrovePost) - MATCH (sourceNode)-[:REFERENCE]->(favPost) - RETURN count( DISTINCT favPost) AS FavoritePostsCount - ` - - params := map[string]any{ - "anthrove_user_id": anthroveUserID, - } - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return 0, err - } - - if len(result.Records) == 0 { - // no matches -> user does not exist, return count 0 - return userFavoriteCount, err - } - - record := result.Records[0] - - userFavoriteCount, _, err = neo4j.GetRecordValue[int64](record, "FavoritePostsCount") - if err != nil { - return userFavoriteCount, err - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "anthrove_user_fav_count": userFavoriteCount, - }).Trace("database: got user favorite count") - - return userFavoriteCount, nil -} - -func GetUserSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { - - userSource := make(map[string]graphModels.AnthroveUserRelationship) - - query := ` - MATCH (user:User{user_id: $anthrove_user_id})-[r:HAS_ACCOUNT_AT]->(s:Source) - RETURN toString(r.user_id) AS sourceUserID, toString(r.username) AS sourceUsername, s as source; - ` - params := map[string]any{ - "anthrove_user_id": anthroveUserID, - } - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return nil, err - } - - if len(result.Records) == 0 { - return nil, fmt.Errorf("user has no relations") - } - - for i := range result.Records { - record := result.Records[i] - source, _, err := neo4j.GetRecordValue[neo4j.Node](record, "source") - if err != nil { - return nil, err - } - sourceUserID, _, err := neo4j.GetRecordValue[string](record, "sourceUserID") - if err != nil { - return nil, err - } - sourceUsername, _, err := neo4j.GetRecordValue[string](record, "sourceUsername") - if err != nil { - return nil, err - } - - displayName := source.Props["display_name"].(string) - domain := source.Props["domain"].(string) - icon := source.Props["icon"].(string) - - anthroveSourceUser := graphModels.AnthroveUserRelationship{ - UserID: sourceUserID, - Username: sourceUsername, - Source: graphModels.AnthroveSource{ - DisplayName: displayName, - Domain: domain, - Icon: icon, - }, - } - userSource[displayName] = anthroveSourceUser - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "anthrove_data": userSource, - }).Trace("database: got user favorite count") - - return userSource, nil -} - -func GetSpecifiedUserSourceLink(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { - - userSource := make(map[string]graphModels.AnthroveUserRelationship) - - query := ` - MATCH (user:User{user_id: $anthrove_user_id})-[r:HAS_ACCOUNT_AT]->(s:Source{display_name: $source_display_name}) - RETURN toString(r.user_id) AS sourceUserID, toString(r.username) AS sourceUsername, s as source; - ` - params := map[string]any{ - "anthrove_user_id": anthroveUserID, - "source_display_name": sourceDisplayName, - } - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return nil, err - } - - if len(result.Records) == 0 { - return nil, fmt.Errorf("user has no relations with the source %s", sourceDisplayName) - } - - for i := range result.Records { - record := result.Records[i] - source, _, err := neo4j.GetRecordValue[neo4j.Node](record, "source") - if err != nil { - return nil, err - } - sourceUserID, _, err := neo4j.GetRecordValue[string](record, "sourceUserID") - if err != nil { - return nil, err - } - sourceUsername, _, err := neo4j.GetRecordValue[string](record, "sourceUsername") - if err != nil { - return nil, err - } - - displayName := source.Props["display_name"].(string) - domain := source.Props["domain"].(string) - icon := source.Props["icon"].(string) - - anthroveSourceUser := graphModels.AnthroveUserRelationship{ - UserID: sourceUserID, - Username: sourceUsername, - Source: graphModels.AnthroveSource{ - DisplayName: displayName, - Domain: domain, - Icon: icon, - }, - } - userSource[displayName] = anthroveSourceUser - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "anthrove_data": userSource, - }).Trace("database: got user favorite count") - - return userSource, nil -} - -func GetAnthroveUser(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { - var err error - var anthroveUser graphModels.AnthroveUser - var userSources graphModels.AnthroveSource - userRelationships := make([]graphModels.AnthroveUserRelationship, 0) - - query := ` - MATCH (user:User{user_id: $anthrove_user_id})-[relation:HAS_ACCOUNT_AT]->(source:Source) - RETURN user as User, relation as Relation, source as Source; - ` - params := map[string]any{ - "anthrove_user_id": anthroveUserID, - } - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return nil, err - } - - if len(result.Records) == 0 { - return nil, fmt.Errorf("user has no relations") - } - - for i := range result.Records { - record := result.Records[i] - - user, _, err := neo4j.GetRecordValue[neo4j.Node](record, "User") - if err != nil { - return nil, err - } - relation, _, err := neo4j.GetRecordValue[neo4j.Relationship](record, "Relation") - if err != nil { - return nil, err - } - source, _, err := neo4j.GetRecordValue[neo4j.Node](record, "Source") - if err != nil { - return nil, err - } - - userRelationships = append(userRelationships, graphModels.AnthroveUserRelationship{ - UserID: fmt.Sprintf("%v", utils.GetOrDefault(relation.Props, "user_id", "")), - Username: utils.GetOrDefault(relation.Props, "username", "").(string), - ScrapeTimeInterval: utils.GetOrDefault(relation.Props, "scrape_time_interval", "").(string), - }) - - userSources = graphModels.AnthroveSource{ - DisplayName: utils.GetOrDefault(source.Props, "display_name", "").(string), - Domain: utils.GetOrDefault(source.Props, "domain", "").(string), - Icon: utils.GetOrDefault(source.Props, "icon", "").(string), - } - - anthroveUser.UserID = models.AnthroveUserID(utils.GetOrDefault(user.Props, "user_id", "").(string)) - anthroveUser.Relationship = userRelationships - - for j := range userRelationships { - anthroveUser.Relationship[j].Source = userSources - } - - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Trace("database: got anthrove user") - - return &anthroveUser, nil - -} - -func GetAllAnthroveUserIDs(ctx context.Context, driver neo4j.DriverWithContext) ([]models.AnthroveUserID, error) { - var err error - var anthroveUsers []models.AnthroveUserID - - query := ` - MATCH (anthroveUser:User) - RETURN anthroveUser - ` - result, err := neo4j.ExecuteQuery(ctx, driver, query, nil, neo4j.EagerResultTransformer) - if err != nil { - return nil, err - } - - if len(result.Records) == 0 { - log.Warnf("No users found, this should not be happening!") - return []models.AnthroveUserID{}, nil - } - - for i := range result.Records { - record := result.Records[i] - - user, _, err := neo4j.GetRecordValue[neo4j.Node](record, "anthroveUser") - if err != nil { - return nil, err - } - - anthroveUsers = append(anthroveUsers, models.AnthroveUserID(fmt.Sprintf(user.Props["user_id"].(string)))) - } - - log.WithFields(log.Fields{ - "anthrove_user_id_count": len(anthroveUsers), - }).Trace("database: got al anthrove user IDs") - - return anthroveUsers, nil - -} - -func GetUserFavoriteNodeWithPagination(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { - var err error - var favoritePosts []graphModels.FavoritePost - - query := ` - CALL { - MATCH (user:User{user_id: $anthrove_user_id})-[r:FAV]->(p:AnthrovePost) - RETURN p.post_id AS post_id - ORDER BY id(p) ASC - SKIP $skip - LIMIT $limit - } - WITH collect(post_id) AS faves - MATCH (a:AnthrovePost)<-[r:REFERENCE]-(s:Source) - WHERE a.post_id in faves - RETURN a AS anthrovePost, r AS postRelation, s AS Source - ORDER BY id(a) ASC - ` - params := map[string]any{ - "anthrove_user_id": anthroveUserID, - "limit": limit, - "skip": skip, - } - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return nil, err - } - - if len(result.Records) == 0 { - return nil, nil - } - - for i := range result.Records { - record := result.Records[i] - - anthrovePost, _, err := neo4j.GetRecordValue[neo4j.Node](record, "anthrovePost") - if err != nil { - return nil, err - } - - postRelation, _, err := neo4j.GetRecordValue[neo4j.Relationship](record, "postRelation") - if err != nil { - return nil, err - } - - source, _, err := neo4j.GetRecordValue[neo4j.Node](record, "Source") - if err != nil { - return nil, err - } - - if len(favoritePosts) != 0 && favoritePosts[len(favoritePosts)-1].AnthrovePost.PostID == models.AnthrovePostID(anthrovePost.Props["post_id"].(string)) { - favoritePosts[len(favoritePosts)-1].Relations = append(favoritePosts[len(favoritePosts)-1].Relations, graphModels.FavoriteRelations{ - SourcesID: source.Props["display_name"].(string), - Relations: graphModels.AnthrovePostRelationship{ - PostID: postRelation.Props["source_post_id"].(string), - Url: postRelation.Props["url"].(string), - }, - }) - } else { - favoritePosts = append(favoritePosts, graphModels.FavoritePost{ - AnthrovePost: graphModels.AnthrovePost{ - PostID: models.AnthrovePostID(anthrovePost.Props["post_id"].(string)), - Rating: models.Rating(anthrovePost.Props["rating"].(string)), - }, - Relations: []graphModels.FavoriteRelations{{ - SourcesID: source.Props["display_name"].(string), - Relations: graphModels.AnthrovePostRelationship{ - PostID: postRelation.Props["source_post_id"].(string), - Url: postRelation.Props["url"].(string), - }, - }}, - }) - - } - - } - - log.WithFields(log.Fields{ - "anthrove_user_fav_count": len(favoritePosts), - }).Trace("database: got al anthrove user favorites") - - return &graphModels.FavoriteList{Posts: favoritePosts}, nil - -} - -func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, driver neo4j.DriverWithContext, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { - var userTags []graphModels.TagsWithFrequency - - query := ` - MATCH (u:User {user_id: $anthrove_user_id})-[:FAV]->(:AnthrovePost)-[:HAS]->(t:Tag) - RETURN t as tag, COUNT(t) AS frequency - ORDER BY frequency DESC - ` - params := map[string]any{ - "anthrove_user_id": anthroveUserID, - } - - result, err := neo4j.ExecuteQuery(ctx, driver, query, params, neo4j.EagerResultTransformer) - if err != nil { - return nil, err - } - - if len(result.Records) == 0 { - return nil, nil - } - - for i := range result.Records { - record := result.Records[i] - - tag, _, err := neo4j.GetRecordValue[neo4j.Node](record, "tag") - if err != nil { - return nil, err - } - - frequency, _, err := neo4j.GetRecordValue[int64](record, "frequency") - if err != nil { - return nil, err - } - - userTags = append(userTags, graphModels.TagsWithFrequency{ - Frequency: frequency, - Tags: graphModels.AnthroveTag{ - Name: tag.Props["name"].(string), - Type: tag.Props["type"].(string), - }, - }) - - } - - log.WithFields(log.Fields{ - "tag_amount": len(userTags), - }).Trace("database: created tag node") - - return userTags, nil -} diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 3ed43a5..d00c08a 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -6,14 +6,13 @@ import ( "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) func CreateAnthrovePostNode(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, anthroveRating models.Rating) error { - post := pgModels.Post{ - BaseModel: pgModels.BaseModel{ + post := models.Post{ + BaseModel: models.BaseModel{ ID: string(anthrovePostID), }, Rating: anthroveRating, @@ -41,8 +40,8 @@ func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, } func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*graphModels.AnthrovePost, bool, error) { - postRef := pgModels.PostReference{} - err := db.WithContext(ctx).Model(&pgModels.PostReference{}).Where("url = ?", sourceURL).First(&postRef).Error + postRef := models.PostReference{} + err := db.WithContext(ctx).Model(&models.PostReference{}).Where("url = ?", sourceURL).First(&postRef).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -51,7 +50,7 @@ func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, return nil, false, err } - var post pgModels.Post + var post models.Post err = db.WithContext(ctx).First(&post, "id = ?", postRef.PostID).Error if err != nil { @@ -76,7 +75,7 @@ func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, db *gorm.DB, s func executeCheckQuery(ctx context.Context, db *gorm.DB, query string, args ...interface{}) (bool, error) { var count int64 - err := db.WithContext(ctx).Model(&pgModels.Post{}).Where(query, args...).Count(&count).Error + err := db.WithContext(ctx).Model(&models.Post{}).Where(query, args...).Count(&count).Error if err != nil { return false, err } diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index a109fdb..969e66d 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -4,13 +4,12 @@ import ( "context" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { - var source pgModels.Source + var source models.Source var err error // Find the source @@ -20,7 +19,7 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrov } // Establish the relationship - err = db.WithContext(ctx).Create(pgModels.PostReference{ + err = db.WithContext(ctx).Create(models.PostReference{ PostID: string(anthrovePostID), SourceID: source.ID, URL: anthrovePostRelationship.Url, @@ -39,7 +38,7 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrov } func EstablishUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { - userFavorite := pgModels.UserFavorite{ + userFavorite := models.UserFavorite{ UserID: string(anthroveUserID), PostID: string(anthrovePostID), } @@ -59,7 +58,7 @@ func EstablishUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID mo func CheckUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { var count int64 - err := db.WithContext(ctx).Model(&pgModels.UserFavorite{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count).Error + err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count).Error if err != nil { return false, err } diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go index 29b29ba..b96a5f3 100644 --- a/internal/postgres/relationships_test.go +++ b/internal/postgres/relationships_test.go @@ -3,7 +3,6 @@ package postgres import ( "context" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" "testing" @@ -26,7 +25,7 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { t.Fatal(err) } - source := &pgModels.Source{ + source := &models.Source{ DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", diff --git a/internal/postgres/source.go b/internal/postgres/source.go index 0e60a5e..5e4ecd5 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -3,20 +3,20 @@ package postgres import ( "context" "fmt" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) // CreateSourceNode creates a pgModels.Source -func CreateSourceNode(ctx context.Context, db *gorm.DB, anthroveSource *pgModels.Source) error { +func CreateSourceNode(ctx context.Context, db *gorm.DB, anthroveSource *models.Source) error { if anthroveSource.Domain == "" { return fmt.Errorf("anthroveSource domain is required") } - result := db.WithContext(ctx).Where(pgModels.Source{Domain: anthroveSource.Domain}).FirstOrCreate(anthroveSource) + result := db.WithContext(ctx).Where(models.Source{Domain: anthroveSource.Domain}).FirstOrCreate(anthroveSource) if result.Error != nil { return result.Error @@ -32,8 +32,8 @@ func CreateSourceNode(ctx context.Context, db *gorm.DB, anthroveSource *pgModels } // GetAllSourceNodes returns a list of all pgModels.Source -func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]pgModels.Source, error) { - var sources []pgModels.Source +func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]models.Source, error) { + var sources []models.Source result := db.WithContext(ctx).Find(&sources) @@ -49,8 +49,8 @@ func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]pgModels.Source, err } // GetSourceNodesByURL returns the first source it finds based on the domain -func GetSourceNodesByURL(ctx context.Context, db *gorm.DB, domain string) (*pgModels.Source, error) { - var sources pgModels.Source +func GetSourceNodesByURL(ctx context.Context, db *gorm.DB, domain string) (*models.Source, error) { + var sources models.Source if domain == "" { return nil, fmt.Errorf("domain is required") diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go index d0514c2..99fd7b8 100644 --- a/internal/postgres/source_test.go +++ b/internal/postgres/source_test.go @@ -2,7 +2,7 @@ package postgres import ( "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" "testing" @@ -19,13 +19,13 @@ func TestCreateSourceNode(t *testing.T) { // Setup Test - validAnthroveSource := &pgModels.Source{ + validAnthroveSource := &models.Source{ DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", } - invalidAnthroveSource := &pgModels.Source{ + invalidAnthroveSource := &models.Source{ Domain: "", } @@ -33,7 +33,7 @@ func TestCreateSourceNode(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveSource *pgModels.Source + anthroveSource *models.Source } tests := []struct { name string @@ -88,7 +88,7 @@ func TestGetAllSourceNodes(t *testing.T) { // Setup Test - sources := []pgModels.Source{ + sources := []models.Source{ { DisplayName: "e621", Domain: "e621.net", @@ -121,7 +121,7 @@ func TestGetAllSourceNodes(t *testing.T) { tests := []struct { name string args args - want []pgModels.Source + want []models.Source wantErr bool }{ { @@ -159,7 +159,7 @@ func TestGetSourceNodesByURL(t *testing.T) { // Setup Test - source := &pgModels.Source{ + source := &models.Source{ DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", @@ -179,7 +179,7 @@ func TestGetSourceNodesByURL(t *testing.T) { tests := []struct { name string args args - want *pgModels.Source + want *models.Source wantErr bool }{ { @@ -227,7 +227,7 @@ func TestGetSourceNodesByURL(t *testing.T) { } } -func checkSourcesNode(got []pgModels.Source, want []pgModels.Source) bool { +func checkSourcesNode(got []models.Source, want []models.Source) bool { for i, source := range want { if source.DisplayName != got[i].DisplayName { return false @@ -244,7 +244,7 @@ func checkSourcesNode(got []pgModels.Source, want []pgModels.Source) bool { } -func checkSourceNode(got *pgModels.Source, want *pgModels.Source) bool { +func checkSourceNode(got *models.Source, want *models.Source) bool { if want == nil && got == nil { return true diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 4249069..124742e 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -4,12 +4,11 @@ import ( "context" "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) -func CreateTag(ctx context.Context, db *gorm.DB, tag *pgModels.Tag) error { +func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { resultTag := db.WithContext(ctx).Where(tag).Create(tag) @@ -25,7 +24,7 @@ func CreateTag(ctx context.Context, db *gorm.DB, tag *pgModels.Tag) error { return nil } -func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.AnthrovePostID, tag *pgModels.Tag) error { +func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.AnthrovePostID, tag *models.Tag) error { if PostID == "" { return fmt.Errorf("PostID is empty") @@ -37,8 +36,8 @@ func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.An return resultTag.Error } - pgPost := pgModels.Post{ - BaseModel: pgModels.BaseModel{ + pgPost := models.Post{ + BaseModel: models.BaseModel{ ID: string(PostID), }, } @@ -58,8 +57,8 @@ func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.An return nil } -func GetTags(ctx context.Context, db *gorm.DB) ([]pgModels.Tag, error) { - var tags []pgModels.Tag +func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) { + var tags []models.Tag result := db.WithContext(ctx).Find(&tags) if result.Error != nil { return nil, result.Error diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index 347754e..c0b323a 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -3,7 +3,6 @@ package postgres import ( "context" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" "testing" @@ -25,7 +24,7 @@ func TestCreateTagNodeWitRelation(t *testing.T) { t.Fatal(err) } - tag := &pgModels.Tag{ + tag := &models.Tag{ Name: "JayTheFerret", Type: "artist", } @@ -35,7 +34,7 @@ func TestCreateTagNodeWitRelation(t *testing.T) { ctx context.Context db *gorm.DB PostID models.AnthrovePostID - tag *pgModels.Tag + tag *models.Tag } tests := []struct { name string @@ -103,7 +102,7 @@ func TestGetTags(t *testing.T) { // Setup Test - tags := []pgModels.Tag{ + tags := []models.Tag{ { Name: "JayTheFerret", Type: "artist", @@ -133,7 +132,7 @@ func TestGetTags(t *testing.T) { tests := []struct { name string args args - want []pgModels.Tag + want []models.Tag wantErr bool }{ { @@ -160,7 +159,7 @@ func TestGetTags(t *testing.T) { } } -func checkTag(got []pgModels.Tag, want []pgModels.Tag) bool { +func checkTag(got []models.Tag, want []models.Tag) bool { for i, tag := range want { if tag.Type != got[i].Type { return false diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 10b343c..2c9e56e 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -5,7 +5,6 @@ import ( "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) @@ -16,8 +15,8 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove return fmt.Errorf("anthroveUserID cannot be empty") } - user := pgModels.User{ - BaseModel: pgModels.BaseModel{ + user := models.User{ + BaseModel: models.BaseModel{ ID: string(anthroveUserID), }, } @@ -39,8 +38,8 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthrove return fmt.Errorf("anthroveUserID cannot be empty") } - user := pgModels.User{ - BaseModel: pgModels.BaseModel{ + user := models.User{ + BaseModel: models.BaseModel{ ID: string(anthroveUserID), }, } @@ -52,7 +51,7 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthrove return err } - source := pgModels.Source{ + source := models.Source{ Domain: sourceDomain, } @@ -63,7 +62,7 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthrove return err } - userSource := pgModels.UserSource{ + userSource := models.UserSource{ UserID: user.ID, SourceID: source.ID, AccountUsername: username, @@ -96,7 +95,7 @@ func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID mode } var count int64 - err := db.WithContext(ctx).Model(&pgModels.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Count(&count).Error + err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Count(&count).Error if err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, @@ -113,10 +112,10 @@ func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID mode } func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { - var userSources []pgModels.UserSource + var userSources []models.UserSource userSourceMap := make(map[string]graphModels.AnthroveUserRelationship) - err := db.WithContext(ctx).Model(&pgModels.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error + err := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error if err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, @@ -125,8 +124,8 @@ func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.A } for _, userSource := range userSources { - var source pgModels.Source - err = db.WithContext(ctx).Model(&pgModels.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error + var source models.Source + err = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error if err != nil { log.WithFields(log.Fields{ "source_id": userSource.SourceID, @@ -157,10 +156,10 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID return nil, fmt.Errorf("anthroveUserID or sourceDisplayName is empty") } - var userSources []pgModels.UserSource + var userSources []models.UserSource userSourceMap := make(map[string]graphModels.AnthroveUserRelationship) - err := db.WithContext(ctx).Model(&pgModels.UserSource{}).InnerJoins("Source", db.Where("display_name = ?", sourceDisplayName)).Where("user_id = ?", string(anthroveUserID)).First(&userSources).Error + err := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("display_name = ?", sourceDisplayName)).Where("user_id = ?", string(anthroveUserID)).First(&userSources).Error if err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, @@ -170,8 +169,8 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID } for _, userSource := range userSources { - var source pgModels.Source - err = db.WithContext(ctx).Model(&pgModels.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error + var source models.Source + err = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error if err != nil { log.WithFields(log.Fields{ "source_id": userSource.SourceID, @@ -204,8 +203,8 @@ func GetAnthroveUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Ant return nil, fmt.Errorf("anthroveUserID cannot be empty") } - var user pgModels.User - var userSources []pgModels.UserSource + var user models.User + var userSources []models.UserSource anthroveUser := &graphModels.AnthroveUser{ UserID: anthroveUserID, } @@ -218,7 +217,7 @@ func GetAnthroveUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Ant return nil, err } - err = db.WithContext(ctx).Model(&pgModels.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error + err = db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error if err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, @@ -227,8 +226,8 @@ func GetAnthroveUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Ant } for _, userSource := range userSources { - var source pgModels.Source - err = db.WithContext(ctx).Model(&pgModels.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error + var source models.Source + err = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error if err != nil { log.WithFields(log.Fields{ "source_id": userSource.SourceID, @@ -255,10 +254,10 @@ func GetAnthroveUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Ant } func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveUserID, error) { - var users []pgModels.User + var users []models.User var userIDs []models.AnthroveUserID - err := db.WithContext(ctx).Model(&pgModels.User{}).Find(&users).Error + err := db.WithContext(ctx).Model(&models.User{}).Find(&users).Error if err != nil { log.Error("database: failed to get all anthrove user IDs") return nil, err @@ -276,10 +275,10 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU } func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { - var userFavorites []pgModels.UserFavorite + var userFavorites []models.UserFavorite var favoritePosts []graphModels.FavoritePost - err := db.WithContext(ctx).Model(&pgModels.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error + err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error if err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, @@ -290,8 +289,8 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthrov } for _, userFavorite := range userFavorites { - var post pgModels.Post - err = db.WithContext(ctx).Model(&pgModels.Post{}).Where("id = ?", userFavorite.PostID).First(&post).Error + var post models.Post + err = db.WithContext(ctx).Model(&models.Post{}).Where("id = ?", userFavorite.PostID).First(&post).Error if err != nil { log.WithFields(log.Fields{ "post_id": userFavorite.PostID, @@ -316,7 +315,7 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthrov } func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { - var userFavorites []pgModels.UserFavorite + var userFavorites []models.UserFavorite err := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites).Error if err != nil { log.WithFields(log.Fields{ @@ -330,7 +329,7 @@ func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, ant typeName string }]int) for _, userFavorite := range userFavorites { - var post pgModels.Post + var post models.Post err = db.WithContext(ctx).Preload("Tags").First(&post, "id = ?", userFavorite.PostID).Error if err != nil { log.WithFields(log.Fields{ diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 531e13e..6beec7b 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -5,7 +5,6 @@ import ( "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" "reflect" @@ -73,7 +72,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { // Setup Test - source := &pgModels.Source{ + source := &models.Source{ DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", @@ -320,7 +319,7 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { defer container.Terminate(ctx) // Setup Test - source := &pgModels.Source{ + source := &models.Source{ DisplayName: "e621", Domain: "e621.net", } @@ -455,37 +454,37 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post1")), Rating: "safe", }, - }, + }, { AnthrovePost: graphModels.AnthrovePost{ PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post2")), Rating: "safe", }, - }, + }, { AnthrovePost: graphModels.AnthrovePost{ PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post3")), Rating: "explicit", }, - }, + }, { AnthrovePost: graphModels.AnthrovePost{ PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post4")), Rating: "explicit", }, - }, + }, { AnthrovePost: graphModels.AnthrovePost{ PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post5")), Rating: "questionable", }, - }, + }, { AnthrovePost: graphModels.AnthrovePost{ PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post6")), Rating: "safe", }, - }, + }, } expectedResult := &graphModels.FavoriteList{ Posts: expectedResultPostsGraph, @@ -502,31 +501,31 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { t.Fatal(err) } - expectedResultPostsPg := []pgModels.Post{ + expectedResultPostsPg := []models.Post{ { - BaseModel: pgModels.BaseModel{ID: "Post1"}, + BaseModel: models.BaseModel{ID: "Post1"}, Rating: "safe", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post2"}, + BaseModel: models.BaseModel{ID: "Post2"}, Rating: "safe", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post3"}, + BaseModel: models.BaseModel{ID: "Post3"}, Rating: "explicit", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post4"}, + BaseModel: models.BaseModel{ID: "Post4"}, Rating: "explicit", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post5"}, + BaseModel: models.BaseModel{ID: "Post5"}, Rating: "questionable", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post6"}, + BaseModel: models.BaseModel{ID: "Post6"}, Rating: "safe", - }, + }, } for _, expectedResultPost := range expectedResultPostsPg { @@ -621,31 +620,31 @@ func TestGetUserFavoritesCount(t *testing.T) { t.Fatal(err) } - expectedResultPostsPg := []pgModels.Post{ + expectedResultPostsPg := []models.Post{ { - BaseModel: pgModels.BaseModel{ID: "Post1"}, + BaseModel: models.BaseModel{ID: "Post1"}, Rating: "safe", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post2"}, + BaseModel: models.BaseModel{ID: "Post2"}, Rating: "safe", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post3"}, + BaseModel: models.BaseModel{ID: "Post3"}, Rating: "explicit", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post4"}, + BaseModel: models.BaseModel{ID: "Post4"}, Rating: "explicit", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post5"}, + BaseModel: models.BaseModel{ID: "Post5"}, Rating: "questionable", - }, + }, { - BaseModel: pgModels.BaseModel{ID: "Post6"}, + BaseModel: models.BaseModel{ID: "Post6"}, Rating: "safe", - }, + }, } for _, expectedResultPost := range expectedResultPostsPg { @@ -727,7 +726,7 @@ func TestGetUserSourceLink(t *testing.T) { // Setup Test - esource := &pgModels.Source{ + esource := &models.Source{ DisplayName: "e621", Domain: "e621.net", } @@ -736,7 +735,7 @@ func TestGetUserSourceLink(t *testing.T) { t.Fatal(err) } - fasource := &pgModels.Source{ + fasource := &models.Source{ DisplayName: "fa", Domain: "fa.net", } @@ -823,10 +822,10 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { t.Fatal(err) } - posts := []pgModels.Post{ - {BaseModel: pgModels.BaseModel{ID: fmt.Sprintf("%-25s", "Post1")}, Rating: "safe"}, - {BaseModel: pgModels.BaseModel{ID: fmt.Sprintf("%-25s", "Post2")}, Rating: "safe"}, - {BaseModel: pgModels.BaseModel{ID: fmt.Sprintf("%-25s", "Post3")}, Rating: "explicit"}, + posts := []models.Post{ + {BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post1")}, Rating: "safe"}, + {BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post2")}, Rating: "safe"}, + {BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post3")}, Rating: "explicit"}, } for _, post := range posts { @@ -840,7 +839,7 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { } } - tags := []pgModels.Tag{ + tags := []models.Tag{ {Name: "JayTheFerret", Type: "artist"}, {Name: "Ferret", Type: "species"}, {Name: "Jay", Type: "character"}, diff --git a/internal/utils/modelConvert.go b/internal/utils/modelConvert.go deleted file mode 100644 index 29a4995..0000000 --- a/internal/utils/modelConvert.go +++ /dev/null @@ -1,60 +0,0 @@ -package utils - -import ( - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/pgModels" -) - -// GraphConvertSource converts a graphModels.AnthroveSource to a pgModels.Source -func GraphConvertSource(graphSource *graphModels.AnthroveSource) *pgModels.Source { - pgSource := &pgModels.Source{ - DisplayName: graphSource.DisplayName, - Domain: graphSource.Domain, - Icon: graphSource.Icon, - } - return pgSource -} - -// PostgresConvertToAnthroveSource converts a pgModels.Source to a graphModels.AnthroveSource -func PostgresConvertToAnthroveSource(pgSource *pgModels.Source) *graphModels.AnthroveSource { - graphSource := &graphModels.AnthroveSource{ - DisplayName: pgSource.DisplayName, - Domain: pgSource.Domain, - Icon: pgSource.Icon, - } - - return graphSource -} - -// GraphConvertTag converts a graphModels.AnthroveTag to a pgModels.Tag -func GraphConvertTag(graphTag *graphModels.AnthroveTag) *pgModels.Tag { - pgTag := &pgModels.Tag{ - Name: graphTag.Name, - Type: models.TagType(graphTag.Type), - } - return pgTag -} - -// PostgresConvertToAnthroveTag converts a pgModels.Tag to a graphModels.AnthroveTag -func PostgresConvertToAnthroveTag(pgTag *pgModels.Tag) *graphModels.AnthroveTag { - graphTag := &graphModels.AnthroveTag{ - Name: pgTag.Name, - Type: string(pgTag.Type), - } - - return graphTag -} - -func ConvertToTagsWithFrequency(tags []pgModels.Tag) []graphModels.TagsWithFrequency { - var tagsWithFrequency []graphModels.TagsWithFrequency - for _, tag := range tags { - graphTag := PostgresConvertToAnthroveTag(&tag) - tagsWithFrequency = append(tagsWithFrequency, graphModels.TagsWithFrequency{ - Frequency: 0, - Tags: *graphTag, - }) - } - - return tagsWithFrequency -} diff --git a/pkg/database/database.go b/pkg/database/database.go index 307bc83..a6c908b 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -1,34 +1,8 @@ -// Package database provides a client for using the OtterSpace API. -// -// This package provides a client to interact with the OtterSpace API. It includes -// methods for all API endpoints, and convenience methods for common tasks. -// -// This is a simple usage example: -// -// package main -// -// import ( -// "context" -// "fmt" -// "git.dragse.it/anthrove/otter-space-sdk/pkg/models" -// "git.dragse.it/anthrove/otter-space-sdk/pkg/database" -// ) -// -// func main() { -// client := database.NewGraphConnection() -// err := client.Connect(context.Background(), "your-endpoint", "your-username", "your-password") -// if err != nil { -// fmt.Println(err) -// return -// } -// // further usage of the client... -// } package database import ( "context" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" ) // OtterSpace provides an interface for interacting with the OtterSpace API. @@ -45,23 +19,23 @@ type OtterSpace interface { // AddSource adds a new source to the OtterSpace database. // It returns an error if the operation fails. - AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error + AddSource(ctx context.Context, anthroveSource *models.Source) error // AddPost adds a new post to the OtterSpace database. // It returns an error if the operation fails. - AddPost(ctx context.Context, anthrovePost *graphModels.AnthrovePost) error + AddPost(ctx context.Context, anthrovePost *models.Post) error // AddTagWithRelationToPost adds a new tag to the OtterSpace database and associates it with a post. // It returns an error if the operation fails. - AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error + AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error // LinkPostWithSource establishes a link between a post and a source in the OtterSpace database. // It returns an error if the operation fails. - LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error + LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.PostReference) error // LinkUserWithPost establishes a link between a user and a post in the OtterSpace database. // It returns an error if the operation fails. - LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error + LinkUserWithPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error // CheckUserPostLink checks if a link between a user and a post exists in the OtterSpace database. // It returns true if the link exists, false otherwise, and an error if the operation fails. @@ -69,15 +43,15 @@ type OtterSpace interface { // CheckPostNodeExistsByAnthroveID checks if a post node exists in the OtterSpace database by its Anthrove ID. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. - CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) + CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, bool, error) // CheckPostNodeExistsBySourceURL checks if a post node exists in the OtterSpace database by its source URL. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. - CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) + CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, bool, error) // CheckPostNodeExistsBySourceID checks if a post node exists in the OtterSpace database by its source ID. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. - CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*graphModels.AnthrovePost, bool, error) + CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.Post, bool, error) // GetUserFavoriteCount retrieves the count of a user's favorite posts from the OtterSpace database. // It returns the count and an error if the operation fails. @@ -85,32 +59,32 @@ type OtterSpace interface { // GetUserSourceLinks retrieves the links between a user and sources in the OtterSpace database. // It returns a map of source domains to user-source relationships, and an error if the operation fails. - GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) + GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) // GetSpecifiedUserSourceLink GetUserSourceLinks retrieves the links between a user and a specific source in the OtterSpace database. // It returns a map of source domains to user-source relationships, and an error if the operation fails. - GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) + GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) // GetAnthroveUser retrieves a user from the OtterSpace database by their ID. // It returns the user and an error if the operation fails. - GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) + GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.User, error) // GetAllAnthroveUserIDs retrieves all user IDs from the OtterSpace database. // It returns a slice of user IDs and an error if the operation fails. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) // GetUserFavoritePostsWithPagination gets all user favorites with relation and sources for the given user - GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) + GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) // GetUserTagsTroughFavedPosts returns a list of Tags that the user hs favorites through a post - GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) + GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) // GetAllTags returns a list of Tags that the user hs favorites through a post - GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) + GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) // GetAllSources returns a list of Sources in the database - GetAllSources(ctx context.Context) ([]graphModels.AnthroveSource, error) + GetAllSources(ctx context.Context) ([]models.Source, error) // GetSourceByURL returns the Source Node based on the URL - GetSourceByURL(ctx context.Context, sourceUrl string) (*graphModels.AnthroveSource, error) + GetSourceByURL(ctx context.Context, sourceUrl string) (*models.Source, error) } diff --git a/pkg/database/graph.go b/pkg/database/graph.go deleted file mode 100644 index 7fc5bf2..0000000 --- a/pkg/database/graph.go +++ /dev/null @@ -1,123 +0,0 @@ -package database - -import ( - "context" - "git.dragse.it/anthrove/otter-space-sdk/internal/graph" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" - "github.com/neo4j/neo4j-go-driver/v5/neo4j" - "github.com/neo4j/neo4j-go-driver/v5/neo4j/config" -) - -type graphConnection struct { - driver neo4j.DriverWithContext - graphDebug bool -} - -func NewGraphConnection(graphDebug bool) OtterSpace { - return &graphConnection{ - driver: nil, - graphDebug: graphDebug, - } -} - -func (g *graphConnection) Connect(ctx context.Context, endpoint string, username string, password string, _ string, _ int, _ string, _ string) error { - driver, err := neo4j.NewDriverWithContext(endpoint, neo4j.BasicAuth(username, password, ""), - logger(g.graphDebug)) - - if err != nil { - return err - } - err = driver.VerifyAuthentication(ctx, nil) - if err != nil { - return err - } - g.driver = driver - return nil -} - -func (g *graphConnection) AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { - return graph.CreateUserNodeWithSourceRelation(ctx, g.driver, anthroveUserID, sourceDomain, userID, username) -} - -func (g *graphConnection) AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error { - return graph.CreateSourceNode(ctx, g.driver, anthroveSource) -} - -func (g *graphConnection) AddPost(ctx context.Context, anthrovePost *graphModels.AnthrovePost) error { - return graph.CreateAnthrovePostNode(ctx, g.driver, anthrovePost) -} - -func (g *graphConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { - return graph.CreateTagNodeWitRelation(ctx, g.driver, anthrovePostID, anthroveTag) -} - -func (g *graphConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { - return graph.EstablishAnthrovePostToSourceLink(ctx, g.driver, anthrovePostID, anthroveSourceDomain, anthrovePostRelationship) -} - -func (g *graphConnection) LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { - return graph.EstablishUserToPostLink(ctx, g.driver, anthroveUser, anthrovePost) -} - -func (g *graphConnection) CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { - return graph.CheckUserToPostLink(ctx, g.driver, anthroveUserID, sourcePostID, sourceUrl) -} - -func (g *graphConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { - return graph.CheckIfAnthrovePostNodeExistsByAnthroveID(ctx, g.driver, anthrovePost) -} - -func (g *graphConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { - return graph.CheckIfAnthrovePostNodeExistsBySourceURl(ctx, g.driver, sourceUrl) -} - -func (g *graphConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*graphModels.AnthrovePost, bool, error) { - return graph.CheckIfAnthrovePostNodeExistsBySourceID(ctx, g.driver, sourcePostID) -} - -func (g *graphConnection) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { - return graph.GetUserFavoritesCount(ctx, g.driver, anthroveUserID) -} - -func (g *graphConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { - return graph.GetUserSourceLink(ctx, g.driver, anthroveUserID) -} - -func (g *graphConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { - return graph.GetSpecifiedUserSourceLink(ctx, g.driver, anthroveUserID, sourceDisplayName) -} - -func (g *graphConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { - return graph.GetAnthroveUser(ctx, g.driver, anthroveUserID) -} - -func (g *graphConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { - return graph.GetAllAnthroveUserIDs(ctx, g.driver) -} - -func (g *graphConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { - return graph.GetUserFavoriteNodeWithPagination(ctx, g.driver, anthroveUserID, skip, limit) -} - -func (g *graphConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { - return graph.GetUserTagNodeWitRelationToFavedPosts(ctx, g.driver, anthroveUserID) -} - -func (g *graphConnection) GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) { - return graph.GetTags(ctx, g.driver) -} - -func (g *graphConnection) GetAllSources(ctx context.Context) ([]graphModels.AnthroveSource, error) { - return graph.GetAllSourceNodes(ctx, g.driver) -} - -func (g *graphConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*graphModels.AnthroveSource, error) { - return graph.GetSourceNodesByURL(ctx, g.driver, sourceUrl) -} - -func logger(graphDebug bool) func(config *config.Config) { - return func(config *config.Config) { - config.Log = graph.NewGraphLogger(graphDebug) - } -} diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index 70ae07a..749a337 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -89,10 +89,10 @@ CREATE TABLE "UserFavorites" CREATE TABLE "UserSource" ( - user_id TEXT REFERENCES "User" (id), - source_id TEXT REFERENCES "Source" (id), - account_username TEXT, - account_id TEXT, + user_id TEXT REFERENCES "User" (id), + source_id TEXT REFERENCES "Source" (id), + scrape_time_interval TEXT account_username TEXT, + account_id TEXT, PRIMARY KEY (user_id, source_id), UNIQUE (account_username, account_id) ); diff --git a/pkg/models/README.md b/pkg/models/README.md deleted file mode 100644 index af61315..0000000 --- a/pkg/models/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Postgres - -https://www.dbdiagram.io/d - -```` -Table User { - id string [primary key] - created_at timestamp -} - -Table Post { - id varchar(25) [primary key] - rating Rating - created_at timestamp -} - -Enum Rating { - safe - questionable - explicit -} - -Table Source { - id varchar(25) [primary key] - display_name text - domain text [not null, unique] -} - -Table Tag { - name text [primary key] - type TagType -} - -Enum TagType { - general - species - character - artist - lore - meta - invalid -} - -Table TagAlias { - name text [primary key] - tag_id text -} - -Table TagGroup { - name text [primary key] - tag_id text -} - -Table UserFavorites { - user_id text [primary key] - post_id text [primary key] - created_at timestamp -} - -Table UserSource { - user_id text [primary key] - source_id text [primary key] - account_username text - account_id text -} - -Table PostReference { - post_id text [primary key] - source_id text [primary key] - url text [not null, unique] - source_post_id text -} - -Ref: Tag.name > TagAlias.tag_id -Ref: Tag.name > TagGroup.tag_id -Ref: Tag.name <> Post.id -Ref: UserFavorites.user_id > User.id -Ref: UserFavorites.post_id > Post.id -Ref: UserSource.user_id > User.id -Ref: UserSource.source_id > Source.id -Ref: PostReference.post_id > Post.id -Ref: PostReference.source_id > Source.id - -```` \ No newline at end of file diff --git a/pkg/models/pgModels/orm.go b/pkg/models/orm.go similarity index 95% rename from pkg/models/pgModels/orm.go rename to pkg/models/orm.go index 4fd79bb..ff7bb64 100644 --- a/pkg/models/pgModels/orm.go +++ b/pkg/models/orm.go @@ -1,4 +1,4 @@ -package pgModels +package models import ( gonanoid "github.com/matoous/go-nanoid/v2" diff --git a/pkg/models/pgModels/userSource.go b/pkg/models/pgModels/userSource.go deleted file mode 100644 index 04371fe..0000000 --- a/pkg/models/pgModels/userSource.go +++ /dev/null @@ -1,13 +0,0 @@ -package pgModels - -type UserSource struct { - UserID string `gorm:"primaryKey"` - Source Source `gorm:"foreignKey:ID;references:SourceID"` - SourceID string `gorm:"primaryKey"` - AccountUsername string - AccountID string -} - -func (UserSource) TableName() string { - return "UserSource" -} diff --git a/pkg/models/pgModels/post.go b/pkg/models/post.go similarity index 65% rename from pkg/models/pgModels/post.go rename to pkg/models/post.go index d5ea588..bac8a50 100644 --- a/pkg/models/pgModels/post.go +++ b/pkg/models/post.go @@ -1,13 +1,9 @@ -package pgModels - -import ( - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" -) +package models // Post model type Post struct { BaseModel - Rating models.Rating `gorm:"type:enum('safe','questionable','explicit')"` + Rating Rating `gorm:"type:enum('safe','questionable','explicit')"` Tags []Tag `gorm:"many2many:post_tags;"` Favorites []UserFavorite `gorm:"foreignKey:PostID"` References []PostReference `gorm:"foreignKey:PostID"` diff --git a/pkg/models/pgModels/postReference.go b/pkg/models/postReference.go similarity index 95% rename from pkg/models/pgModels/postReference.go rename to pkg/models/postReference.go index 8ab7797..999e145 100644 --- a/pkg/models/pgModels/postReference.go +++ b/pkg/models/postReference.go @@ -1,4 +1,4 @@ -package pgModels +package models type PostReference struct { PostID string `gorm:"primaryKey"` diff --git a/pkg/models/pgModels/source.go b/pkg/models/source.go similarity index 95% rename from pkg/models/pgModels/source.go rename to pkg/models/source.go index 7159ea5..0860b81 100644 --- a/pkg/models/pgModels/source.go +++ b/pkg/models/source.go @@ -1,4 +1,4 @@ -package pgModels +package models // Source model type Source struct { diff --git a/pkg/models/pgModels/tag.go b/pkg/models/tag.go similarity index 53% rename from pkg/models/pgModels/tag.go rename to pkg/models/tag.go index 7538ac9..583cd78 100644 --- a/pkg/models/pgModels/tag.go +++ b/pkg/models/tag.go @@ -1,14 +1,12 @@ -package pgModels - -import "git.dragse.it/anthrove/otter-space-sdk/pkg/models" +package models // Tag models type Tag struct { - Name string `gorm:"primaryKey"` - Type models.TagType `gorm:"column:tag_type"` - Aliases []TagAlias `gorm:"foreignKey:TagID"` - Groups []TagGroup `gorm:"foreignKey:TagID"` - Posts []Post `gorm:"many2many:post_tags;"` + Name string `gorm:"primaryKey"` + Type TagType `gorm:"column:tag_type"` + Aliases []TagAlias `gorm:"foreignKey:TagID"` + Groups []TagGroup `gorm:"foreignKey:TagID"` + Posts []Post `gorm:"many2many:post_tags;"` } func (Tag) TableName() string { @@ -34,3 +32,8 @@ type TagGroup struct { func (TagGroup) TableName() string { return "TagGroup" } + +type TagsWithFrequency struct { + Frequency int64 `json:"frequency"` + Tags Tag `json:"tags"` +} diff --git a/pkg/models/pgModels/user.go b/pkg/models/user.go similarity index 92% rename from pkg/models/pgModels/user.go rename to pkg/models/user.go index 1120ae7..96dd70e 100644 --- a/pkg/models/pgModels/user.go +++ b/pkg/models/user.go @@ -1,4 +1,4 @@ -package pgModels +package models // User model type User struct { diff --git a/pkg/models/pgModels/userFavorite.go b/pkg/models/userFavorite.go similarity index 69% rename from pkg/models/pgModels/userFavorite.go rename to pkg/models/userFavorite.go index e01093f..1393c61 100644 --- a/pkg/models/pgModels/userFavorite.go +++ b/pkg/models/userFavorite.go @@ -1,4 +1,4 @@ -package pgModels +package models import "time" @@ -11,3 +11,7 @@ type UserFavorite struct { func (UserFavorite) TableName() string { return "UserFavorites" } + +type FavoriteList struct { + Posts []UserFavorite `json:"posts,omitempty"` +} diff --git a/pkg/models/userSource.go b/pkg/models/userSource.go new file mode 100644 index 0000000..97793d6 --- /dev/null +++ b/pkg/models/userSource.go @@ -0,0 +1,14 @@ +package models + +type UserSource struct { + UserID string `gorm:"primaryKey"` + Source Source `gorm:"foreignKey:ID;references:SourceID"` + SourceID string `gorm:"primaryKey"` + ScrapeTimeInterval string + AccountUsername string + AccountID string +} + +func (UserSource) TableName() string { + return "UserSource" +} From b11cfbaa245401fb84baeee9bcac5d35307a029c Mon Sep 17 00:00:00 2001 From: soxx Date: Sat, 22 Jun 2024 22:07:36 +0200 Subject: [PATCH 059/124] refactor(postgres): removed old graph related code Signed-off-by: soxx --- pkg/database/postgres.go | 1 - pkg/models/graphModels/api.go | 20 -------------------- pkg/models/graphModels/post.go | 8 -------- pkg/models/graphModels/relationships.go | 12 ------------ pkg/models/graphModels/source.go | 7 ------- pkg/models/graphModels/tag.go | 6 ------ pkg/models/graphModels/user.go | 8 -------- 7 files changed, 62 deletions(-) delete mode 100644 pkg/models/graphModels/api.go delete mode 100644 pkg/models/graphModels/post.go delete mode 100644 pkg/models/graphModels/relationships.go delete mode 100644 pkg/models/graphModels/source.go delete mode 100644 pkg/models/graphModels/tag.go delete mode 100644 pkg/models/graphModels/user.go diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index ff4eb16..7025a97 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -71,7 +71,6 @@ func (p *postgresqlConnection) AddUserWithRelationToSource(ctx context.Context, } func (p *postgresqlConnection) AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error { - source := utils.GraphConvertSource(anthroveSource) return postgres.CreateSourceNode(ctx, p.db, source) } diff --git a/pkg/models/graphModels/api.go b/pkg/models/graphModels/api.go deleted file mode 100644 index 7683097..0000000 --- a/pkg/models/graphModels/api.go +++ /dev/null @@ -1,20 +0,0 @@ -package graphModels - -type FavoriteRelations struct { - SourcesID string `json:"sources_id"` - Relations AnthrovePostRelationship `json:"relations"` -} - -type FavoritePost struct { - AnthrovePost AnthrovePost `json:"anthrove_post"` - Relations []FavoriteRelations `json:"relations"` -} - -type FavoriteList struct { - Posts []FavoritePost `json:"posts,omitempty"` -} - -type TagsWithFrequency struct { - Frequency int64 `json:"frequency"` - Tags AnthroveTag `json:"tags"` -} diff --git a/pkg/models/graphModels/post.go b/pkg/models/graphModels/post.go deleted file mode 100644 index 28caa38..0000000 --- a/pkg/models/graphModels/post.go +++ /dev/null @@ -1,8 +0,0 @@ -package graphModels - -import "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - -type AnthrovePost struct { - PostID models.AnthrovePostID `json:"post_id"` - Rating models.Rating `json:"rating"` -} diff --git a/pkg/models/graphModels/relationships.go b/pkg/models/graphModels/relationships.go deleted file mode 100644 index 639966f..0000000 --- a/pkg/models/graphModels/relationships.go +++ /dev/null @@ -1,12 +0,0 @@ -package graphModels - -type AnthroveUserRelationship struct { - UserID string `json:"user_id"` - Username string `json:"username"` - ScrapeTimeInterval string `json:"scrape_time_interval"` - Source AnthroveSource `json:"source"` -} -type AnthrovePostRelationship struct { - PostID string `json:"post_id"` - Url string `json:"url"` -} diff --git a/pkg/models/graphModels/source.go b/pkg/models/graphModels/source.go deleted file mode 100644 index 5e3795b..0000000 --- a/pkg/models/graphModels/source.go +++ /dev/null @@ -1,7 +0,0 @@ -package graphModels - -type AnthroveSource struct { - DisplayName string `json:"display_name"` - Domain string `json:"domain"` - Icon string `json:"icon"` -} diff --git a/pkg/models/graphModels/tag.go b/pkg/models/graphModels/tag.go deleted file mode 100644 index 699a1fc..0000000 --- a/pkg/models/graphModels/tag.go +++ /dev/null @@ -1,6 +0,0 @@ -package graphModels - -type AnthroveTag struct { - Name string `json:"name"` - Type string `json:"type"` -} diff --git a/pkg/models/graphModels/user.go b/pkg/models/graphModels/user.go deleted file mode 100644 index 3b74a51..0000000 --- a/pkg/models/graphModels/user.go +++ /dev/null @@ -1,8 +0,0 @@ -package graphModels - -import "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - -type AnthroveUser struct { - UserID models.AnthroveUserID `json:"user_id"` - Relationship []AnthroveUserRelationship `json:"relationship"` -} From 2621eea00c58d549f0c6b1166ec1927bba3ada99 Mon Sep 17 00:00:00 2001 From: soxx Date: Sat, 22 Jun 2024 22:27:38 +0200 Subject: [PATCH 060/124] refactor(postgres): fixed implementation Signed-off-by: soxx --- internal/postgres/post.go | 21 +++++---- internal/postgres/relationships.go | 11 +++-- internal/postgres/tag.go | 2 +- pkg/database/database.go | 6 +-- pkg/database/postgres.go | 72 +++++++++++------------------- 5 files changed, 46 insertions(+), 66 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index d00c08a..bf0fea4 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -5,17 +5,16 @@ import ( "errors" "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) -func CreateAnthrovePostNode(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, anthroveRating models.Rating) error { +func CreateAnthrovePostNode(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error { post := models.Post{ BaseModel: models.BaseModel{ - ID: string(anthrovePostID), + ID: string(anthrovePost.ID), }, - Rating: anthroveRating, + Rating: anthrovePost.Rating, } err := db.WithContext(ctx).Create(&post).Error @@ -24,14 +23,14 @@ func CreateAnthrovePostNode(ctx context.Context, db *gorm.DB, anthrovePostID mod } log.WithFields(log.Fields{ - "anthrove_post_id": anthrovePostID, - "anthrove_post_rating": anthroveRating, + "anthrove_post_id": anthrovePost.ID, + "anthrove_post_rating": anthrovePost.Rating, }).Trace("database: created anthrove post") return nil } -func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID) (bool, error) { +func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID string) (*models.Post, error) { if anthrovePostID == "" { return false, fmt.Errorf("anthrovePostID is required") } @@ -39,9 +38,9 @@ func CheckIfAnthrovePostNodeExistsByAnthroveID(ctx context.Context, db *gorm.DB, return executeCheckQuery(ctx, db, "id = ?", string(anthrovePostID)) } -func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*graphModels.AnthrovePost, bool, error) { - postRef := models.PostReference{} - err := db.WithContext(ctx).Model(&models.PostReference{}).Where("url = ?", sourceURL).First(&postRef).Error +func GetPostBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.Post, bool, 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 errors.Is(err, gorm.ErrRecordNotFound) { @@ -68,7 +67,7 @@ func CheckIfAnthrovePostNodeExistsBySourceURL(ctx context.Context, db *gorm.DB, return &pgPost, true, nil } -func CheckIfAnthrovePostNodeExistsBySourceID(ctx context.Context, db *gorm.DB, sourceID string) (bool, error) { +func GetPostBySourceID(ctx context.Context, db *gorm.DB, sourceID string) (*models.Post, error) { return executeCheckQuery(ctx, db, "source_id = ?", sourceID) } diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index 969e66d..c6d020f 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -3,17 +3,16 @@ package postgres import ( "context" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) -func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { +func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain string, anthrovePostRelationship *models.PostReference) error { var source models.Source var err error // Find the source - err = db.WithContext(ctx).Where("domain = ?", anthroveSourceDomain).First(&source).Error + err = db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&source).Error if err != nil { return err } @@ -22,7 +21,7 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrov err = db.WithContext(ctx).Create(models.PostReference{ PostID: string(anthrovePostID), SourceID: source.ID, - URL: anthrovePostRelationship.Url, + URL: anthrovePostRelationship.URL, }).Error if err != nil { @@ -31,13 +30,13 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrov log.WithFields(log.Fields{ "anthrove_post_id": anthrovePostID, - "anthrove_source_domain": anthroveSourceDomain, + "anthrove_source_domain": sourceDomain, }).Trace("database: created anthrove post to source link") return nil } -func EstablishUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { +func EstablishUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID string, anthrovePostID string) error { userFavorite := models.UserFavorite{ UserID: string(anthroveUserID), PostID: string(anthrovePostID), diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 124742e..03131e7 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -57,7 +57,7 @@ func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.An return nil } -func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) { +func GetTags(ctx context.Context, db *gorm.DB) ([]models.TagsWithFrequency, error) { var tags []models.Tag result := db.WithContext(ctx).Find(&tags) if result.Error != nil { diff --git a/pkg/database/database.go b/pkg/database/database.go index a6c908b..dc95d91 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -43,15 +43,15 @@ type OtterSpace interface { // CheckPostNodeExistsByAnthroveID checks if a post node exists in the OtterSpace database by its Anthrove ID. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. - CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, bool, error) + CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) // CheckPostNodeExistsBySourceURL checks if a post node exists in the OtterSpace database by its source URL. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. - CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, bool, error) + CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) // CheckPostNodeExistsBySourceID checks if a post node exists in the OtterSpace database by its source ID. // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. - CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.Post, bool, error) + CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) // GetUserFavoriteCount retrieves the count of a user's favorite posts from the OtterSpace database. // It returns the count and an error if the operation fails. diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 7025a97..d91f57a 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -6,9 +6,7 @@ import ( "embed" "fmt" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" - "git.dragse.it/anthrove/otter-space-sdk/internal/utils" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" _ "github.com/lib/pq" migrate "github.com/rubenv/sql-migrate" log "github.com/sirupsen/logrus" @@ -70,61 +68,55 @@ func (p *postgresqlConnection) AddUserWithRelationToSource(ctx context.Context, return postgres.CreateUserNodeWithSourceRelation(ctx, p.db, anthroveUserID, sourceDomain, userID, userID) } -func (p *postgresqlConnection) AddSource(ctx context.Context, anthroveSource *graphModels.AnthroveSource) error { - return postgres.CreateSourceNode(ctx, p.db, source) +func (p *postgresqlConnection) AddSource(ctx context.Context, anthroveSource *models.Source) error { + return postgres.CreateSourceNode(ctx, p.db, anthroveSource) } -func (p *postgresqlConnection) AddPost(ctx context.Context, anthrovePost *graphModels.AnthrovePost) error { - return postgres.CreateAnthrovePostNode(ctx, p.db, anthrovePost.PostID, anthrovePost.Rating) +func (p *postgresqlConnection) AddPost(ctx context.Context, anthrovePost *models.Post) error { + return postgres.CreateAnthrovePostNode(ctx, p.db, anthrovePost) } -func (p *postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *graphModels.AnthroveTag) error { - return postgres.CreateTagNodeWitRelation(ctx, p.db, anthrovePostID, utils.GraphConvertTag(anthroveTag)) +func (p *postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error { + return postgres.CreateTagNodeWitRelation(ctx, p.db, anthrovePostID, anthroveTag) } -func (p *postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *graphModels.AnthrovePostRelationship) error { - return postgres.EstablishAnthrovePostToSourceLink(ctx, p.db, anthrovePostID, anthroveSourceDomain, anthrovePostRelationship) +func (p *postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain string, anthrovePostRelationship *models.PostReference) error { + return postgres.EstablishAnthrovePostToSourceLink(ctx, p.db, anthrovePostID, sourceDomain, anthrovePostRelationship) } -func (p *postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *graphModels.AnthroveUser, anthrovePost *graphModels.AnthrovePost) error { - return postgres.EstablishUserToPostLink(ctx, p.db, anthroveUser.UserID, anthrovePost.PostID) +func (p *postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error { + return postgres.EstablishUserToPostLink(ctx, p.db, anthroveUser.ID, anthrovePost.ID) } func (p *postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { return postgres.CheckUserToPostLink(ctx, p.db, anthroveUserID, models.AnthrovePostID(sourcePostID)) } -func (p *postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *graphModels.AnthrovePost) (*graphModels.AnthrovePost, bool, error) { - exists, err := postgres.CheckIfAnthrovePostNodeExistsByAnthroveID(ctx, p.db, anthrovePost.PostID) - return anthrovePost, exists, err +func (p *postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) { + return postgres.GetPostByAnthroveID(ctx, p.db, anthrovePost.ID) } -// CheckPostNodeExistsBySourceURL NOT WORKING! TODO! -func (p *postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*graphModels.AnthrovePost, bool, error) { - post, exists, err := postgres.CheckIfAnthrovePostNodeExistsBySourceURL(ctx, p.db, sourceUrl) - return post, exists, err +func (p *postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) { + return postgres.GetPostBySourceURL(ctx, p.db, sourceUrl) } -// CheckPostNodeExistsBySourceID NOT WORKING! TODO! -func (p *postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*graphModels.AnthrovePost, bool, error) { - var post graphModels.AnthrovePost - exists, err := postgres.CheckIfAnthrovePostNodeExistsBySourceID(ctx, p.db, sourcePostID) - return &post, exists, err +func (p *postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) { + return postgres.GetPostBySourceID(ctx, p.db, sourcePostID) } func (p *postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { return postgres.GetUserFavoritesCount(ctx, p.db, anthroveUserID) } -func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { +func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) { return postgres.GetUserSourceLink(ctx, p.db, anthroveUserID) } -func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { +func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) { return postgres.GetSpecifiedUserSourceLink(ctx, p.db, anthroveUserID, sourceDisplayName) } -func (p *postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { +func (p *postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.User, error) { return postgres.GetAnthroveUser(ctx, p.db, anthroveUserID) } @@ -132,34 +124,24 @@ func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]mod return postgres.GetAllAnthroveUserIDs(ctx, p.db) } -func (p *postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { +func (p *postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { return postgres.GetUserFavoriteNodeWithPagination(ctx, p.db, anthroveUserID, skip, limit) } -func (p *postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { +func (p *postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { return postgres.GetUserTagNodeWitRelationToFavedPosts(ctx, p.db, anthroveUserID) } -func (p *postgresqlConnection) GetAllTags(ctx context.Context) ([]graphModels.TagsWithFrequency, error) { - tags, err := postgres.GetTags(ctx, p.db) - - return utils.ConvertToTagsWithFrequency(tags), err +func (p *postgresqlConnection) GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) { + return postgres.GetTags(ctx, p.db) } -func (p *postgresqlConnection) GetAllSources(ctx context.Context) ([]graphModels.AnthroveSource, error) { - var anthroveSources []graphModels.AnthroveSource - source, err := postgres.GetAllSourceNodes(ctx, p.db) - - for _, v := range source { - anthroveSource := utils.PostgresConvertToAnthroveSource(&v) - anthroveSources = append(anthroveSources, *anthroveSource) - } - return nil, err +func (p *postgresqlConnection) GetAllSources(ctx context.Context) ([]models.Source, error) { + return postgres.GetAllSourceNodes(ctx, p.db) } -func (p *postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*graphModels.AnthroveSource, error) { - source, err := postgres.GetSourceNodesByURL(ctx, p.db, sourceUrl) - return utils.PostgresConvertToAnthroveSource(source), err +func (p *postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*models.Source, error) { + return postgres.GetSourceNodesByURL(ctx, p.db, sourceUrl) } func (p *postgresqlConnection) migrateDatabase(connectionString string) error { From 78145fe02ab2d9451d7da6c056238660ea2305a3 Mon Sep 17 00:00:00 2001 From: soxx Date: Sat, 22 Jun 2024 22:28:29 +0200 Subject: [PATCH 061/124] refactor(postgres): removed old docs Signed-off-by: soxx --- pkg/database/database.go | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/pkg/database/database.go b/pkg/database/database.go index dc95d91..7977186 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -5,86 +5,46 @@ import ( "git.dragse.it/anthrove/otter-space-sdk/pkg/models" ) -// OtterSpace provides an interface for interacting with the OtterSpace API. -// It includes methods for connecting to the API, adding and linking users, posts, and sources, -// and retrieving information about users and posts. type OtterSpace interface { - // Connect sets up a connection to the OtterSpace API endpoint using the provided username and password. - // It returns an error if the connection cannot be established. Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error - // AddUserWithRelationToSource adds a new user to the OtterSpace database and associates them with a source. - // It returns the newly created user and an error if the operation fails. AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error - // AddSource adds a new source to the OtterSpace database. - // It returns an error if the operation fails. AddSource(ctx context.Context, anthroveSource *models.Source) error - // AddPost adds a new post to the OtterSpace database. - // It returns an error if the operation fails. AddPost(ctx context.Context, anthrovePost *models.Post) error - // AddTagWithRelationToPost adds a new tag to the OtterSpace database and associates it with a post. - // It returns an error if the operation fails. AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error - // LinkPostWithSource establishes a link between a post and a source in the OtterSpace database. - // It returns an error if the operation fails. LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.PostReference) error - // LinkUserWithPost establishes a link between a user and a post in the OtterSpace database. - // It returns an error if the operation fails. LinkUserWithPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error - // CheckUserPostLink checks if a link between a user and a post exists in the OtterSpace database. - // It returns true if the link exists, false otherwise, and an error if the operation fails. CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) - // CheckPostNodeExistsByAnthroveID checks if a post node exists in the OtterSpace database by its Anthrove ID. - // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) - // CheckPostNodeExistsBySourceURL checks if a post node exists in the OtterSpace database by its source URL. - // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) - // CheckPostNodeExistsBySourceID checks if a post node exists in the OtterSpace database by its source ID. - // It returns the post if it exists, a boolean indicating whether the post was found, and an error if the operation fails. CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) - // GetUserFavoriteCount retrieves the count of a user's favorite posts from the OtterSpace database. - // It returns the count and an error if the operation fails. GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) - // GetUserSourceLinks retrieves the links between a user and sources in the OtterSpace database. - // It returns a map of source domains to user-source relationships, and an error if the operation fails. GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) - // GetSpecifiedUserSourceLink GetUserSourceLinks retrieves the links between a user and a specific source in the OtterSpace database. - // It returns a map of source domains to user-source relationships, and an error if the operation fails. GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) - // GetAnthroveUser retrieves a user from the OtterSpace database by their ID. - // It returns the user and an error if the operation fails. GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.User, error) - // GetAllAnthroveUserIDs retrieves all user IDs from the OtterSpace database. - // It returns a slice of user IDs and an error if the operation fails. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) - // GetUserFavoritePostsWithPagination gets all user favorites with relation and sources for the given user GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) - // GetUserTagsTroughFavedPosts returns a list of Tags that the user hs favorites through a post GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) - // GetAllTags returns a list of Tags that the user hs favorites through a post GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) - // GetAllSources returns a list of Sources in the database GetAllSources(ctx context.Context) ([]models.Source, error) - // GetSourceByURL returns the Source Node based on the URL GetSourceByURL(ctx context.Context, sourceUrl string) (*models.Source, error) } From 55296d9a95b6ca4de03f12e99e2a215dc43ed6e2 Mon Sep 17 00:00:00 2001 From: soxx Date: Sat, 22 Jun 2024 22:30:03 +0200 Subject: [PATCH 062/124] refactor(postgres): renamed functions to be more clear Signed-off-by: soxx --- pkg/database/database.go | 6 +++--- pkg/database/postgres.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/database/database.go b/pkg/database/database.go index 7977186..bc31c17 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -22,11 +22,11 @@ type OtterSpace interface { CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) - CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) + GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) - CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) + GetPostBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) - CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) + GetPostBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index d91f57a..f4a2750 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -92,15 +92,15 @@ func (p *postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUs return postgres.CheckUserToPostLink(ctx, p.db, anthroveUserID, models.AnthrovePostID(sourcePostID)) } -func (p *postgresqlConnection) CheckPostNodeExistsByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) { +func (p *postgresqlConnection) GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) { return postgres.GetPostByAnthroveID(ctx, p.db, anthrovePost.ID) } -func (p *postgresqlConnection) CheckPostNodeExistsBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) { +func (p *postgresqlConnection) GetPostBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) { return postgres.GetPostBySourceURL(ctx, p.db, sourceUrl) } -func (p *postgresqlConnection) CheckPostNodeExistsBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) { +func (p *postgresqlConnection) GetPostBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) { return postgres.GetPostBySourceID(ctx, p.db, sourcePostID) } From b28891f3835b82e603428380ba934f37ed2e2a24 Mon Sep 17 00:00:00 2001 From: soxx Date: Sat, 22 Jun 2024 23:23:23 +0200 Subject: [PATCH 063/124] refactor(postgres): fixed any IDE errors Signed-off-by: soxx --- internal/postgres/user.go | 108 ++++++++------------------------- internal/postgres/user_test.go | 6 +- pkg/database/database.go | 22 ++++++- pkg/database/postgres.go | 6 +- pkg/models/userFavorite.go | 2 +- 5 files changed, 50 insertions(+), 94 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 2c9e56e..c7b0586 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) @@ -111,9 +110,9 @@ func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID mode return count, nil } -func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (map[string]graphModels.AnthroveUserRelationship, error) { +func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) { var userSources []models.UserSource - userSourceMap := make(map[string]graphModels.AnthroveUserRelationship) + userSourceMap := make(map[string]models.UserSource) err := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error if err != nil { @@ -133,10 +132,10 @@ func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.A return nil, err } - userSourceMap[source.DisplayName] = graphModels.AnthroveUserRelationship{ - UserID: userSource.AccountID, - Username: userSource.AccountUsername, - Source: graphModels.AnthroveSource{ + userSourceMap[source.DisplayName] = models.UserSource{ + UserID: userSource.AccountID, + AccountUsername: userSource.AccountUsername, + Source: models.Source{ DisplayName: source.DisplayName, Domain: source.Domain, Icon: source.Icon, @@ -151,13 +150,13 @@ func GetUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.A return userSourceMap, nil } -func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]graphModels.AnthroveUserRelationship, error) { +func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) { if anthroveUserID == "" || sourceDisplayName == "" { return nil, fmt.Errorf("anthroveUserID or sourceDisplayName is empty") } var userSources []models.UserSource - userSourceMap := make(map[string]graphModels.AnthroveUserRelationship) + userSourceMap := make(map[string]models.UserSource) err := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("display_name = ?", sourceDisplayName)).Where("user_id = ?", string(anthroveUserID)).First(&userSources).Error if err != nil { @@ -178,10 +177,10 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID return nil, err } - userSourceMap[source.DisplayName] = graphModels.AnthroveUserRelationship{ - UserID: userSource.AccountID, - Username: userSource.AccountUsername, - Source: graphModels.AnthroveSource{ + userSourceMap[source.DisplayName] = models.UserSource{ + UserID: userSource.AccountID, + AccountUsername: userSource.AccountUsername, + Source: models.Source{ DisplayName: source.DisplayName, Domain: source.Domain, Icon: source.Icon, @@ -197,62 +196,6 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID return userSourceMap, nil } -func GetAnthroveUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) (*graphModels.AnthroveUser, error) { - - if anthroveUserID == "" { - return nil, fmt.Errorf("anthroveUserID cannot be empty") - } - - var user models.User - var userSources []models.UserSource - anthroveUser := &graphModels.AnthroveUser{ - UserID: anthroveUserID, - } - - err := db.WithContext(ctx).First(&user, "id = ?", string(anthroveUserID)).Error - if err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Error("database: failed to get user") - return nil, err - } - - err = db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error - if err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Error("database: failed to get user sources") - return nil, err - } - - for _, userSource := range userSources { - var source models.Source - err = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error - if err != nil { - log.WithFields(log.Fields{ - "source_id": userSource.SourceID, - }).Error("database: failed to get source") - return nil, err - } - - anthroveUser.Relationship = append(anthroveUser.Relationship, graphModels.AnthroveUserRelationship{ - UserID: userSource.AccountID, - Username: userSource.AccountUsername, - Source: graphModels.AnthroveSource{ - DisplayName: source.DisplayName, - Domain: source.Domain, - Icon: source.Icon, - }, - }) - } - - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Trace("database: got anthrove user") - - return anthroveUser, nil -} - func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveUserID, error) { var users []models.User var userIDs []models.AnthroveUserID @@ -274,9 +217,9 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU return userIDs, nil } -func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*graphModels.FavoriteList, error) { +func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { var userFavorites []models.UserFavorite - var favoritePosts []graphModels.FavoritePost + var favoritePosts []models.Post err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error if err != nil { @@ -298,12 +241,11 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthrov return nil, err } - favoritePosts = append(favoritePosts, graphModels.FavoritePost{ - AnthrovePost: graphModels.AnthrovePost{ - PostID: models.AnthrovePostID(post.ID), - Rating: post.Rating, - }, - }) + favoritePosts = append(favoritePosts, + models.Post{ + BaseModel: models.BaseModel{ID: post.ID}, + Rating: post.Rating, + }) } log.WithFields(log.Fields{ @@ -311,10 +253,10 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthrov "anthrove_user_fav_count": len(favoritePosts), }).Trace("database: got all anthrove user favorites") - return &graphModels.FavoriteList{Posts: favoritePosts}, nil + return &models.FavoriteList{Posts: favoritePosts}, nil } -func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]graphModels.TagsWithFrequency, error) { +func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { var userFavorites []models.UserFavorite err := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites).Error if err != nil { @@ -346,13 +288,13 @@ func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, ant } } - var tagsWithFrequency []graphModels.TagsWithFrequency + var tagsWithFrequency []models.TagsWithFrequency for data, frequency := range tagFrequency { - tagsWithFrequency = append(tagsWithFrequency, graphModels.TagsWithFrequency{ + tagsWithFrequency = append(tagsWithFrequency, models.TagsWithFrequency{ Frequency: int64(frequency), - Tags: graphModels.AnthroveTag{ + Tags: models.Tag{ Name: data.name, - Type: data.typeName, + Type: models.TagType(data.typeName), }, }) } diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 6beec7b..b0742c5 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -795,13 +795,13 @@ func TestGetUserSourceLink(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetUserSourceLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) + got, err := GetUserSourceLinks(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) if (err != nil) != tt.wantErr { - t.Errorf("GetUserSourceLink() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetUserSourceLinks() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetUserSourceLink() got = %v, want %v", got, tt.want) + t.Errorf("GetUserSourceLinks() got = %v, want %v", got, tt.want) } }) } diff --git a/pkg/database/database.go b/pkg/database/database.go index bc31c17..76269bf 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -6,45 +6,63 @@ import ( ) type OtterSpace interface { + // Connect establishes a connection to the database. Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error + // AddUserWithRelationToSource adds a user with a relation to a source. AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error + // AddSource adds a new source to the database. AddSource(ctx context.Context, anthroveSource *models.Source) error + // AddPost adds a new post to the database. AddPost(ctx context.Context, anthrovePost *models.Post) error + // AddTagWithRelationToPost adds a tag with a relation to a post. AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error + // LinkPostWithSource links a post with a source. LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.PostReference) error + // LinkUserWithPost links a user with a post. LinkUserWithPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error + // CheckUserPostLink checks if a user-post link exists. CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) + // GetPostByAnthroveID retrieves a post by its Anthrove ID. GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) + // GetPostBySourceURL retrieves a post by its source URL. GetPostBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) + // GetPostBySourceID retrieves a post by its source ID. GetPostBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) + // GetUserFavoriteCount retrieves the count of a user's favorites. GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) + // GetUserSourceLinks retrieves the source links of a user. GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) + // GetSpecifiedUserSourceLink retrieves a specified source link of a user. GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) - GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.User, error) - + // GetAllAnthroveUserIDs retrieves all Anthrove user IDs. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) + // GetUserFavoritePostsWithPagination retrieves a user's favorite posts with pagination. GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) + // GetUserTagsTroughFavedPosts retrieves a user's tags through their favorited posts. GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) + // GetAllTags retrieves all tags. GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) + // GetAllSources retrieves all sources. GetAllSources(ctx context.Context) ([]models.Source, error) + // GetSourceByURL retrieves a source by its URL. GetSourceByURL(ctx context.Context, sourceUrl string) (*models.Source, error) } diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index f4a2750..ac996c0 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -109,17 +109,13 @@ func (p *postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthrov } func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) { - return postgres.GetUserSourceLink(ctx, p.db, anthroveUserID) + return postgres.GetUserSourceLinks(ctx, p.db, anthroveUserID) } func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) { return postgres.GetSpecifiedUserSourceLink(ctx, p.db, anthroveUserID, sourceDisplayName) } -func (p *postgresqlConnection) GetAnthroveUser(ctx context.Context, anthroveUserID models.AnthroveUserID) (*models.User, error) { - return postgres.GetAnthroveUser(ctx, p.db, anthroveUserID) -} - func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { return postgres.GetAllAnthroveUserIDs(ctx, p.db) } diff --git a/pkg/models/userFavorite.go b/pkg/models/userFavorite.go index 1393c61..8ccd106 100644 --- a/pkg/models/userFavorite.go +++ b/pkg/models/userFavorite.go @@ -13,5 +13,5 @@ func (UserFavorite) TableName() string { } type FavoriteList struct { - Posts []UserFavorite `json:"posts,omitempty"` + Posts []Post `json:"posts,omitempty"` } From 9471941e025bc268f29fe648236e59ce227b57b0 Mon Sep 17 00:00:00 2001 From: soxx Date: Sat, 22 Jun 2024 23:25:06 +0200 Subject: [PATCH 064/124] refactor(postgres): fixed any IDE errors Signed-off-by: soxx --- internal/postgres/tag.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 03131e7..124742e 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -57,7 +57,7 @@ func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.An return nil } -func GetTags(ctx context.Context, db *gorm.DB) ([]models.TagsWithFrequency, error) { +func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) { var tags []models.Tag result := db.WithContext(ctx).Find(&tags) if result.Error != nil { From bb7cb23c2a468253661dc99c428d6a75fde7cbd1 Mon Sep 17 00:00:00 2001 From: soxx Date: Sat, 22 Jun 2024 23:25:28 +0200 Subject: [PATCH 065/124] refactor(postgres): Refactor post retrieval functions and remove unnecessary code in tag and user creation Signed-off-by: soxx --- internal/postgres/post.go | 56 +++++++++++++-------------------------- internal/postgres/tag.go | 6 ----- internal/postgres/user.go | 15 +---------- pkg/models/userSource.go | 1 + 4 files changed, 21 insertions(+), 57 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index bf0fea4..32ee5af 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -32,60 +32,42 @@ func CreateAnthrovePostNode(ctx context.Context, db *gorm.DB, anthrovePost *mode func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID string) (*models.Post, error) { if anthrovePostID == "" { - return false, fmt.Errorf("anthrovePostID is required") + return nil, fmt.Errorf("anthrovePostID is required") } - return executeCheckQuery(ctx, db, "id = ?", string(anthrovePostID)) + var post models.Post + err := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID).Error + if err != nil { + return nil, err + } + + return &post, nil } -func GetPostBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.Post, bool, error) { +func GetPostBySourceURL(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 errors.Is(err, gorm.ErrRecordNotFound) { - return nil, false, nil + return nil, nil } - return nil, false, err + return nil, err } - var post models.Post - err = db.WithContext(ctx).First(&post, "id = ?", postRef.PostID).Error - - if err != nil { - return nil, false, err - } - - pgPost := graphModels.AnthrovePost{ - PostID: models.AnthrovePostID(post.ID), - Rating: post.Rating, - } - - //TODO Now test it! :D - // Naaa - // D: - return &pgPost, true, nil + return &post, nil } func GetPostBySourceID(ctx context.Context, db *gorm.DB, sourceID string) (*models.Post, error) { - return executeCheckQuery(ctx, db, "source_id = ?", sourceID) -} + 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 -func executeCheckQuery(ctx context.Context, db *gorm.DB, query string, args ...interface{}) (bool, error) { - var count int64 - - err := db.WithContext(ctx).Model(&models.Post{}).Where(query, args...).Count(&count).Error if err != nil { - return false, err + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err } - exists := count > 0 - - log.WithFields(log.Fields{ - "query": query, - "args": args, - "exists": exists, - }).Trace("database: executed check query") - - return exists, nil + return &post, nil } diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 124742e..40e0f68 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -30,12 +30,6 @@ func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.An return fmt.Errorf("PostID is empty") } - resultTag := db.WithContext(ctx).Where(tag).FirstOrCreate(tag) - - if resultTag.Error != nil { - return resultTag.Error - } - pgPost := models.Post{ BaseModel: models.BaseModel{ ID: string(PostID), diff --git a/internal/postgres/user.go b/internal/postgres/user.go index c7b0586..8afd07f 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -37,19 +37,6 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthrove return fmt.Errorf("anthroveUserID cannot be empty") } - user := models.User{ - BaseModel: models.BaseModel{ - ID: string(anthroveUserID), - }, - } - - if err := db.WithContext(ctx).FirstOrCreate(&user).Error; err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Error("database: failed to find or create user") - return err - } - source := models.Source{ Domain: sourceDomain, } @@ -62,7 +49,7 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthrove } userSource := models.UserSource{ - UserID: user.ID, + User: models.User{BaseModel: models.BaseModel{ID: string(anthroveUserID)}}, SourceID: source.ID, AccountUsername: username, AccountID: userID, diff --git a/pkg/models/userSource.go b/pkg/models/userSource.go index 97793d6..59788a1 100644 --- a/pkg/models/userSource.go +++ b/pkg/models/userSource.go @@ -1,6 +1,7 @@ package models type UserSource struct { + User User `gorm:"foreignKey:ID;references:UserID"` UserID string `gorm:"primaryKey"` Source Source `gorm:"foreignKey:ID;references:SourceID"` SourceID string `gorm:"primaryKey"` From 7842976f4b4a3cb7eda14aca5c6d22f207da269c Mon Sep 17 00:00:00 2001 From: soxx Date: Sun, 23 Jun 2024 01:18:23 +0200 Subject: [PATCH 066/124] test(postgres): fixed the tests & also squashed some bugs Signed-off-by: soxx --- internal/postgres/post.go | 11 +- internal/postgres/post_test.go | 312 +++++++++++++++--- internal/postgres/relationships.go | 8 +- internal/postgres/relationships_test.go | 272 ++++++++------- internal/postgres/source_test.go | 10 +- internal/postgres/tag.go | 8 +- internal/postgres/tag_test.go | 20 +- internal/postgres/user.go | 23 +- internal/postgres/user_test.go | 295 +++++------------ .../migrations/001_inital_database.sql | 3 +- pkg/database/postgres.go | 2 +- 11 files changed, 556 insertions(+), 408 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 32ee5af..079be3d 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -9,15 +9,8 @@ import ( "gorm.io/gorm" ) -func CreateAnthrovePostNode(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error { - post := models.Post{ - BaseModel: models.BaseModel{ - ID: string(anthrovePost.ID), - }, - Rating: anthrovePost.Rating, - } - - err := db.WithContext(ctx).Create(&post).Error +func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error { + err := db.WithContext(ctx).Create(&anthrovePost).Error if err != nil { return err } diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index 20444e7..87d2690 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -2,6 +2,7 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" _ "github.com/lib/pq" @@ -19,11 +20,24 @@ func TestCreateAnthrovePostNode(t *testing.T) { } defer container.Terminate(ctx) + // Setup Tests + + validPost := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + invalidPost := &models.Post{ + Rating: "error", + } + + // Test type args struct { - ctx context.Context - db *gorm.DB - anthrovePostID models.AnthrovePostID - anthroveRating models.Rating + ctx context.Context + db *gorm.DB + anthrovePost *models.Post } tests := []struct { name string @@ -33,34 +47,32 @@ func TestCreateAnthrovePostNode(t *testing.T) { { name: "Test 1: Valid AnthrovePostID and Rating", args: args{ - ctx: context.Background(), - db: gormDB, - anthrovePostID: "1234", - anthroveRating: models.Rating("safe"), + ctx: context.Background(), + db: gormDB, + anthrovePost: validPost, }, wantErr: false, }, { - name: "Test 2: Invalid AnthrovePostID and Rating", + name: "Test 2: Invalid Rating", args: args{ - ctx: context.Background(), - db: gormDB, - anthrovePostID: "", - anthroveRating: "a4dsa4d", + ctx: context.Background(), + db: gormDB, + anthrovePost: invalidPost, }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CreateAnthrovePostNode(tt.args.ctx, tt.args.db, tt.args.anthrovePostID, tt.args.anthroveRating); (err != nil) != tt.wantErr { - t.Errorf("CreateAnthrovePostNode() error = %v, wantErr %v", err, tt.wantErr) + if err := CreatePost(tt.args.ctx, tt.args.db, tt.args.anthrovePost); (err != nil) != tt.wantErr { + t.Errorf("CreatePost() error = %v, wantErr %v", err, tt.wantErr) } }) } } -func TestCheckIfAnthrovePostNodeExistsByAnthroveID(t *testing.T) { +func TestGetPostByAnthroveID(t *testing.T) { // Setup trow away container ctx := context.Background() container, gormDB, err := test.StartPostgresContainer(ctx) @@ -69,68 +81,284 @@ func TestCheckIfAnthrovePostNodeExistsByAnthroveID(t *testing.T) { } defer container.Terminate(ctx) - // Setup Test + // Setup Tests - err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = CreatePost(ctx, gormDB, post) if err != nil { - t.Fatal(err) + t.Fatal("Could not create post", err) } // Test - type args struct { ctx context.Context db *gorm.DB - anthrovePostID models.AnthrovePostID + anthrovePostID string } tests := []struct { name string args args - want bool + want *models.Post wantErr bool }{ { - name: "Test 1: Valid AnthroveID", + name: "Test 1: Valid anthrovePostID", + args: args{ + ctx: ctx, + db: gormDB, + anthrovePostID: post.ID, + }, + want: post, + wantErr: false, + }, + { + name: "Test 2: Invalid anthrovePostID", args: args{ ctx: ctx, db: gormDB, anthrovePostID: "1234", }, - want: true, - wantErr: false, + want: nil, + wantErr: true, }, { - name: "Test 2: Invalid AnthroveID", - args: args{ - ctx: ctx, - db: gormDB, - anthrovePostID: "123456", - }, - want: false, - wantErr: false, - }, - { - name: "Test 3: No AnthroveID", + name: "Test 3: No anthrovePostID", args: args{ ctx: ctx, db: gormDB, anthrovePostID: "", }, - want: false, + want: nil, wantErr: true, }, } - for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := CheckIfAnthrovePostNodeExistsByAnthroveID(tt.args.ctx, tt.args.db, tt.args.anthrovePostID) + got, err := GetPostByAnthroveID(tt.args.ctx, tt.args.db, tt.args.anthrovePostID) if (err != nil) != tt.wantErr { - t.Errorf("CheckIfAnthrovePostNodeExistsByAnthroveID() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetPostByAnthroveID() error = %v, wantErr %v", err, tt.wantErr) return } - if got != tt.want { - t.Errorf("CheckIfAnthrovePostNodeExistsByAnthroveID() got = %v, want %v", got, tt.want) + if !checkPost(got, tt.want) { + t.Errorf("GetPostByAnthroveID() got = %v, want %v", got, tt.want) } }) } } + +func TestGetPostBySourceURL(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Tests + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal("Could not create post", err) + } + + source := models.Source{ + BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.net/icon.ico", + } + + err = CreateSourceNode(ctx, gormDB, &source) + if err != nil { + t.Fatal("Could not create source", err) + } + + err = EstablishAnthrovePostToSourceLink(ctx, gormDB, post.ID, source.Domain) + if err != nil { + t.Fatal("Could not create source reference", err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + sourceURL string + } + tests := []struct { + name string + args args + want *models.Post + wantErr bool + }{ + { + name: "Test 1: Valid sourceURL", + args: args{ + ctx: ctx, + db: gormDB, + sourceURL: source.Domain, + }, + want: post, + wantErr: false, + }, + { + name: "Test 2: Invalid sourceURL", + args: args{ + ctx: ctx, + db: gormDB, + sourceURL: "1234", + }, + want: nil, + wantErr: false, + }, + { + name: "Test 3: No sourceURL", + args: args{ + ctx: ctx, + db: gormDB, + sourceURL: "", + }, + want: nil, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetPostBySourceURL(tt.args.ctx, tt.args.db, tt.args.sourceURL) + if (err != nil) != tt.wantErr { + t.Errorf("GetPostBySourceURL() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkPost(got, tt.want) { + t.Errorf("GetPostBySourceURL() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetPostBySourceID(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Tests + + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal("Could not create post", err) + } + + source := models.Source{ + BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.net/icon.ico", + } + + err = CreateSourceNode(ctx, gormDB, &source) + if err != nil { + t.Fatal("Could not create source", err) + } + + err = EstablishAnthrovePostToSourceLink(ctx, gormDB, post.ID, source.Domain) + if err != nil { + t.Fatal("Could not create source reference", err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + sourceID string + } + + tests := []struct { + name string + args args + want *models.Post + wantErr bool + }{ + { + name: "Test 1: Valid sourceID", + args: args{ + ctx: ctx, + db: gormDB, + sourceID: source.ID, + }, + want: post, + wantErr: false, + }, + { + name: "Test 2: Invalid sourceID", + args: args{ + ctx: ctx, + db: gormDB, + sourceID: "1234", + }, + want: nil, + wantErr: false, + }, + { + name: "Test 3: No sourceID", + args: args{ + ctx: ctx, + db: gormDB, + sourceID: "", + }, + want: nil, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetPostBySourceID(tt.args.ctx, tt.args.db, tt.args.sourceID) + if (err != nil) != tt.wantErr { + t.Errorf("GetPostBySourceID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkPost(got, tt.want) { + t.Errorf("GetPostBySourceID() got = %v, want %v", got, tt.want) + } + }) + } +} + +func checkPost(got *models.Post, want *models.Post) bool { + + if got == nil { + return true + } + + if got.ID != want.ID { + return false + } + + if got.Rating != want.Rating { + return false + } + + return true +} diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index c6d020f..7f319e0 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -7,7 +7,7 @@ import ( "gorm.io/gorm" ) -func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain string, anthrovePostRelationship *models.PostReference) error { +func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID string, sourceDomain string) error { var source models.Source var err error @@ -19,9 +19,9 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrov // Establish the relationship err = db.WithContext(ctx).Create(models.PostReference{ - PostID: string(anthrovePostID), + PostID: anthrovePostID, SourceID: source.ID, - URL: anthrovePostRelationship.URL, + URL: sourceDomain, }).Error if err != nil { @@ -55,7 +55,7 @@ func EstablishUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID st return nil } -func CheckUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { +func CheckUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID string, anthrovePostID string) (bool, error) { var count int64 err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count).Error if err != nil { diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go index b96a5f3..7d2bc56 100644 --- a/internal/postgres/relationships_test.go +++ b/internal/postgres/relationships_test.go @@ -2,13 +2,14 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" "testing" ) -func TestEstablishAnthrovePostToSourceLink(t *testing.T) { +func TestCheckUserToPostLink(t *testing.T) { // Setup trow away container ctx := context.Background() @@ -19,8 +20,118 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { defer container.Terminate(ctx) // Setup Test + err = CreateUser(ctx, gormDB, "1") + if err != nil { + t.Fatal(err) + } - err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal(err) + } + + err = EstablishUserToPostLink(ctx, gormDB, "1", post.ID) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID string + anthrovePostID string + } + tests := []struct { + name string + args args + want bool + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveUserID and AnthrovePostID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + anthrovePostID: post.ID, + }, + want: true, + wantErr: false, + }, + { + name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + anthrovePostID: "qadw", + }, + want: false, + wantErr: false, + }, + { + name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "123", + anthrovePostID: post.ID, + }, + want: false, + wantErr: false, + }, + { + name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "123", + anthrovePostID: "123456", + }, + want: false, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := CheckUserToPostLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) + if (err != nil) != tt.wantErr { + t.Errorf("CheckUserToPostLink() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("CheckUserToPostLink() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestEstablishAnthrovePostToSourceLink(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = CreatePost(ctx, gormDB, post) if err != nil { t.Fatal(err) } @@ -36,12 +147,12 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { } // Test - type args struct { - ctx context.Context - db *gorm.DB - anthrovePostID models.AnthrovePostID - anthroveSourceDomain string + ctx context.Context + db *gorm.DB + anthrovePostID string + sourceDomain string + anthrovePostRelationship *models.PostReference } tests := []struct { name string @@ -51,47 +162,47 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { { name: "Test 1: Valid AnthrovePostID and anthroveSourceDomain", args: args{ - ctx: ctx, - db: gormDB, - anthrovePostID: "1234", - anthroveSourceDomain: "e621.net", + ctx: ctx, + db: gormDB, + anthrovePostID: post.ID, + sourceDomain: "e621.net", }, wantErr: false, }, { name: "Test 2: Invalid AnthrovePostID and Valid anthroveSourceDomain", args: args{ - ctx: ctx, - db: gormDB, - anthrovePostID: "123456", - anthroveSourceDomain: "e621.net", + ctx: ctx, + db: gormDB, + anthrovePostID: "123456", + sourceDomain: "e621.net", }, wantErr: true, }, { name: "Test 3: Invalid anthroveSourceDomain and Valid AnthrovePostID", args: args{ - ctx: ctx, - db: gormDB, - anthrovePostID: "1234", - anthroveSourceDomain: "fa.banana", + ctx: ctx, + db: gormDB, + anthrovePostID: "1234", + sourceDomain: "fa.banana", }, wantErr: true, }, { name: "Test 4: Invalid anthroveSourceDomain and Invalid AnthrovePostID", args: args{ - ctx: ctx, - db: gormDB, - anthrovePostID: "696969", - anthroveSourceDomain: "hehe.funny.number", + ctx: ctx, + db: gormDB, + anthrovePostID: "696969", + sourceDomain: "hehe.funny.number", }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := EstablishAnthrovePostToSourceLink(tt.args.ctx, tt.args.db, tt.args.anthrovePostID, tt.args.anthroveSourceDomain); (err != nil) != tt.wantErr { + if err := EstablishAnthrovePostToSourceLink(tt.args.ctx, tt.args.db, tt.args.anthrovePostID, tt.args.sourceDomain); (err != nil) != tt.wantErr { t.Errorf("EstablishAnthrovePostToSourceLink() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -113,7 +224,14 @@ func TestEstablishUserToPostLink(t *testing.T) { t.Fatal(err) } - err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = CreatePost(ctx, gormDB, post) if err != nil { t.Fatal(err) } @@ -122,8 +240,8 @@ func TestEstablishUserToPostLink(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveUserID models.AnthroveUserID - anthrovePostID models.AnthrovePostID + anthroveUserID string + anthrovePostID string } tests := []struct { name string @@ -136,7 +254,7 @@ func TestEstablishUserToPostLink(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - anthrovePostID: "1234", + anthrovePostID: post.ID, }, wantErr: false, }, @@ -179,101 +297,3 @@ func TestEstablishUserToPostLink(t *testing.T) { }) } } - -func TestCheckUserToPostLink(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - err = CreateUser(ctx, gormDB, "1") - if err != nil { - t.Fatal(err) - } - - err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") - if err != nil { - t.Fatal(err) - } - - err = EstablishUserToPostLink(ctx, gormDB, "1", "1234") - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - anthrovePostID models.AnthrovePostID - } - tests := []struct { - name string - args args - want bool - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveUserID and AnthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "1", - anthrovePostID: "1234", - }, - want: true, - wantErr: false, - }, - { - name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "1", - anthrovePostID: "123456", - }, - want: false, - wantErr: false, - }, - { - name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "123", - anthrovePostID: "1234", - }, - want: false, - wantErr: false, - }, - { - name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "123", - anthrovePostID: "123456", - }, - want: false, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := CheckUserToPostLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) - if (err != nil) != tt.wantErr { - t.Errorf("CheckUserToPostLink() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("CheckUserToPostLink() got = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go index 99fd7b8..f0a3103 100644 --- a/internal/postgres/source_test.go +++ b/internal/postgres/source_test.go @@ -19,13 +19,13 @@ func TestCreateSourceNode(t *testing.T) { // Setup Test - validAnthroveSource := &models.Source{ + validSource := &models.Source{ DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", } - invalidAnthroveSource := &models.Source{ + invalidSource := &models.Source{ Domain: "", } @@ -45,7 +45,7 @@ func TestCreateSourceNode(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveSource: validAnthroveSource, + anthroveSource: validSource, }, wantErr: false, }, @@ -54,7 +54,7 @@ func TestCreateSourceNode(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveSource: invalidAnthroveSource, + anthroveSource: invalidSource, }, wantErr: true, }, @@ -63,7 +63,7 @@ func TestCreateSourceNode(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveSource: validAnthroveSource, + anthroveSource: validSource, }, wantErr: false, }, diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 40e0f68..885ffa3 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -8,7 +8,7 @@ import ( "gorm.io/gorm" ) -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) @@ -24,12 +24,16 @@ func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { return nil } -func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID models.AnthrovePostID, tag *models.Tag) error { +func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID string, tag *models.Tag) error { if PostID == "" { return fmt.Errorf("PostID is empty") } + if tag == nil { + return fmt.Errorf("tag is nill") + } + pgPost := models.Post{ BaseModel: models.BaseModel{ ID: string(PostID), diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index c0b323a..00b0b46 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -2,6 +2,7 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" @@ -19,7 +20,14 @@ func TestCreateTagNodeWitRelation(t *testing.T) { // Setup Test - err = CreateAnthrovePostNode(ctx, gormDB, "1234", "safe") + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = CreatePost(ctx, gormDB, post) if err != nil { t.Fatal(err) } @@ -33,7 +41,7 @@ func TestCreateTagNodeWitRelation(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - PostID models.AnthrovePostID + PostID string tag *models.Tag } tests := []struct { @@ -46,17 +54,17 @@ func TestCreateTagNodeWitRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - PostID: "1234", + PostID: post.ID, tag: tag, }, wantErr: false, }, { - name: "Test 2: Valid PostID and invalid Tag", + name: "Test 2: Valid PostID and no Tag", args: args{ ctx: ctx, db: gormDB, - PostID: "1234", + PostID: post.ID, tag: nil, }, wantErr: true, @@ -118,7 +126,7 @@ func TestGetTags(t *testing.T) { } for _, tag := range tags { - err = CreateTag(ctx, gormDB, &tag) + err = createTag(ctx, gormDB, &tag) if err != nil { t.Fatal(err) } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 8afd07f..fed56f9 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -8,7 +8,7 @@ import ( "gorm.io/gorm" ) -func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { +func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID string) error { if anthroveUserID == "" { return fmt.Errorf("anthroveUserID cannot be empty") @@ -20,7 +20,7 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove }, } - err := db.WithContext(ctx).Create(&user).Error + err := db.WithContext(ctx).FirstOrCreate(&user).Error if err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, @@ -31,12 +31,17 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove return nil } -func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { +func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthroveUserID string, sourceDomain string, userID string, username string) error { if anthroveUserID == "" || username == "" || userID == "" { return fmt.Errorf("anthroveUserID cannot be empty") } + err := CreateUser(ctx, db, anthroveUserID) + if err != nil { + return err + } + source := models.Source{ Domain: sourceDomain, } @@ -49,10 +54,11 @@ func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthrove } userSource := models.UserSource{ - User: models.User{BaseModel: models.BaseModel{ID: string(anthroveUserID)}}, + User: models.User{BaseModel: models.BaseModel{ID: anthroveUserID}}, SourceID: source.ID, AccountUsername: username, AccountID: userID, + UserID: anthroveUserID, } if err := db.WithContext(ctx).FirstOrCreate(&userSource).Error; err != nil { @@ -183,9 +189,9 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID return userSourceMap, nil } -func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveUserID, error) { +func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]string, error) { var users []models.User - var userIDs []models.AnthroveUserID + var userIDs []string err := db.WithContext(ctx).Model(&models.User{}).Find(&users).Error if err != nil { @@ -194,7 +200,7 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU } for _, user := range users { - userIDs = append(userIDs, models.AnthroveUserID(user.ID)) + userIDs = append(userIDs, user.ID) } log.WithFields(log.Fields{ @@ -204,7 +210,7 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU return userIDs, nil } -func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { +func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID string, skip int, limit int) (*models.FavoriteList, error) { var userFavorites []models.UserFavorite var favoritePosts []models.Post @@ -257,6 +263,7 @@ func GetUserTagNodeWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, ant name string typeName string }]int) + for _, userFavorite := range userFavorites { var post models.Post err = db.WithContext(ctx).Preload("Tags").First(&post, "id = ?", userFavorite.PostID).Error diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index b0742c5..cae2b0c 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models/graphModels" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" "reflect" @@ -26,7 +25,7 @@ func TestCreateUser(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveUserID models.AnthroveUserID + anthroveUserID string } tests := []struct { name string @@ -86,7 +85,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveUserID models.AnthroveUserID + anthroveUserID string sourceDomain string userID string username string @@ -102,7 +101,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceDomain: "e621.net", + sourceDomain: source.Domain, userID: "e1", username: "marius", }, @@ -114,7 +113,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "2", - sourceDomain: "e621.net", + sourceDomain: source.Domain, userID: "e1", username: "marius", }, @@ -126,7 +125,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "", - sourceDomain: "e621.net", + sourceDomain: source.Domain, userID: "e1", username: "marius", }, @@ -150,7 +149,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceDomain: "e621.net", + sourceDomain: source.Domain, userID: "", username: "marius", }, @@ -162,7 +161,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceDomain: "e621.net", + sourceDomain: source.Domain, userID: "aa", username: "", }, @@ -189,7 +188,7 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { // Setup Test - users := []models.AnthroveUserID{"1", "2", "3"} + users := []string{"1", "2", "3"} for _, user := range users { err = CreateUser(ctx, gormDB, user) @@ -206,7 +205,7 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { tests := []struct { name string args args - want []models.AnthroveUserID + want []string wantErr bool }{ { @@ -233,82 +232,6 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { } } -func TestGetAnthroveUser(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Setup Test - - user := graphModels.AnthroveUser{ - UserID: "1", - } - err = CreateUser(ctx, gormDB, user.UserID) - if err != nil { - t.Fatal(err) - } - - // Test - type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - } - tests := []struct { - name string - args args - want *graphModels.AnthroveUser - wantErr bool - }{ - { - name: "Test 1: Valid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "1", - }, - want: &user, - wantErr: false, - }, - { - name: "Test 2: Invalid AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "2", - }, - want: nil, - wantErr: true, - }, - { - name: "Test 3: No AnthroveUserID", - args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetAnthroveUser(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) - if (err != nil) != tt.wantErr { - t.Errorf("GetAnthroveUser() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAnthroveUser() got = %v, want %v", got, tt.want) - } - }) - } -} - func TestGetSpecifiedUserSourceLink(t *testing.T) { // Setup trow away container ctx := context.Background() @@ -319,31 +242,33 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { defer container.Terminate(ctx) // Setup Test - source := &models.Source{ - DisplayName: "e621", - Domain: "e621.net", + + expectedResult := make(map[string]models.UserSource) + expectedResult["e621"] = models.UserSource{ + UserID: "e1", + AccountUsername: "euser", + Source: models.Source{ + DisplayName: "e621", + Domain: "e621.net", + }, } + + source := &models.Source{ + DisplayName: expectedResult["e621"].Source.DisplayName, + Domain: expectedResult["e621"].Source.Domain, + } + err = CreateSourceNode(ctx, gormDB, source) if err != nil { t.Fatal(err) } - expectedResult := make(map[string]graphModels.AnthroveUserRelationship) - expectedResult["e621"] = graphModels.AnthroveUserRelationship{ - UserID: "e1", - Username: "euser", - Source: graphModels.AnthroveSource{ - DisplayName: source.DisplayName, - Domain: source.Domain, - }, - } - - err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", source.Domain, expectedResult["e621"].UserID, expectedResult["e621"].Username) + err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", source.Domain, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } - // Test + // Test type args struct { ctx context.Context db *gorm.DB @@ -353,7 +278,7 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { tests := []struct { name string args args - want map[string]graphModels.AnthroveUserRelationship + want map[string]models.UserSource wantErr bool }{ { @@ -431,7 +356,7 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetSpecifiedUserSourceLink() got = %v, expectedResult %v", got, tt.want) + t.Errorf("GetSpecifiedUserSourceLink() got = %v, want %v", got, tt.want) } }) } @@ -448,52 +373,41 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { // Setup Test - expectedResultPostsGraph := []graphModels.FavoritePost{ + expectedResultPosts := []models.Post{ { - AnthrovePost: graphModels.AnthrovePost{ - PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post1")), - Rating: "safe", - }, + BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post1")}, + Rating: "safe", }, { - AnthrovePost: graphModels.AnthrovePost{ - PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post2")), - Rating: "safe", - }, + + BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post2")}, + Rating: "safe", }, { - AnthrovePost: graphModels.AnthrovePost{ - PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post3")), - Rating: "explicit", - }, + BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post3")}, + Rating: "explicit", }, { - AnthrovePost: graphModels.AnthrovePost{ - PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post4")), - Rating: "explicit", - }, + BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post4")}, + Rating: "explicit", }, { - AnthrovePost: graphModels.AnthrovePost{ - PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post5")), - Rating: "questionable", - }, + BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post5")}, + Rating: "questionable", }, { - AnthrovePost: graphModels.AnthrovePost{ - PostID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post6")), - Rating: "safe", - }, + BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post6")}, + Rating: "safe", }, } - expectedResult := &graphModels.FavoriteList{ - Posts: expectedResultPostsGraph, + expectedResult := &models.FavoriteList{ + Posts: expectedResultPosts, } - expectedResult2 := &graphModels.FavoriteList{ - Posts: expectedResultPostsGraph[2:], + expectedResult2 := &models.FavoriteList{ + Posts: expectedResultPosts[2:], } - expectedResult3 := &graphModels.FavoriteList{ - Posts: expectedResultPostsGraph[:3], + expectedResult3 := &models.FavoriteList{ + Posts: expectedResultPosts[:3], } err = CreateUser(ctx, gormDB, "1") @@ -501,39 +415,12 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { t.Fatal(err) } - expectedResultPostsPg := []models.Post{ - { - BaseModel: models.BaseModel{ID: "Post1"}, - Rating: "safe", - }, - { - BaseModel: models.BaseModel{ID: "Post2"}, - Rating: "safe", - }, - { - BaseModel: models.BaseModel{ID: "Post3"}, - Rating: "explicit", - }, - { - BaseModel: models.BaseModel{ID: "Post4"}, - Rating: "explicit", - }, - { - BaseModel: models.BaseModel{ID: "Post5"}, - Rating: "questionable", - }, - { - BaseModel: models.BaseModel{ID: "Post6"}, - Rating: "safe", - }, - } - - for _, expectedResultPost := range expectedResultPostsPg { - err = CreateAnthrovePostNode(ctx, gormDB, models.AnthrovePostID(expectedResultPost.ID), expectedResultPost.Rating) + for _, expectedResultPost := range expectedResultPosts { + err = CreatePost(ctx, gormDB, &expectedResultPost) if err != nil { t.Fatal(err) } - err = EstablishUserToPostLink(ctx, gormDB, "1", models.AnthrovePostID(expectedResultPost.ID)) + err = EstablishUserToPostLink(ctx, gormDB, "1", expectedResultPost.ID) if err != nil { t.Fatal(err) } @@ -543,14 +430,14 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveUserID models.AnthroveUserID + anthroveUserID string skip int limit int } tests := []struct { name string args args - want *graphModels.FavoriteList + want *models.FavoriteList wantErr bool }{ { @@ -620,7 +507,7 @@ func TestGetUserFavoritesCount(t *testing.T) { t.Fatal(err) } - expectedResultPostsPg := []models.Post{ + expectedResultPosts := []models.Post{ { BaseModel: models.BaseModel{ID: "Post1"}, Rating: "safe", @@ -647,12 +534,12 @@ func TestGetUserFavoritesCount(t *testing.T) { }, } - for _, expectedResultPost := range expectedResultPostsPg { - err = CreateAnthrovePostNode(ctx, gormDB, models.AnthrovePostID(expectedResultPost.ID), expectedResultPost.Rating) + for _, post := range expectedResultPosts { + err = CreatePost(ctx, gormDB, &post) if err != nil { t.Fatal(err) } - err = EstablishUserToPostLink(ctx, gormDB, "1", models.AnthrovePostID(expectedResultPost.ID)) + err = EstablishUserToPostLink(ctx, gormDB, "1", post.ID) if err != nil { t.Fatal(err) } @@ -715,7 +602,7 @@ func TestGetUserFavoritesCount(t *testing.T) { } } -func TestGetUserSourceLink(t *testing.T) { +func TestGetUserSourceLinks(t *testing.T) { // Setup trow away containert ctx := context.Background() container, gormDB, err := test.StartPostgresContainer(ctx) @@ -725,51 +612,51 @@ func TestGetUserSourceLink(t *testing.T) { defer container.Terminate(ctx) // Setup Test - - esource := &models.Source{ + eSource := &models.Source{ DisplayName: "e621", Domain: "e621.net", } - err = CreateSourceNode(ctx, gormDB, esource) + err = CreateSourceNode(ctx, gormDB, eSource) if err != nil { t.Fatal(err) } - fasource := &models.Source{ + faSource := &models.Source{ DisplayName: "fa", Domain: "fa.net", } - err = CreateSourceNode(ctx, gormDB, fasource) + err = CreateSourceNode(ctx, gormDB, faSource) if err != nil { t.Fatal(err) } - expectedResult := make(map[string]graphModels.AnthroveUserRelationship) - expectedResult["e621"] = graphModels.AnthroveUserRelationship{ - UserID: "e1", - Username: "euser", - Source: graphModels.AnthroveSource{ - DisplayName: esource.DisplayName, - Domain: esource.Domain, + expectedResult := make(map[string]models.UserSource) + expectedResult["e621"] = models.UserSource{ + UserID: "e1", + AccountUsername: "e621-user", + Source: models.Source{ + DisplayName: eSource.DisplayName, + Domain: eSource.Domain, }, } - expectedResult["fa"] = graphModels.AnthroveUserRelationship{ - UserID: "fa1", - Username: "fauser", - Source: graphModels.AnthroveSource{ - DisplayName: fasource.DisplayName, - Domain: fasource.Domain, + expectedResult["fa"] = models.UserSource{ + UserID: "fa1", + AccountUsername: "fa-user", + Source: models.Source{ + DisplayName: faSource.DisplayName, + Domain: faSource.Domain, }, } - err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", esource.Domain, expectedResult["e621"].UserID, expectedResult["e621"].Username) + err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", eSource.Domain, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } - err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", fasource.Domain, expectedResult["fa"].UserID, expectedResult["fa"].Username) + err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", faSource.Domain, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) if err != nil { t.Fatal(err) } + // Test type args struct { ctx context.Context @@ -779,7 +666,7 @@ func TestGetUserSourceLink(t *testing.T) { tests := []struct { name string args args - want map[string]graphModels.AnthroveUserRelationship + want map[string]models.UserSource wantErr bool }{ { @@ -829,11 +716,11 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { } for _, post := range posts { - err = CreateAnthrovePostNode(ctx, gormDB, models.AnthrovePostID(post.ID), post.Rating) + err = CreatePost(ctx, gormDB, &post) if err != nil { t.Fatal(err) } - err = EstablishUserToPostLink(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) + err = EstablishUserToPostLink(ctx, gormDB, "1", post.ID) if err != nil { t.Fatal(err) } @@ -846,32 +733,32 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { } for i, tag := range tags { - err = CreateTagNodeWitRelation(ctx, gormDB, models.AnthrovePostID(posts[i].ID), &tag) + err = CreateTagNodeWitRelation(ctx, gormDB, posts[i].ID, &tag) if err != nil { t.Fatal(err) } } - expectedResult := []graphModels.TagsWithFrequency{ + expectedResult := []models.TagsWithFrequency{ { Frequency: 1, - Tags: graphModels.AnthroveTag{ + Tags: models.Tag{ Name: tags[0].Name, - Type: string(tags[0].Type), + Type: tags[0].Type, }, }, { Frequency: 1, - Tags: graphModels.AnthroveTag{ + Tags: models.Tag{ Name: tags[1].Name, - Type: string(tags[1].Type), + Type: tags[1].Type, }, }, { Frequency: 1, - Tags: graphModels.AnthroveTag{ + Tags: models.Tag{ Name: tags[2].Name, - Type: string(tags[2].Type), + Type: tags[2].Type, }, }, } @@ -885,11 +772,11 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { tests := []struct { name string args args - want []graphModels.TagsWithFrequency + want []models.TagsWithFrequency wantErr bool }{ { - name: "", + name: "Test 1: Get Data", args: args{ ctx: ctx, db: gormDB, diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index 749a337..e6758e3 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -91,7 +91,8 @@ CREATE TABLE "UserSource" ( user_id TEXT REFERENCES "User" (id), source_id TEXT REFERENCES "Source" (id), - scrape_time_interval TEXT account_username TEXT, + scrape_time_interval TEXT, + account_username TEXT, account_id TEXT, PRIMARY KEY (user_id, source_id), UNIQUE (account_username, account_id) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index ac996c0..0cfc1bd 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -73,7 +73,7 @@ func (p *postgresqlConnection) AddSource(ctx context.Context, anthroveSource *mo } func (p *postgresqlConnection) AddPost(ctx context.Context, anthrovePost *models.Post) error { - return postgres.CreateAnthrovePostNode(ctx, p.db, anthrovePost) + return postgres.CreatePost(ctx, p.db, anthrovePost) } func (p *postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error { From 8a0229eb23766f93abefc6f82ade95268b822ba1 Mon Sep 17 00:00:00 2001 From: soxx Date: Sun, 23 Jun 2024 21:23:38 +0200 Subject: [PATCH 067/124] test(postgres): renamed functions to be more clear Signed-off-by: soxx --- internal/postgres/post_test.go | 8 +- internal/postgres/relationships.go | 6 +- internal/postgres/relationships_test.go | 18 ++-- internal/postgres/source.go | 12 +-- internal/postgres/source_test.go | 20 ++--- internal/postgres/tag.go | 4 +- internal/postgres/tag_test.go | 6 +- internal/postgres/user.go | 26 +++--- internal/postgres/user_test.go | 112 ++++++++++++------------ pkg/database/database.go | 46 +++++----- pkg/database/postgres.go | 44 +++++----- 11 files changed, 153 insertions(+), 149 deletions(-) diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index 87d2690..098fe2b 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -181,12 +181,12 @@ func TestGetPostBySourceURL(t *testing.T) { Icon: "https://e621.net/icon.ico", } - err = CreateSourceNode(ctx, gormDB, &source) + err = CreateSource(ctx, gormDB, &source) if err != nil { t.Fatal("Could not create source", err) } - err = EstablishAnthrovePostToSourceLink(ctx, gormDB, post.ID, source.Domain) + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, source.Domain) if err != nil { t.Fatal("Could not create source reference", err) } @@ -278,12 +278,12 @@ func TestGetPostBySourceID(t *testing.T) { Icon: "https://e621.net/icon.ico", } - err = CreateSourceNode(ctx, gormDB, &source) + err = CreateSource(ctx, gormDB, &source) if err != nil { t.Fatal("Could not create source", err) } - err = EstablishAnthrovePostToSourceLink(ctx, gormDB, post.ID, source.Domain) + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, source.Domain) if err != nil { t.Fatal("Could not create source reference", err) } diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index 7f319e0..cade964 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -7,7 +7,7 @@ import ( "gorm.io/gorm" ) -func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrovePostID string, sourceDomain string) error { +func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID string, sourceDomain string) error { var source models.Source var err error @@ -36,7 +36,7 @@ func EstablishAnthrovePostToSourceLink(ctx context.Context, db *gorm.DB, anthrov return nil } -func EstablishUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID string, anthrovePostID string) error { +func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID string, anthrovePostID string) error { userFavorite := models.UserFavorite{ UserID: string(anthroveUserID), PostID: string(anthrovePostID), @@ -55,7 +55,7 @@ func EstablishUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID st return nil } -func CheckUserToPostLink(ctx context.Context, db *gorm.DB, anthroveUserID string, anthrovePostID string) (bool, error) { +func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID string, anthrovePostID string) (bool, error) { var count int64 err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count).Error if err != nil { diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go index 7d2bc56..4d49f65 100644 --- a/internal/postgres/relationships_test.go +++ b/internal/postgres/relationships_test.go @@ -37,7 +37,7 @@ func TestCheckUserToPostLink(t *testing.T) { t.Fatal(err) } - err = EstablishUserToPostLink(ctx, gormDB, "1", post.ID) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", post.ID) if err != nil { t.Fatal(err) } @@ -102,13 +102,13 @@ func TestCheckUserToPostLink(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := CheckUserToPostLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) + got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) if (err != nil) != tt.wantErr { - t.Errorf("CheckUserToPostLink() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("CheckReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { - t.Errorf("CheckUserToPostLink() got = %v, want %v", got, tt.want) + t.Errorf("CheckReferenceBetweenUserAndPost() got = %v, want %v", got, tt.want) } }) } @@ -141,7 +141,7 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { Domain: "e621.net", Icon: "icon.e621.net", } - err = CreateSourceNode(ctx, gormDB, source) + err = CreateSource(ctx, gormDB, source) if err != nil { t.Fatal(err) } @@ -202,8 +202,8 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := EstablishAnthrovePostToSourceLink(tt.args.ctx, tt.args.db, tt.args.anthrovePostID, tt.args.sourceDomain); (err != nil) != tt.wantErr { - t.Errorf("EstablishAnthrovePostToSourceLink() error = %v, wantErr %v", err, tt.wantErr) + if err := CreateReferenceBetweenPostAndSource(tt.args.ctx, tt.args.db, tt.args.anthrovePostID, tt.args.sourceDomain); (err != nil) != tt.wantErr { + t.Errorf("CreateReferenceBetweenPostAndSource() error = %v, wantErr %v", err, tt.wantErr) } }) } @@ -291,8 +291,8 @@ func TestEstablishUserToPostLink(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := EstablishUserToPostLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID); (err != nil) != tt.wantErr { - t.Errorf("EstablishUserToPostLink() error = %v, wantErr %v", err, tt.wantErr) + if err := CreateReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID); (err != nil) != tt.wantErr { + t.Errorf("CreateReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) } }) } diff --git a/internal/postgres/source.go b/internal/postgres/source.go index 5e4ecd5..ec889fd 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -9,8 +9,8 @@ import ( "gorm.io/gorm" ) -// CreateSourceNode creates a pgModels.Source -func CreateSourceNode(ctx context.Context, db *gorm.DB, anthroveSource *models.Source) error { +// CreateSource creates a pgModels.Source +func CreateSource(ctx context.Context, db *gorm.DB, anthroveSource *models.Source) error { if anthroveSource.Domain == "" { return fmt.Errorf("anthroveSource domain is required") @@ -31,8 +31,8 @@ func CreateSourceNode(ctx context.Context, db *gorm.DB, anthroveSource *models.S return nil } -// GetAllSourceNodes returns a list of all pgModels.Source -func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]models.Source, error) { +// GetAllSource returns a list of all pgModels.Source +func GetAllSource(ctx context.Context, db *gorm.DB) ([]models.Source, error) { var sources []models.Source result := db.WithContext(ctx).Find(&sources) @@ -48,8 +48,8 @@ func GetAllSourceNodes(ctx context.Context, db *gorm.DB) ([]models.Source, error return sources, nil } -// GetSourceNodesByURL returns the first source it finds based on the domain -func GetSourceNodesByURL(ctx context.Context, db *gorm.DB, domain string) (*models.Source, error) { +// GetSourceByURL returns the first source it finds based on the domain +func GetSourceByURL(ctx context.Context, db *gorm.DB, domain string) (*models.Source, error) { var sources models.Source if domain == "" { diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go index f0a3103..a6d7863 100644 --- a/internal/postgres/source_test.go +++ b/internal/postgres/source_test.go @@ -70,8 +70,8 @@ func TestCreateSourceNode(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CreateSourceNode(tt.args.ctx, tt.args.db, tt.args.anthroveSource); (err != nil) != tt.wantErr { - t.Errorf("CreateSourceNode() error = %v, wantErr %v", err, tt.wantErr) + if err := CreateSource(tt.args.ctx, tt.args.db, tt.args.anthroveSource); (err != nil) != tt.wantErr { + t.Errorf("CreateSource() error = %v, wantErr %v", err, tt.wantErr) } }) } @@ -107,7 +107,7 @@ func TestGetAllSourceNodes(t *testing.T) { } for _, source := range sources { - err = CreateSourceNode(ctx, gormDB, &source) + err = CreateSource(ctx, gormDB, &source) if err != nil { t.Fatal(err) } @@ -136,13 +136,13 @@ func TestGetAllSourceNodes(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetAllSourceNodes(tt.args.ctx, tt.args.db) + got, err := GetAllSource(tt.args.ctx, tt.args.db) if (err != nil) != tt.wantErr { - t.Errorf("GetAllSourceNodes() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetAllSource() error = %v, wantErr %v", err, tt.wantErr) return } if !checkSourcesNode(got, tt.want) { - t.Errorf("GetAllSourceNodes() got = %v, want %v", got, tt.want) + t.Errorf("GetAllSource() got = %v, want %v", got, tt.want) } }) } @@ -165,7 +165,7 @@ func TestGetSourceNodesByURL(t *testing.T) { Icon: "icon.e621.net", } - err = CreateSourceNode(ctx, gormDB, source) + err = CreateSource(ctx, gormDB, source) if err != nil { t.Fatal(err) } @@ -215,13 +215,13 @@ func TestGetSourceNodesByURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetSourceNodesByURL(tt.args.ctx, tt.args.db, tt.args.domain) + got, err := GetSourceByURL(tt.args.ctx, tt.args.db, tt.args.domain) if (err != nil) != tt.wantErr { - t.Errorf("GetSourceNodesByURL() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetSourceByURL() error = %v, wantErr %v", err, tt.wantErr) return } if !checkSourceNode(got, tt.want) { - t.Errorf("GetSourceNodesByURL() got = %v, want %v", got, tt.want) + t.Errorf("GetSourceByURL() got = %v, want %v", got, tt.want) } }) } diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 885ffa3..4213b28 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -8,7 +8,7 @@ import ( "gorm.io/gorm" ) -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) @@ -24,7 +24,7 @@ func createTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { return nil } -func CreateTagNodeWitRelation(ctx context.Context, db *gorm.DB, PostID string, tag *models.Tag) error { +func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, PostID string, tag *models.Tag) error { if PostID == "" { return fmt.Errorf("PostID is empty") diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index 00b0b46..d83d760 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -92,8 +92,8 @@ func TestCreateTagNodeWitRelation(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CreateTagNodeWitRelation(tt.args.ctx, tt.args.db, tt.args.PostID, tt.args.tag); (err != nil) != tt.wantErr { - t.Errorf("CreateTagNodeWitRelation() error = %v, wantErr %v", err, tt.wantErr) + if err := CreateTagAndReferenceToPost(tt.args.ctx, tt.args.db, tt.args.PostID, tt.args.tag); (err != nil) != tt.wantErr { + t.Errorf("CreateTagAndReferenceToPost() error = %v, wantErr %v", err, tt.wantErr) } }) } @@ -126,7 +126,7 @@ func TestGetTags(t *testing.T) { } for _, tag := range tags { - err = createTag(ctx, gormDB, &tag) + err = CreateTag(ctx, gormDB, &tag) if err != nil { t.Fatal(err) } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index fed56f9..91282d2 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -31,7 +31,7 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID string) error { return nil } -func CreateUserNodeWithSourceRelation(ctx context.Context, db *gorm.DB, anthroveUserID string, sourceDomain string, userID string, username string) error { +func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUserID string, sourceDomain string, userID string, username string) error { if anthroveUserID == "" || username == "" || userID == "" { return fmt.Errorf("anthroveUserID cannot be empty") @@ -143,19 +143,23 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models. return userSourceMap, nil } -func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) { - if anthroveUserID == "" || sourceDisplayName == "" { - return nil, fmt.Errorf("anthroveUserID or sourceDisplayName is empty") +func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID string) (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 userSourceMap := make(map[string]models.UserSource) - err := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("display_name = ?", sourceDisplayName)).Where("user_id = ?", string(anthroveUserID)).First(&userSources).Error + err := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("id = ?", sourceID)).Where("user_id = ?", string(anthroveUserID)).First(&userSources).Error if err != nil { log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "source_display_name": sourceDisplayName, + "anthrove_user_id": anthroveUserID, + "source_id": sourceID, }).Error("database: failed to get specified user source link") return nil, err } @@ -182,8 +186,8 @@ func GetSpecifiedUserSourceLink(ctx context.Context, db *gorm.DB, anthroveUserID } log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "source_display_name": sourceDisplayName, + "anthrove_user_id": anthroveUserID, + "source_id": sourceID, }).Trace("database: got specified user source link") return userSourceMap, nil @@ -210,7 +214,7 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]string, error) { return userIDs, nil } -func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID string, skip int, limit int) (*models.FavoriteList, error) { +func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID string, skip int, limit int) (*models.FavoriteList, error) { var userFavorites []models.UserFavorite var favoritePosts []models.Post @@ -249,7 +253,7 @@ func GetUserFavoriteNodeWithPagination(ctx context.Context, db *gorm.DB, anthrov return &models.FavoriteList{Posts: favoritePosts}, nil } -func GetUserTagNodeWitRelationToFavedPosts(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.UserFavorite err := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites).Error if err != nil { diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index cae2b0c..3adee0f 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -76,7 +76,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { Domain: "e621.net", Icon: "icon.e621.net", } - err = CreateSourceNode(ctx, gormDB, source) + err = CreateSource(ctx, gormDB, source) if err != nil { t.Fatal(err) } @@ -170,8 +170,8 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CreateUserNodeWithSourceRelation(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceDomain, tt.args.userID, tt.args.username); (err != nil) != tt.wantErr { - t.Errorf("CreateUserNodeWithSourceRelation() error = %v, wantErr %v", err, tt.wantErr) + if err := CreateUserWithRelationToSource(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceDomain, tt.args.userID, tt.args.username); (err != nil) != tt.wantErr { + t.Errorf("CreateUserWithRelationToSource() error = %v, wantErr %v", err, tt.wantErr) } }) } @@ -232,7 +232,7 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { } } -func TestGetSpecifiedUserSourceLink(t *testing.T) { +func TestGetUserSourceBySourceID(t *testing.T) { // Setup trow away container ctx := context.Background() container, gormDB, err := test.StartPostgresContainer(ctx) @@ -254,26 +254,27 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { } source := &models.Source{ + BaseModel: models.BaseModel{ID: expectedResult["e621"].Source.ID}, DisplayName: expectedResult["e621"].Source.DisplayName, Domain: expectedResult["e621"].Source.Domain, } - err = CreateSourceNode(ctx, gormDB, source) + err = CreateSource(ctx, gormDB, source) if err != nil { t.Fatal(err) } - err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", source.Domain, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, "1", source.Domain, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } // Test type args struct { - ctx context.Context - db *gorm.DB - anthroveUserID models.AnthroveUserID - sourceDisplayName string + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + sourceID string } tests := []struct { name string @@ -282,45 +283,45 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { wantErr bool }{ { - name: "Test 1: Valid AnthroveUserID and SourceDisplayName", + name: "Test 1: Valid AnthroveUserID and sourceID", args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "1", - sourceDisplayName: "e621", + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceID: source.ID, }, want: expectedResult, wantErr: false, }, { - name: "Test 2: Invalid AnthroveUserID and valid SourceDisplayName", + name: "Test 2: Invalid AnthroveUserID and valid sourceID", args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "22", - sourceDisplayName: "e621", + ctx: ctx, + db: gormDB, + anthroveUserID: "22", + sourceID: source.ID, }, want: nil, wantErr: true, }, { - name: "Test 3: Valid AnthroveUserID and invalid SourceDisplayName", + name: "Test 3: Valid AnthroveUserID and invalid sourceID", args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "1", - sourceDisplayName: "fa", + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceID: "fa", }, want: nil, wantErr: true, }, { - name: "Test 4: No AnthroveUserID and Valid SourceDisplayName", + name: "Test 4: No AnthroveUserID and Valid sourceID", args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - sourceDisplayName: "e621", + ctx: ctx, + db: gormDB, + anthroveUserID: "", + sourceID: source.ID, }, want: nil, wantErr: true, @@ -328,10 +329,10 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { { name: "Test 5: Valid AnthroveUserID and No SourceDisplayName", args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "1", - sourceDisplayName: "", + ctx: ctx, + db: gormDB, + anthroveUserID: "1", + sourceID: "", }, want: nil, wantErr: true, @@ -339,10 +340,10 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { { name: "Test 6: No AnthroveUserID and No SourceDisplayName", args: args{ - ctx: ctx, - db: gormDB, - anthroveUserID: "", - sourceDisplayName: "", + ctx: ctx, + db: gormDB, + anthroveUserID: "", + sourceID: "", }, want: nil, wantErr: true, @@ -350,18 +351,17 @@ func TestGetSpecifiedUserSourceLink(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetSpecifiedUserSourceLink(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceDisplayName) + got, err := GetUserSourceBySourceID(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID) if (err != nil) != tt.wantErr { - t.Errorf("GetSpecifiedUserSourceLink() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetUserSourceBySourceID() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetSpecifiedUserSourceLink() got = %v, want %v", got, tt.want) + t.Errorf("GetUserSourceBySourceID() got = %v, want %v", got, tt.want) } }) } } - func TestGetUserFavoriteNodeWithPagination(t *testing.T) { // Setup trow away containert ctx := context.Background() @@ -420,7 +420,7 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { if err != nil { t.Fatal(err) } - err = EstablishUserToPostLink(ctx, gormDB, "1", expectedResultPost.ID) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", expectedResultPost.ID) if err != nil { t.Fatal(err) } @@ -479,13 +479,13 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetUserFavoriteNodeWithPagination(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) + got, err := GetUserFavoriteWithPagination(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) if (err != nil) != tt.wantErr { - t.Errorf("GetUserFavoriteNodeWithPagination() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetUserFavoriteWithPagination() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetUserFavoriteNodeWithPagination() got = %v, want %v", got, tt.want) + t.Errorf("GetUserFavoriteWithPagination() got = %v, want %v", got, tt.want) } }) } @@ -539,7 +539,7 @@ func TestGetUserFavoritesCount(t *testing.T) { if err != nil { t.Fatal(err) } - err = EstablishUserToPostLink(ctx, gormDB, "1", post.ID) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", post.ID) if err != nil { t.Fatal(err) } @@ -616,7 +616,7 @@ func TestGetUserSourceLinks(t *testing.T) { DisplayName: "e621", Domain: "e621.net", } - err = CreateSourceNode(ctx, gormDB, eSource) + err = CreateSource(ctx, gormDB, eSource) if err != nil { t.Fatal(err) } @@ -625,7 +625,7 @@ func TestGetUserSourceLinks(t *testing.T) { DisplayName: "fa", Domain: "fa.net", } - err = CreateSourceNode(ctx, gormDB, faSource) + err = CreateSource(ctx, gormDB, faSource) if err != nil { t.Fatal(err) } @@ -648,11 +648,11 @@ func TestGetUserSourceLinks(t *testing.T) { }, } - err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", eSource.Domain, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, "1", eSource.Domain, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } - err = CreateUserNodeWithSourceRelation(ctx, gormDB, "1", faSource.Domain, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, "1", faSource.Domain, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) if err != nil { t.Fatal(err) } @@ -720,7 +720,7 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { if err != nil { t.Fatal(err) } - err = EstablishUserToPostLink(ctx, gormDB, "1", post.ID) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", post.ID) if err != nil { t.Fatal(err) } @@ -733,7 +733,7 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { } for i, tag := range tags { - err = CreateTagNodeWitRelation(ctx, gormDB, posts[i].ID, &tag) + err = CreateTagAndReferenceToPost(ctx, gormDB, posts[i].ID, &tag) if err != nil { t.Fatal(err) } @@ -788,13 +788,13 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetUserTagNodeWitRelationToFavedPosts(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) + got, err := GetUserTagWitRelationToFavedPosts(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) if (err != nil) != tt.wantErr { - t.Errorf("GetUserTagNodeWitRelationToFavedPosts() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetUserTagWitRelationToFavedPosts() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetUserTagNodeWitRelationToFavedPosts() got = %v, want %v", got, tt.want) + t.Errorf("GetUserTagWitRelationToFavedPosts() got = %v, want %v", got, tt.want) } }) } diff --git a/pkg/database/database.go b/pkg/database/database.go index 76269bf..f0c74f0 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -9,26 +9,26 @@ type OtterSpace interface { // Connect establishes a connection to the database. Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error - // AddUserWithRelationToSource adds a user with a relation to a source. - AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error + // CreateUserWithRelationToSource adds a user with a relation to a source. + CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error - // AddSource adds a new source to the database. - AddSource(ctx context.Context, anthroveSource *models.Source) error + // CreateSource adds a new source to the database. + CreateSource(ctx context.Context, anthroveSource *models.Source) error - // AddPost adds a new post to the database. - AddPost(ctx context.Context, anthrovePost *models.Post) error + // CreatePost adds a new post to the database. + CreatePost(ctx context.Context, anthrovePost *models.Post) error - // AddTagWithRelationToPost adds a tag with a relation to a post. - AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error + // CreateTagAndReferenceToPost adds a tag with a relation to a post. + CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error - // LinkPostWithSource links a post with a source. - LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.PostReference) error + // CreateReferenceBetweenPostAndSource links a post with a source. + CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.PostReference) error - // LinkUserWithPost links a user with a post. - LinkUserWithPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error + // CreateReferenceBetweenUserAndPost links a user with a post. + CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error - // CheckUserPostLink checks if a user-post link exists. - CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) + // CheckReferenceBetweenUserAndPost checks if a user-post link exists. + CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) // GetPostByAnthroveID retrieves a post by its Anthrove ID. GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) @@ -39,26 +39,26 @@ type OtterSpace interface { // GetPostBySourceID retrieves a post by its source ID. GetPostBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) - // GetUserFavoriteCount retrieves the count of a user's favorites. - GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) + // GetUserFavoritesCount retrieves the count of a user's favorites. + GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) // GetUserSourceLinks retrieves the source links of a user. GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) - // GetSpecifiedUserSourceLink retrieves a specified source link of a user. - GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) + // GetUserSourceBySourceID retrieves a specified source link of a user. + GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID string) (map[string]models.UserSource, error) // GetAllAnthroveUserIDs retrieves all Anthrove user IDs. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) - // GetUserFavoritePostsWithPagination retrieves a user's favorite posts with pagination. - GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) + // GetUserFavoriteWithPagination retrieves a user's favorite posts with pagination. + GetUserFavoriteWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) - // GetUserTagsTroughFavedPosts retrieves a user's tags through their favorited posts. - GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) + // GetUserTagWitRelationToFavedPosts retrieves a user's tags through their favorited posts. + GetUserTagWitRelationToFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) // GetAllTags retrieves all tags. - GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) + GetAllTags(ctx context.Context) ([]models.Tag, error) // GetAllSources retrieves all sources. GetAllSources(ctx context.Context) ([]models.Source, error) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 0cfc1bd..3503deb 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -64,32 +64,32 @@ func (p *postgresqlConnection) Connect(_ context.Context, endpoint string, usern return nil } -func (p *postgresqlConnection) AddUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { - return postgres.CreateUserNodeWithSourceRelation(ctx, p.db, anthroveUserID, sourceDomain, userID, userID) +func (p *postgresqlConnection) CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { + return postgres.CreateUserWithRelationToSource(ctx, p.db, anthroveUserID, sourceDomain, userID, userID) } -func (p *postgresqlConnection) AddSource(ctx context.Context, anthroveSource *models.Source) error { - return postgres.CreateSourceNode(ctx, p.db, anthroveSource) +func (p *postgresqlConnection) CreateSource(ctx context.Context, anthroveSource *models.Source) error { + return postgres.CreateSource(ctx, p.db, anthroveSource) } -func (p *postgresqlConnection) AddPost(ctx context.Context, anthrovePost *models.Post) error { +func (p *postgresqlConnection) CreatePost(ctx context.Context, anthrovePost *models.Post) error { return postgres.CreatePost(ctx, p.db, anthrovePost) } -func (p *postgresqlConnection) AddTagWithRelationToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error { - return postgres.CreateTagNodeWitRelation(ctx, p.db, anthrovePostID, anthroveTag) +func (p *postgresqlConnection) CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error { + return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag) } -func (p *postgresqlConnection) LinkPostWithSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain string, anthrovePostRelationship *models.PostReference) error { - return postgres.EstablishAnthrovePostToSourceLink(ctx, p.db, anthrovePostID, sourceDomain, anthrovePostRelationship) +func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain string, anthrovePostRelationship *models.PostReference) error { + return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain, anthrovePostRelationship) } -func (p *postgresqlConnection) LinkUserWithPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error { - return postgres.EstablishUserToPostLink(ctx, p.db, anthroveUser.ID, anthrovePost.ID) +func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error { + return postgres.CreateReferenceBetweenUserAndPost(ctx, p.db, anthroveUser.ID, anthrovePost.ID) } -func (p *postgresqlConnection) CheckUserPostLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { - return postgres.CheckUserToPostLink(ctx, p.db, anthroveUserID, models.AnthrovePostID(sourcePostID)) +func (p *postgresqlConnection) CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { + return postgres.CheckReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, models.AnthrovePostID(sourcePostID)) } func (p *postgresqlConnection) GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) { @@ -104,7 +104,7 @@ func (p *postgresqlConnection) GetPostBySourceID(ctx context.Context, sourcePost return postgres.GetPostBySourceID(ctx, p.db, sourcePostID) } -func (p *postgresqlConnection) GetUserFavoriteCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { +func (p *postgresqlConnection) GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { return postgres.GetUserFavoritesCount(ctx, p.db, anthroveUserID) } @@ -112,7 +112,7 @@ func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveU return postgres.GetUserSourceLinks(ctx, p.db, anthroveUserID) } -func (p *postgresqlConnection) GetSpecifiedUserSourceLink(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) { +func (p *postgresqlConnection) GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) { return postgres.GetSpecifiedUserSourceLink(ctx, p.db, anthroveUserID, sourceDisplayName) } @@ -120,24 +120,24 @@ func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]mod return postgres.GetAllAnthroveUserIDs(ctx, p.db) } -func (p *postgresqlConnection) GetUserFavoritePostsWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { - return postgres.GetUserFavoriteNodeWithPagination(ctx, p.db, anthroveUserID, skip, limit) +func (p *postgresqlConnection) GetUserFavoriteWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { + return postgres.GetUserFavoriteWithPagination(ctx, p.db, anthroveUserID, skip, limit) } -func (p *postgresqlConnection) GetUserTagsTroughFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { - return postgres.GetUserTagNodeWitRelationToFavedPosts(ctx, p.db, anthroveUserID) +func (p *postgresqlConnection) GetUserTagWitRelationToFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { + return postgres.GetUserTagWitRelationToFavedPosts(ctx, p.db, anthroveUserID) } -func (p *postgresqlConnection) GetAllTags(ctx context.Context) ([]models.TagsWithFrequency, error) { +func (p *postgresqlConnection) GetAllTags(ctx context.Context) ([]models.Tag, error) { return postgres.GetTags(ctx, p.db) } func (p *postgresqlConnection) GetAllSources(ctx context.Context) ([]models.Source, error) { - return postgres.GetAllSourceNodes(ctx, p.db) + return postgres.GetAllSource(ctx, p.db) } func (p *postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*models.Source, error) { - return postgres.GetSourceNodesByURL(ctx, p.db, sourceUrl) + return postgres.GetSourceByURL(ctx, p.db, sourceUrl) } func (p *postgresqlConnection) migrateDatabase(connectionString string) error { From b0d98d842f2e37c21b7886514883a035c10626cc Mon Sep 17 00:00:00 2001 From: soxx Date: Sun, 23 Jun 2024 22:35:46 +0200 Subject: [PATCH 068/124] refactor(postgres): renamed function names and fixed tests and other issues Signed-off-by: soxx --- internal/postgres/post.go | 6 +-- internal/postgres/post_test.go | 18 ++++---- internal/postgres/relationships.go | 10 ++--- internal/postgres/relationships_test.go | 22 ++++----- internal/postgres/source.go | 8 ++-- internal/postgres/source_test.go | 8 ++-- internal/postgres/tag.go | 2 +- internal/postgres/tag_test.go | 6 +-- internal/postgres/user.go | 48 +++++++++++--------- internal/postgres/user_test.go | 60 +++++++++++++------------ pkg/database/database.go | 20 ++++----- pkg/database/postgres.go | 32 ++++++------- pkg/models/const.go | 5 ++- pkg/models/orm.go | 6 +++ 14 files changed, 135 insertions(+), 116 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 079be3d..2dde49a 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -23,7 +23,7 @@ func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) err return nil } -func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID string) (*models.Post, error) { +func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID) (*models.Post, error) { if anthrovePostID == "" { return nil, fmt.Errorf("anthrovePostID is required") } @@ -37,7 +37,7 @@ func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID string return &post, nil } -func GetPostBySourceURL(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 @@ -51,7 +51,7 @@ func GetPostBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*mo return &post, nil } -func GetPostBySourceID(ctx context.Context, db *gorm.DB, sourceID string) (*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 diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index 098fe2b..cf2ebc4 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -99,7 +99,7 @@ func TestGetPostByAnthroveID(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthrovePostID string + anthrovePostID models.AnthrovePostID } tests := []struct { name string @@ -112,7 +112,7 @@ func TestGetPostByAnthroveID(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthrovePostID: post.ID, + anthrovePostID: models.AnthrovePostID(post.ID), }, want: post, wantErr: false, @@ -186,7 +186,7 @@ func TestGetPostBySourceURL(t *testing.T) { t.Fatal("Could not create source", err) } - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, source.Domain) + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, models.AnthrovePostID(post.ID), models.AnthroveSourceDomain(source.Domain)) if err != nil { t.Fatal("Could not create source reference", err) } @@ -236,13 +236,13 @@ func TestGetPostBySourceURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetPostBySourceURL(tt.args.ctx, tt.args.db, tt.args.sourceURL) + got, err := GetPostByURL(tt.args.ctx, tt.args.db, tt.args.sourceURL) if (err != nil) != tt.wantErr { - t.Errorf("GetPostBySourceURL() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetPostByURL() error = %v, wantErr %v", err, tt.wantErr) return } if !checkPost(got, tt.want) { - t.Errorf("GetPostBySourceURL() got = %v, want %v", got, tt.want) + t.Errorf("GetPostByURL() got = %v, want %v", got, tt.want) } }) } @@ -283,7 +283,7 @@ func TestGetPostBySourceID(t *testing.T) { t.Fatal("Could not create source", err) } - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, source.Domain) + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, models.AnthrovePostID(post.ID), models.AnthroveSourceDomain(source.Domain)) if err != nil { t.Fatal("Could not create source reference", err) } @@ -292,7 +292,7 @@ func TestGetPostBySourceID(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - sourceID string + sourceID models.AnthroveSourceID } tests := []struct { @@ -306,7 +306,7 @@ func TestGetPostBySourceID(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - sourceID: source.ID, + sourceID: models.AnthroveSourceID(source.ID), }, want: post, wantErr: false, diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index cade964..5c268f8 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -7,7 +7,7 @@ import ( "gorm.io/gorm" ) -func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID string, sourceDomain string) error { +func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { var source models.Source var err error @@ -19,9 +19,9 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr // Establish the relationship err = db.WithContext(ctx).Create(models.PostReference{ - PostID: anthrovePostID, + PostID: string(anthrovePostID), SourceID: source.ID, - URL: sourceDomain, + URL: string(sourceDomain), }).Error if err != nil { @@ -36,7 +36,7 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr return nil } -func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID string, anthrovePostID string) error { +func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { userFavorite := models.UserFavorite{ UserID: string(anthroveUserID), PostID: string(anthrovePostID), @@ -55,7 +55,7 @@ func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthrov return nil } -func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID string, anthrovePostID string) (bool, error) { +func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { var count int64 err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count).Error if err != nil { diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go index 4d49f65..cc763a0 100644 --- a/internal/postgres/relationships_test.go +++ b/internal/postgres/relationships_test.go @@ -37,7 +37,7 @@ func TestCheckUserToPostLink(t *testing.T) { t.Fatal(err) } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", post.ID) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) if err != nil { t.Fatal(err) } @@ -46,8 +46,8 @@ func TestCheckUserToPostLink(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveUserID string - anthrovePostID string + anthroveUserID models.AnthroveUserID + anthrovePostID models.AnthrovePostID } tests := []struct { name string @@ -61,7 +61,7 @@ func TestCheckUserToPostLink(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - anthrovePostID: post.ID, + anthrovePostID: models.AnthrovePostID(post.ID), }, want: true, wantErr: false, @@ -83,7 +83,7 @@ func TestCheckUserToPostLink(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "123", - anthrovePostID: post.ID, + anthrovePostID: models.AnthrovePostID(post.ID), }, want: false, wantErr: false, @@ -150,8 +150,8 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthrovePostID string - sourceDomain string + anthrovePostID models.AnthrovePostID + sourceDomain models.AnthroveSourceDomain anthrovePostRelationship *models.PostReference } tests := []struct { @@ -164,7 +164,7 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthrovePostID: post.ID, + anthrovePostID: models.AnthrovePostID(post.ID), sourceDomain: "e621.net", }, wantErr: false, @@ -240,8 +240,8 @@ func TestEstablishUserToPostLink(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveUserID string - anthrovePostID string + anthroveUserID models.AnthroveUserID + anthrovePostID models.AnthrovePostID } tests := []struct { name string @@ -254,7 +254,7 @@ func TestEstablishUserToPostLink(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - anthrovePostID: post.ID, + anthrovePostID: models.AnthrovePostID(post.ID), }, wantErr: false, }, diff --git a/internal/postgres/source.go b/internal/postgres/source.go index ec889fd..da13fc3 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -48,15 +48,15 @@ func GetAllSource(ctx context.Context, db *gorm.DB) ([]models.Source, error) { return sources, nil } -// GetSourceByURL returns the first source it finds based on the domain -func GetSourceByURL(ctx context.Context, db *gorm.DB, domain string) (*models.Source, error) { +// GetSourceByDomain returns the first source it finds based on the domain +func GetSourceByDomain(ctx context.Context, db *gorm.DB, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) { var sources models.Source - if domain == "" { + if sourceDomain == "" { return nil, fmt.Errorf("domain is required") } - result := db.WithContext(ctx).Where("domain = ?", domain).First(&sources) + result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&sources) if result.Error != nil { return nil, result.Error diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go index a6d7863..80c0dc8 100644 --- a/internal/postgres/source_test.go +++ b/internal/postgres/source_test.go @@ -174,7 +174,7 @@ func TestGetSourceNodesByURL(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - domain string + domain models.AnthroveSourceDomain } tests := []struct { name string @@ -215,13 +215,13 @@ func TestGetSourceNodesByURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetSourceByURL(tt.args.ctx, tt.args.db, tt.args.domain) + got, err := GetSourceByDomain(tt.args.ctx, tt.args.db, tt.args.domain) if (err != nil) != tt.wantErr { - t.Errorf("GetSourceByURL() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetSourceByDomain() error = %v, wantErr %v", err, tt.wantErr) return } if !checkSourceNode(got, tt.want) { - t.Errorf("GetSourceByURL() got = %v, want %v", got, tt.want) + t.Errorf("GetSourceByDomain() got = %v, want %v", got, tt.want) } }) } diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 4213b28..a20b352 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -24,7 +24,7 @@ func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { return nil } -func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, PostID string, tag *models.Tag) error { +func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, PostID models.AnthrovePostID, tag *models.Tag) error { if PostID == "" { return fmt.Errorf("PostID is empty") diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index d83d760..bc94c77 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -41,7 +41,7 @@ func TestCreateTagNodeWitRelation(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - PostID string + PostID models.AnthrovePostID tag *models.Tag } tests := []struct { @@ -54,7 +54,7 @@ func TestCreateTagNodeWitRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - PostID: post.ID, + PostID: models.AnthrovePostID(post.ID), tag: tag, }, wantErr: false, @@ -64,7 +64,7 @@ func TestCreateTagNodeWitRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - PostID: post.ID, + PostID: models.AnthrovePostID(post.ID), tag: nil, }, wantErr: true, diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 91282d2..1b4e38f 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -8,7 +8,7 @@ import ( "gorm.io/gorm" ) -func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID string) error { +func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { if anthroveUserID == "" { return fmt.Errorf("anthroveUserID cannot be empty") @@ -31,51 +31,59 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID string) error { return nil } -func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUserID string, sourceDomain string, userID string, username string) error { +func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error { - if anthroveUserID == "" || username == "" || userID == "" { + if anthroveUserID == "" { return fmt.Errorf("anthroveUserID cannot be empty") } + if accountId == "" { + return fmt.Errorf("account_id cannot be empty") + } + + if accountUsername == "" { + return fmt.Errorf("account_username cannot be empty") + } + err := CreateUser(ctx, db, anthroveUserID) if err != nil { return err } source := models.Source{ - Domain: sourceDomain, + BaseModel: models.BaseModel{ID: string(sourceID)}, } if err := db.WithContext(ctx).Where(&source).First(&source).Error; err != nil { log.WithFields(log.Fields{ - "source_domain": sourceDomain, + "source_id": sourceID, }).Error("database: failed to find source") return err } userSource := models.UserSource{ - User: models.User{BaseModel: models.BaseModel{ID: anthroveUserID}}, + User: models.User{BaseModel: models.BaseModel{ID: string(anthroveUserID)}}, SourceID: source.ID, - AccountUsername: username, - AccountID: userID, - UserID: anthroveUserID, + AccountUsername: accountUsername, + AccountID: accountId, + UserID: string(anthroveUserID), } if err := db.WithContext(ctx).FirstOrCreate(&userSource).Error; err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, - "source_domain": sourceDomain, - "account_username": username, - "account_id": userID, + "source_id": sourceID, + "account_username": accountUsername, + "account_id": accountId, }).Error("database: failed to create user-source relationship") return err } log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, - "source_domain": sourceDomain, - "account_username": username, - "account_id": userID, + "source_id": sourceID, + "account_username": accountUsername, + "account_id": accountId, }).Trace("database: created user-source relationship") return nil @@ -143,7 +151,7 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models. return userSourceMap, nil } -func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID string) (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") } @@ -193,9 +201,9 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo return userSourceMap, nil } -func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]string, error) { +func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveUserID, error) { var users []models.User - var userIDs []string + var userIDs []models.AnthroveUserID err := db.WithContext(ctx).Model(&models.User{}).Find(&users).Error if err != nil { @@ -204,7 +212,7 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]string, error) { } for _, user := range users { - userIDs = append(userIDs, user.ID) + userIDs = append(userIDs, models.AnthroveUserID(user.ID)) } log.WithFields(log.Fields{ @@ -214,7 +222,7 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]string, error) { return userIDs, nil } -func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID string, skip int, limit int) (*models.FavoriteList, error) { +func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { var userFavorites []models.UserFavorite var favoritePosts []models.Post diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 3adee0f..6a701da 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -25,7 +25,7 @@ func TestCreateUser(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveUserID string + anthroveUserID models.AnthroveUserID } tests := []struct { name string @@ -72,6 +72,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { // Setup Test source := &models.Source{ + BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", @@ -85,8 +86,8 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveUserID string - sourceDomain string + anthroveUserID models.AnthroveUserID + sourceID models.AnthroveSourceID userID string username string } @@ -96,24 +97,24 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { wantErr bool }{ { - name: "Test 1: Valid anthroveUserID, sourceDomain, userID, username", + name: "Test 1: Valid anthroveUserID, sourceID, userID, username", args: args{ ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceDomain: source.Domain, + sourceID: models.AnthroveSourceID(source.ID), userID: "e1", username: "marius", }, wantErr: false, }, { - name: "Test 2: Invalid anthroveUserID, valid sourceDomain, userID, username", + name: "Test 2: Invalid anthroveUserID, valid sourceID, userID, username", args: args{ ctx: ctx, db: gormDB, anthroveUserID: "2", - sourceDomain: source.Domain, + sourceID: models.AnthroveSourceID(source.ID), userID: "e1", username: "marius", }, @@ -125,19 +126,19 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "", - sourceDomain: source.Domain, + sourceID: models.AnthroveSourceID(source.ID), userID: "e1", username: "marius", }, wantErr: true, }, { - name: "Test 4: invalid sourceDomain", + name: "Test 4: invalid sourceID", args: args{ ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceDomain: "fa.net", + sourceID: "fa.net", userID: "e1", username: "marius", }, @@ -149,7 +150,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceDomain: source.Domain, + sourceID: models.AnthroveSourceID(source.ID), userID: "", username: "marius", }, @@ -161,7 +162,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceDomain: source.Domain, + sourceID: models.AnthroveSourceID(source.ID), userID: "aa", username: "", }, @@ -170,7 +171,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CreateUserWithRelationToSource(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceDomain, tt.args.userID, tt.args.username); (err != nil) != tt.wantErr { + if err := CreateUserWithRelationToSource(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID, tt.args.userID, tt.args.username); (err != nil) != tt.wantErr { t.Errorf("CreateUserWithRelationToSource() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -188,7 +189,7 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { // Setup Test - users := []string{"1", "2", "3"} + users := []models.AnthroveUserID{"1", "2", "3"} for _, user := range users { err = CreateUser(ctx, gormDB, user) @@ -205,7 +206,7 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { tests := []struct { name string args args - want []string + want []models.AnthroveUserID wantErr bool }{ { @@ -264,7 +265,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { t.Fatal(err) } - err = CreateUserWithRelationToSource(ctx, gormDB, "1", source.Domain, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, "1", models.AnthroveSourceID(expectedResult["e621"].SourceID), expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } @@ -274,7 +275,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { ctx context.Context db *gorm.DB anthroveUserID models.AnthroveUserID - sourceID string + sourceID models.AnthroveSourceID } tests := []struct { name string @@ -288,7 +289,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceID: source.ID, + sourceID: models.AnthroveSourceID(source.ID), }, want: expectedResult, wantErr: false, @@ -299,7 +300,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "22", - sourceID: source.ID, + sourceID: models.AnthroveSourceID(source.ID), }, want: nil, wantErr: true, @@ -321,7 +322,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "", - sourceID: source.ID, + sourceID: models.AnthroveSourceID(source.ID), }, want: nil, wantErr: true, @@ -362,6 +363,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { }) } } + func TestGetUserFavoriteNodeWithPagination(t *testing.T) { // Setup trow away containert ctx := context.Background() @@ -420,7 +422,7 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { if err != nil { t.Fatal(err) } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", expectedResultPost.ID) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(expectedResultPost.ID)) if err != nil { t.Fatal(err) } @@ -430,7 +432,7 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { type args struct { ctx context.Context db *gorm.DB - anthroveUserID string + anthroveUserID models.AnthroveUserID skip int limit int } @@ -492,7 +494,7 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { } func TestGetUserFavoritesCount(t *testing.T) { - // Setup trow away containert + // Setup trow away container ctx := context.Background() container, gormDB, err := test.StartPostgresContainer(ctx) if err != nil { @@ -539,7 +541,7 @@ func TestGetUserFavoritesCount(t *testing.T) { if err != nil { t.Fatal(err) } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", post.ID) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) if err != nil { t.Fatal(err) } @@ -613,6 +615,7 @@ func TestGetUserSourceLinks(t *testing.T) { // Setup Test eSource := &models.Source{ + BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, DisplayName: "e621", Domain: "e621.net", } @@ -622,6 +625,7 @@ func TestGetUserSourceLinks(t *testing.T) { } faSource := &models.Source{ + BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "2")}, DisplayName: "fa", Domain: "fa.net", } @@ -648,11 +652,11 @@ func TestGetUserSourceLinks(t *testing.T) { }, } - err = CreateUserWithRelationToSource(ctx, gormDB, "1", eSource.Domain, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, "1", models.AnthroveSourceID(eSource.ID), expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } - err = CreateUserWithRelationToSource(ctx, gormDB, "1", faSource.Domain, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, "1", models.AnthroveSourceID(faSource.ID), expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) if err != nil { t.Fatal(err) } @@ -720,7 +724,7 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { if err != nil { t.Fatal(err) } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", post.ID) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) if err != nil { t.Fatal(err) } @@ -733,7 +737,7 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { } for i, tag := range tags { - err = CreateTagAndReferenceToPost(ctx, gormDB, posts[i].ID, &tag) + err = CreateTagAndReferenceToPost(ctx, gormDB, models.AnthrovePostID(posts[i].ID), &tag) if err != nil { t.Fatal(err) } diff --git a/pkg/database/database.go b/pkg/database/database.go index f0c74f0..ee0a644 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -10,7 +10,7 @@ type OtterSpace interface { Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error // CreateUserWithRelationToSource adds a user with a relation to a source. - CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error + CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error // CreateSource adds a new source to the database. CreateSource(ctx context.Context, anthroveSource *models.Source) error @@ -22,22 +22,22 @@ type OtterSpace interface { CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error // CreateReferenceBetweenPostAndSource links a post with a source. - CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveSourceDomain string, anthrovePostRelationship *models.PostReference) error + CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error // CreateReferenceBetweenUserAndPost links a user with a post. - CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error + CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthrovePostID, anthrovePostID models.AnthrovePostID) error // CheckReferenceBetweenUserAndPost checks if a user-post link exists. - CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) + CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID models.AnthrovePostID) (bool, error) // GetPostByAnthroveID retrieves a post by its Anthrove ID. GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) - // GetPostBySourceURL retrieves a post by its source URL. - GetPostBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) + // GetPostByURL retrieves a post by its source URL. + GetPostByURL(ctx context.Context, sourceUrl string) (*models.Post, error) // GetPostBySourceID retrieves a post by its source ID. - GetPostBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) + GetPostBySourceID(ctx context.Context, sourceID models.AnthroveSourceID) (*models.Post, error) // GetUserFavoritesCount retrieves the count of a user's favorites. GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) @@ -46,7 +46,7 @@ type OtterSpace interface { GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) // GetUserSourceBySourceID retrieves a specified source link of a user. - GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID string) (map[string]models.UserSource, error) + GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) // GetAllAnthroveUserIDs retrieves all Anthrove user IDs. GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) @@ -63,6 +63,6 @@ type OtterSpace interface { // GetAllSources retrieves all sources. GetAllSources(ctx context.Context) ([]models.Source, error) - // GetSourceByURL retrieves a source by its URL. - GetSourceByURL(ctx context.Context, sourceUrl string) (*models.Source, error) + // GetSourceByDomain retrieves a source by its URL. + GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) } diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 3503deb..0aa504d 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -64,8 +64,8 @@ func (p *postgresqlConnection) Connect(_ context.Context, endpoint string, usern return nil } -func (p *postgresqlConnection) CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDomain string, userID string, username string) error { - return postgres.CreateUserWithRelationToSource(ctx, p.db, anthroveUserID, sourceDomain, userID, userID) +func (p *postgresqlConnection) CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error { + return postgres.CreateUserWithRelationToSource(ctx, p.db, anthroveUserID, sourceID, accountId, accountUsername) } func (p *postgresqlConnection) CreateSource(ctx context.Context, anthroveSource *models.Source) error { @@ -80,28 +80,28 @@ func (p *postgresqlConnection) CreateTagAndReferenceToPost(ctx context.Context, return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag) } -func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain string, anthrovePostRelationship *models.PostReference) error { - return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain, anthrovePostRelationship) +func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { + return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain) } -func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUser *models.User, anthrovePost *models.Post) error { - return postgres.CreateReferenceBetweenUserAndPost(ctx, p.db, anthroveUser.ID, anthrovePost.ID) +func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthrovePostID, anthrovePostID models.AnthrovePostID) error { + return postgres.CreateReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID) } -func (p *postgresqlConnection) CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID string, sourceUrl string) (bool, error) { - return postgres.CheckReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, models.AnthrovePostID(sourcePostID)) +func (p *postgresqlConnection) CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { + return postgres.CheckReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID) } func (p *postgresqlConnection) GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) { return postgres.GetPostByAnthroveID(ctx, p.db, anthrovePost.ID) } -func (p *postgresqlConnection) GetPostBySourceURL(ctx context.Context, sourceUrl string) (*models.Post, error) { - return postgres.GetPostBySourceURL(ctx, p.db, sourceUrl) +func (p *postgresqlConnection) GetPostByURL(ctx context.Context, sourceUrl string) (*models.Post, error) { + return postgres.GetPostByURL(ctx, p.db, sourceUrl) } -func (p *postgresqlConnection) GetPostBySourceID(ctx context.Context, sourcePostID string) (*models.Post, error) { - return postgres.GetPostBySourceID(ctx, p.db, sourcePostID) +func (p *postgresqlConnection) GetPostBySourceID(ctx context.Context, sourceID models.AnthroveSourceID) (*models.Post, error) { + return postgres.GetPostBySourceID(ctx, p.db, sourceID) } func (p *postgresqlConnection) GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) { @@ -112,8 +112,8 @@ func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveU return postgres.GetUserSourceLinks(ctx, p.db, anthroveUserID) } -func (p *postgresqlConnection) GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceDisplayName string) (map[string]models.UserSource, error) { - return postgres.GetSpecifiedUserSourceLink(ctx, p.db, anthroveUserID, sourceDisplayName) +func (p *postgresqlConnection) GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) { + return postgres.GetUserSourceBySourceID(ctx, p.db, anthroveUserID, sourceID) } func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { @@ -136,8 +136,8 @@ func (p *postgresqlConnection) GetAllSources(ctx context.Context) ([]models.Sour return postgres.GetAllSource(ctx, p.db) } -func (p *postgresqlConnection) GetSourceByURL(ctx context.Context, sourceUrl string) (*models.Source, error) { - return postgres.GetSourceByURL(ctx, p.db, sourceUrl) +func (p *postgresqlConnection) GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) { + return postgres.GetSourceByDomain(ctx, p.db, sourceDomain) } func (p *postgresqlConnection) migrateDatabase(connectionString string) error { diff --git a/pkg/models/const.go b/pkg/models/const.go index a9c3cf6..5b0e59a 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -2,6 +2,9 @@ package models type AnthroveUserID string type AnthrovePostID string +type AnthroveSourceID string +type AnthroveSourceDomain string + type Rating string type TagType string @@ -24,7 +27,6 @@ const ( ) func (r *Rating) Convert(e621Rating string) { - switch e621Rating { case "e": *r = NSFW @@ -35,5 +37,4 @@ func (r *Rating) Convert(e621Rating string) { default: *r = Unknown } - } diff --git a/pkg/models/orm.go b/pkg/models/orm.go index ff7bb64..7e74329 100644 --- a/pkg/models/orm.go +++ b/pkg/models/orm.go @@ -6,6 +6,12 @@ import ( "time" ) +type ID interface { + AnthroveUserID + AnthroveSourceID + AnthrovePostID +} + type BaseModel struct { ID string `gorm:"primaryKey"` CreatedAt time.Time From a5f41e7a2d887b7f6944ab7a0778261c7ef6c689 Mon Sep 17 00:00:00 2001 From: soxx Date: Sun, 23 Jun 2024 22:39:54 +0200 Subject: [PATCH 069/124] fix(postgres): function mismatch with new types Signed-off-by: soxx --- pkg/database/database.go | 2 +- pkg/database/postgres.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/database/database.go b/pkg/database/database.go index ee0a644..cebec64 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -25,7 +25,7 @@ type OtterSpace interface { CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error // CreateReferenceBetweenUserAndPost links a user with a post. - CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthrovePostID, anthrovePostID models.AnthrovePostID) error + CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error // CheckReferenceBetweenUserAndPost checks if a user-post link exists. CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID models.AnthrovePostID) (bool, error) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 0aa504d..0aac161 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -84,7 +84,7 @@ func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.C return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain) } -func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthrovePostID, anthrovePostID models.AnthrovePostID) error { +func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { return postgres.CreateReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID) } @@ -93,7 +93,7 @@ func (p *postgresqlConnection) CheckReferenceBetweenUserAndPost(ctx context.Cont } func (p *postgresqlConnection) GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) { - return postgres.GetPostByAnthroveID(ctx, p.db, anthrovePost.ID) + return postgres.GetPostByAnthroveID(ctx, p.db, models.AnthrovePostID(anthrovePost.ID)) } func (p *postgresqlConnection) GetPostByURL(ctx context.Context, sourceUrl string) (*models.Post, error) { From 1ed6b912149ff619c6803fc8a437cc38fd8f79f0 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 24 Jun 2024 11:58:29 +0200 Subject: [PATCH 070/124] ci(postgres): implemented CI for build check in sonarqube Signed-off-by: SoXX --- .gitea/workflows/ build_check.yaml | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .gitea/workflows/ build_check.yaml diff --git a/.gitea/workflows/ build_check.yaml b/.gitea/workflows/ build_check.yaml new file mode 100644 index 0000000..db9f671 --- /dev/null +++ b/.gitea/workflows/ build_check.yaml @@ -0,0 +1,39 @@ +name: Gitea Build Check +run-name: ${{ gitea.actor }} is testing the build +on: + push: + branches: + - main + pull_request: + branches: [ "main" ] + +jobs: + Build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Setup Go environment + uses: https://github.com/actions/setup-go@v3 + with: + # The Go version to download (if necessary) and use. Supports semver spec and ranges. + go-version: 1.22.0 # optional + # Path to the go.mod file. + go-version-file: ./go.mod # optional + # Set this option to true if you want the action to always check for the latest available version that satisfies the version spec + check-latest: true # optional + # Used to specify whether caching is needed. Set to true, if you'd like to enable caching. + cache: true # optional + + - name: Execute Go Test files with coverage report + run: go test -v ./... -json -coverprofile="coverage.out" > "test-report.out" + + - uses: sonarsource/sonarqube-scan-action@master + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} + with: + args: > + -Dsonar.projectKey=Anthrove---OtterSpace-SDK \ No newline at end of file From bfa074fd9be4c2a259a16ca456c0a13796cc94a6 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 24 Jun 2024 12:02:39 +0200 Subject: [PATCH 071/124] ci(postgres): fixed trigger Signed-off-by: SoXX --- .gitea/workflows/ build_check.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/ build_check.yaml b/.gitea/workflows/ build_check.yaml index db9f671..193bcfd 100644 --- a/.gitea/workflows/ build_check.yaml +++ b/.gitea/workflows/ build_check.yaml @@ -3,7 +3,7 @@ run-name: ${{ gitea.actor }} is testing the build on: push: branches: - - main + - develop/postgresql pull_request: branches: [ "main" ] From b40d93c993cbd4caf1ed7239a147cc002396187e Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 24 Jun 2024 12:59:51 +0200 Subject: [PATCH 072/124] feat(postgres): config map Signed-off-by: SoXX --- pkg/database/database.go | 3 ++- pkg/database/postgres.go | 18 +++++++++++++----- pkg/models/config.go | 12 ++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 pkg/models/config.go diff --git a/pkg/database/database.go b/pkg/database/database.go index cebec64..6db8e3c 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -2,12 +2,13 @@ package database import ( "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" ) type OtterSpace interface { // Connect establishes a connection to the database. - Connect(ctx context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error + Connect(ctx context.Context, config models.DatabaseConfig) error // CreateUserWithRelationToSource adds a user with a relation to a source. CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 0aac161..7c2371d 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -5,6 +5,10 @@ import ( "database/sql" "embed" "fmt" + log2 "log" + "os" + "time" + "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" _ "github.com/lib/pq" @@ -13,9 +17,6 @@ import ( gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" logger2 "gorm.io/gorm/logger" - log2 "log" - "os" - "time" ) //go:embed migrations/*.sql @@ -33,8 +34,15 @@ func NewPostgresqlConnection(debugOutput bool) OtterSpace { } } -func (p *postgresqlConnection) Connect(_ context.Context, endpoint string, username string, password string, database string, port int, ssl string, timezone string) error { - dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", endpoint, username, password, database, port, ssl, timezone) +func (p *postgresqlConnection) Connect(_ context.Context, config models.DatabaseConfig) error { + var localSSL string + if config.SSL { + localSSL = "require" + } else { + localSSL = "disable" + } + + dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", config.Endpoint, config.Username, config.Password, config.Database, config.Port, localSSL, config.Timezone) var err error err = p.migrateDatabase(dsn) diff --git a/pkg/models/config.go b/pkg/models/config.go new file mode 100644 index 0000000..2013b95 --- /dev/null +++ b/pkg/models/config.go @@ -0,0 +1,12 @@ +package models + +type DatabaseConfig struct { + Endpoint string `env:"DB_ENDPOINT,required"` + Username string `env:"DB_USERNAME,required"` + Password string `env:"DB_PASSWORD,required,unset"` + Database string `env:"DB_DATABASE,required"` + Port int `env:"DB_PORT,required" envDefault:"5432"` + SSL bool `env:"DB_SSL,required" envDefault:"true"` + Timezone string `env:"DB_TIMEZONE,required" envDefault:"Europe/Berlin"` + Debug bool `env:"DB_DEBUG" envDefault:"false"` +} From 57729359d261e3b09239a6dd44e14e1777de6d56 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 24 Jun 2024 13:13:32 +0200 Subject: [PATCH 073/124] feat(postgres): using only gorm Signed-off-by: SoXX --- pkg/database/postgres.go | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 7c2371d..7ce11d4 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -2,7 +2,6 @@ package database import ( "context" - "database/sql" "embed" "fmt" log2 "log" @@ -27,10 +26,9 @@ type postgresqlConnection struct { debug bool } -func NewPostgresqlConnection(debugOutput bool) OtterSpace { +func NewPostgresqlConnection() OtterSpace { return &postgresqlConnection{ - db: nil, - debug: debugOutput, + db: nil, } } @@ -45,13 +43,6 @@ func (p *postgresqlConnection) Connect(_ context.Context, config models.Database dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", config.Endpoint, config.Username, config.Password, config.Database, config.Port, localSSL, config.Timezone) var err error - err = p.migrateDatabase(dsn) - if err != nil { - return err - } - - log.Infof("OtterSpace: migration compleate") - dbLogger := logger2.New(log2.New(os.Stdout, "\r\n", log2.LstdFlags), logger2.Config{ SlowThreshold: 200 * time.Millisecond, LogLevel: logger2.Warn, @@ -67,7 +58,14 @@ func (p *postgresqlConnection) Connect(_ context.Context, config models.Database return err } - log.Infof("OtterSpace: postgres connection established") + log.Infof("OtterSpace: database connection established") + + err = p.migrateDatabase(db) + if err != nil { + return err + } + + log.Infof("OtterSpace: migration compleate") return nil } @@ -148,11 +146,11 @@ func (p *postgresqlConnection) GetSourceByDomain(ctx context.Context, sourceDoma return postgres.GetSourceByDomain(ctx, p.db, sourceDomain) } -func (p *postgresqlConnection) migrateDatabase(connectionString string) error { +func (p *postgresqlConnection) migrateDatabase(dbPool *gorm.DB) error { dialect := "postgres" migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"} - db, err := sql.Open(dialect, connectionString) + db, err := dbPool.DB() if err != nil { return fmt.Errorf("postgres migration: %v", err) } From 30fa03ef9acad93082836b92c4b1b36782e6dc12 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 24 Jun 2024 14:28:09 +0200 Subject: [PATCH 074/124] feat(postgres): added more tests Signed-off-by: SoXX --- internal/utils/slices_test.go | 60 +++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 2 ++ pkg/database/postgres_test.go | 26 +++++++++++++++ pkg/models/const_test.go | 59 ++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 internal/utils/slices_test.go create mode 100644 pkg/database/postgres_test.go create mode 100644 pkg/models/const_test.go diff --git a/internal/utils/slices_test.go b/internal/utils/slices_test.go new file mode 100644 index 0000000..9f8cdc6 --- /dev/null +++ b/internal/utils/slices_test.go @@ -0,0 +1,60 @@ +package utils + +import ( + "reflect" + "testing" +) + +func TestGetOrDefault(t *testing.T) { + type args struct { + data map[string]any + key string + defaultVal any + } + tests := []struct { + name string + args args + want any + }{ + { + name: "Test 1: Nil map", + args: args{ + data: nil, + key: "key1", + defaultVal: "default", + }, + want: "default", + }, + { + name: "Test 2: Existing key", + args: args{ + data: map[string]interface{}{ + "key1": "value1", + "key2": "value2", + }, + key: "key1", + defaultVal: "default", + }, + want: "value1", + }, + { + name: "Test 3: Non-existing key", + args: args{ + data: map[string]interface{}{ + "key1": "value1", + "key2": "value2", + }, + key: "key3", + defaultVal: "default", + }, + want: "default", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := GetOrDefault(tt.args.data, tt.args.key, tt.args.defaultVal); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetOrDefault() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 7ce11d4..44654aa 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -40,6 +40,8 @@ func (p *postgresqlConnection) Connect(_ context.Context, config models.Database localSSL = "disable" } + p.debug = config.Debug + dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", config.Endpoint, config.Username, config.Password, config.Database, config.Port, localSSL, config.Timezone) var err error diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go new file mode 100644 index 0000000..0249f43 --- /dev/null +++ b/pkg/database/postgres_test.go @@ -0,0 +1,26 @@ +package database + +import ( + "testing" +) + +func TestNewPostgresqlConnection(t *testing.T) { + // Test + tests := []struct { + name string + want OtterSpace + }{ + { + name: "Test 1: Create new postgresql connection", + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.want != NewPostgresqlConnection() { + } else { + t.Errorf("NewPostgresqlConnection() = %s", tt.want) + } + }) + } +} diff --git a/pkg/models/const_test.go b/pkg/models/const_test.go new file mode 100644 index 0000000..cba0f75 --- /dev/null +++ b/pkg/models/const_test.go @@ -0,0 +1,59 @@ +package models + +import ( + "reflect" + "testing" +) + +func TestRating_Convert(t *testing.T) { + type args struct { + e621Rating string + } + tests := []struct { + name string + r *Rating + args args + want Rating + }{ + { + name: "Test 1: NSFW Rating", + r: new(Rating), + args: args{ + e621Rating: "e", + }, + want: NSFW, + }, + { + name: "Test 2: Questionable Rating", + r: new(Rating), + args: args{ + e621Rating: "q", + }, + want: Questionable, + }, + { + name: "Test 3: SFW Rating", + r: new(Rating), + args: args{ + e621Rating: "s", + }, + want: SFW, + }, + { + name: "Test 4: Unknown Rating", + r: new(Rating), + args: args{ + e621Rating: "x", + }, + want: Unknown, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.r.Convert(tt.args.e621Rating) + if !reflect.DeepEqual(*tt.r, tt.want) { + t.Errorf("Convert() = %v, want %v", *tt.r, tt.want) + } + }) + } +} From 2a752adcacb389cfc4b86b47d943567c8a7f9e3f Mon Sep 17 00:00:00 2001 From: soxx Date: Mon, 24 Jun 2024 17:07:41 +0200 Subject: [PATCH 075/124] test(postgres): added more tests Signed-off-by: soxx --- internal/postgres/relationships.go | 4 +- internal/postgres/user.go | 8 +-- pkg/models/orm_test.go | 55 +++++++++++++++++ pkg/models/post.go | 2 +- pkg/models/postReference_test.go | 42 +++++++++++++ pkg/models/post_test.go | 38 ++++++++++++ pkg/models/source_test.go | 40 +++++++++++++ pkg/models/tag_test.go | 96 ++++++++++++++++++++++++++++++ pkg/models/user.go | 4 +- pkg/models/userFavorite.go | 4 +- pkg/models/userFavorite_test.go | 37 ++++++++++++ pkg/models/userSource_test.go | 42 +++++++++++++ pkg/models/user_test.go | 34 +++++++++++ 13 files changed, 395 insertions(+), 11 deletions(-) create mode 100644 pkg/models/orm_test.go create mode 100644 pkg/models/postReference_test.go create mode 100644 pkg/models/post_test.go create mode 100644 pkg/models/source_test.go create mode 100644 pkg/models/tag_test.go create mode 100644 pkg/models/userFavorite_test.go create mode 100644 pkg/models/userSource_test.go create mode 100644 pkg/models/user_test.go diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index 5c268f8..f719704 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -37,7 +37,7 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr } func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { - userFavorite := models.UserFavorite{ + userFavorite := models.UserFavorites{ UserID: string(anthroveUserID), PostID: string(anthrovePostID), } @@ -57,7 +57,7 @@ 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) { var count int64 - err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count).Error + err := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ? AND post_id = ?", string(anthroveUserID), string(anthrovePostID)).Count(&count).Error if err != nil { return false, err } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 1b4e38f..9cdc2da 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -95,7 +95,7 @@ func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID mode } var count int64 - err := db.WithContext(ctx).Model(&models.UserFavorite{}).Where("user_id = ?", string(anthroveUserID)).Count(&count).Error + err := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Count(&count).Error if err != nil { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, @@ -223,10 +223,10 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU } func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { - var userFavorites []models.UserFavorite + var userFavorites []models.UserFavorites var favoritePosts []models.Post - err := db.WithContext(ctx).Model(&models.UserFavorite{}).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 { log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, @@ -262,7 +262,7 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse } func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { - var userFavorites []models.UserFavorite + var userFavorites []models.UserFavorites err := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites).Error if err != nil { log.WithFields(log.Fields{ diff --git a/pkg/models/orm_test.go b/pkg/models/orm_test.go new file mode 100644 index 0000000..d18fd2b --- /dev/null +++ b/pkg/models/orm_test.go @@ -0,0 +1,55 @@ +package models + +import ( + "gorm.io/gorm" + "testing" + "time" +) + +func TestBaseModel_BeforeCreate(t *testing.T) { + type fields struct { + ID string + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt + } + type args struct { + db *gorm.DB + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "Test 1: Prefilled ID", + fields: fields{ + ID: "1", + }, + args: args{db: nil}, + wantErr: false, + }, + { + name: "Test 1: Autogenerate ID", + fields: fields{ + ID: "", + }, + args: args{db: nil}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + base := &BaseModel{ + ID: tt.fields.ID, + CreatedAt: tt.fields.CreatedAt, + UpdatedAt: tt.fields.UpdatedAt, + DeletedAt: tt.fields.DeletedAt, + } + if err := base.BeforeCreate(tt.args.db); (err != nil) != tt.wantErr { + t.Errorf("BeforeCreate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/models/post.go b/pkg/models/post.go index bac8a50..9aef5e7 100644 --- a/pkg/models/post.go +++ b/pkg/models/post.go @@ -5,7 +5,7 @@ type Post struct { BaseModel Rating Rating `gorm:"type:enum('safe','questionable','explicit')"` Tags []Tag `gorm:"many2many:post_tags;"` - Favorites []UserFavorite `gorm:"foreignKey:PostID"` + Favorites []UserFavorites `gorm:"foreignKey:PostID"` References []PostReference `gorm:"foreignKey:PostID"` } diff --git a/pkg/models/postReference_test.go b/pkg/models/postReference_test.go new file mode 100644 index 0000000..232a695 --- /dev/null +++ b/pkg/models/postReference_test.go @@ -0,0 +1,42 @@ +package models + +import "testing" + +func TestPostReference_TableName(t *testing.T) { + type fields struct { + PostID string + SourceID string + URL string + SourcePostID string + FullFileURL string + PreviewFileURL string + SampleFileURL string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: PostReference", + fields: fields{}, + want: "PostReference", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + po := PostReference{ + PostID: tt.fields.PostID, + SourceID: tt.fields.SourceID, + URL: tt.fields.URL, + SourcePostID: tt.fields.SourcePostID, + FullFileURL: tt.fields.FullFileURL, + PreviewFileURL: tt.fields.PreviewFileURL, + SampleFileURL: tt.fields.SampleFileURL, + } + if got := po.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/models/post_test.go b/pkg/models/post_test.go new file mode 100644 index 0000000..c90852e --- /dev/null +++ b/pkg/models/post_test.go @@ -0,0 +1,38 @@ +package models + +import "testing" + +func TestPost_TableName(t *testing.T) { + type fields struct { + BaseModel BaseModel + Rating Rating + Tags []Tag + Favorites []UserFavorites + References []PostReference + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: Is name Post", + fields: fields{}, + want: "Post", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + po := Post{ + BaseModel: tt.fields.BaseModel, + Rating: tt.fields.Rating, + Tags: tt.fields.Tags, + Favorites: tt.fields.Favorites, + References: tt.fields.References, + } + if got := po.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/models/source_test.go b/pkg/models/source_test.go new file mode 100644 index 0000000..1a5ff8c --- /dev/null +++ b/pkg/models/source_test.go @@ -0,0 +1,40 @@ +package models + +import "testing" + +func TestSource_TableName(t *testing.T) { + type fields struct { + BaseModel BaseModel + DisplayName string + Domain string + Icon string + UserSources []UserSource + References []PostReference + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: Is name Source", + fields: fields{}, + want: "Source", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + so := Source{ + BaseModel: tt.fields.BaseModel, + DisplayName: tt.fields.DisplayName, + Domain: tt.fields.Domain, + Icon: tt.fields.Icon, + UserSources: tt.fields.UserSources, + References: tt.fields.References, + } + if got := so.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/models/tag_test.go b/pkg/models/tag_test.go new file mode 100644 index 0000000..6f66b18 --- /dev/null +++ b/pkg/models/tag_test.go @@ -0,0 +1,96 @@ +package models + +import "testing" + +func TestTagAlias_TableName(t *testing.T) { + type fields struct { + Name string + TagID string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: Is Name TagAlias", + fields: fields{}, + want: "TagAlias", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ta := TagAlias{ + Name: tt.fields.Name, + TagID: tt.fields.TagID, + } + if got := ta.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestTagGroup_TableName(t *testing.T) { + type fields struct { + Name string + TagID string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: Is name TagGroup", + fields: fields{}, + want: "TagGroup", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ta := TagGroup{ + Name: tt.fields.Name, + TagID: tt.fields.TagID, + } + if got := ta.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestTag_TableName(t *testing.T) { + type fields struct { + Name string + Type TagType + Aliases []TagAlias + Groups []TagGroup + Posts []Post + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: Is name Tag", + fields: fields{}, + want: "Tag", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ta := Tag{ + Name: tt.fields.Name, + Type: tt.fields.Type, + Aliases: tt.fields.Aliases, + Groups: tt.fields.Groups, + Posts: tt.fields.Posts, + } + if got := ta.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/models/user.go b/pkg/models/user.go index 96dd70e..7f723e6 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -3,8 +3,8 @@ package models // User model type User struct { BaseModel - Favorites []UserFavorite `gorm:"foreignKey:UserID"` - Sources []UserSource `gorm:"foreignKey:UserID"` + Favorites []UserFavorites `gorm:"foreignKey:UserID"` + Sources []UserSource `gorm:"foreignKey:UserID"` } func (User) TableName() string { diff --git a/pkg/models/userFavorite.go b/pkg/models/userFavorite.go index 8ccd106..3bebe91 100644 --- a/pkg/models/userFavorite.go +++ b/pkg/models/userFavorite.go @@ -2,13 +2,13 @@ package models import "time" -type UserFavorite struct { +type UserFavorites struct { UserID string `gorm:"primaryKey"` PostID string `gorm:"primaryKey"` CreatedAt time.Time } -func (UserFavorite) TableName() string { +func (UserFavorites) TableName() string { return "UserFavorites" } diff --git a/pkg/models/userFavorite_test.go b/pkg/models/userFavorite_test.go new file mode 100644 index 0000000..3b69143 --- /dev/null +++ b/pkg/models/userFavorite_test.go @@ -0,0 +1,37 @@ +package models + +import ( + "testing" + "time" +) + +func TestUserFavorite_TableName(t *testing.T) { + type fields struct { + UserID string + PostID string + CreatedAt time.Time + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: Is name UserFavorites", + fields: fields{}, + want: "UserFavorites", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + us := UserFavorites{ + UserID: tt.fields.UserID, + PostID: tt.fields.PostID, + CreatedAt: tt.fields.CreatedAt, + } + if got := us.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/models/userSource_test.go b/pkg/models/userSource_test.go new file mode 100644 index 0000000..ff8cd95 --- /dev/null +++ b/pkg/models/userSource_test.go @@ -0,0 +1,42 @@ +package models + +import "testing" + +func TestUserSource_TableName(t *testing.T) { + type fields struct { + User User + UserID string + Source Source + SourceID string + ScrapeTimeInterval string + AccountUsername string + AccountID string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: Is name UserSource", + fields: fields{}, + want: "UserSource", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + us := UserSource{ + User: tt.fields.User, + UserID: tt.fields.UserID, + Source: tt.fields.Source, + SourceID: tt.fields.SourceID, + ScrapeTimeInterval: tt.fields.ScrapeTimeInterval, + AccountUsername: tt.fields.AccountUsername, + AccountID: tt.fields.AccountID, + } + if got := us.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/models/user_test.go b/pkg/models/user_test.go new file mode 100644 index 0000000..fa2c511 --- /dev/null +++ b/pkg/models/user_test.go @@ -0,0 +1,34 @@ +package models + +import "testing" + +func TestUser_TableName(t *testing.T) { + type fields struct { + BaseModel BaseModel + Favorites []UserFavorites + Sources []UserSource + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: Is name User", + fields: fields{}, + want: "User", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + us := User{ + BaseModel: tt.fields.BaseModel, + Favorites: tt.fields.Favorites, + Sources: tt.fields.Sources, + } + if got := us.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} From 97758b180ebbc6fb8e16542d616b790400d25e3c Mon Sep 17 00:00:00 2001 From: soxx Date: Mon, 24 Jun 2024 22:07:34 +0200 Subject: [PATCH 076/124] test(postgres): added more tests and some fixes Signed-off-by: soxx --- internal/postgres/post_test.go | 4 +- pkg/database/database.go | 2 +- pkg/database/postgres.go | 4 +- pkg/database/postgres_test.go | 766 +++++++++++++++++++++++++++++++++ test/helper.go | 42 ++ 5 files changed, 814 insertions(+), 4 deletions(-) diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index cf2ebc4..70d2b37 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -348,8 +348,10 @@ func TestGetPostBySourceID(t *testing.T) { func checkPost(got *models.Post, want *models.Post) bool { - if got == nil { + if got == nil && want == nil { return true + } else if got == nil || want == nil { + return false } if got.ID != want.ID { diff --git a/pkg/database/database.go b/pkg/database/database.go index 6db8e3c..10d203a 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -32,7 +32,7 @@ type OtterSpace interface { CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID models.AnthrovePostID) (bool, error) // GetPostByAnthroveID retrieves a post by its Anthrove ID. - GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) + GetPostByAnthroveID(ctx context.Context, anthrovePostID models.AnthrovePostID) (*models.Post, error) // GetPostByURL retrieves a post by its source URL. GetPostByURL(ctx context.Context, sourceUrl string) (*models.Post, error) diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 44654aa..4245c9b 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -100,8 +100,8 @@ func (p *postgresqlConnection) CheckReferenceBetweenUserAndPost(ctx context.Cont return postgres.CheckReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID) } -func (p *postgresqlConnection) GetPostByAnthroveID(ctx context.Context, anthrovePost *models.Post) (*models.Post, error) { - return postgres.GetPostByAnthroveID(ctx, p.db, models.AnthrovePostID(anthrovePost.ID)) +func (p *postgresqlConnection) GetPostByAnthroveID(ctx context.Context, anthrovePostID models.AnthrovePostID) (*models.Post, error) { + return postgres.GetPostByAnthroveID(ctx, p.db, anthrovePostID) } func (p *postgresqlConnection) GetPostByURL(ctx context.Context, sourceUrl string) (*models.Post, error) { diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index 0249f43..d14a354 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -1,6 +1,11 @@ package database import ( + "context" + "fmt" + "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + "git.dragse.it/anthrove/otter-space-sdk/test" "testing" ) @@ -24,3 +29,764 @@ func TestNewPostgresqlConnection(t *testing.T) { }) } } + +func Test_postgresqlConnection_Connect(t *testing.T) { + + // Setup trow away container + ctx := context.Background() + container, _, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Tests + + dbConfig, err := test.DatabaseModesFromConnectionString(ctx, container) + if err != nil { + t.Fatalf("Could not parse database config: %v", err) + } + + // Test + type args struct { + in0 context.Context + config models.DatabaseConfig + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Connect to postgresql connection", + args: args{ + in0: ctx, + config: *dbConfig, + }, + wantErr: false, + }, + { + name: "Test 1: Empty connection config", + args: args{ + in0: ctx, + config: models.DatabaseConfig{}, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{} + if err := p.Connect(tt.args.in0, tt.args.config); (err != nil) != tt.wantErr { + t.Errorf("Connect() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + source := &models.Source{ + BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + } + err = postgres.CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + sourceID models.AnthroveSourceID + accountId string + accountUsername string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid anthroveUserID, sourceID, accountId, accountUsername", + args: args{ + ctx: ctx, + anthroveUserID: "1", + sourceID: models.AnthroveSourceID(source.ID), + accountId: "e1", + accountUsername: "marius", + }, + wantErr: false, + }, + { + name: "Test 2: Invalid anthroveUserID, valid sourceID, accountId, accountUsername", + args: args{ + ctx: ctx, + anthroveUserID: "2", + sourceID: models.AnthroveSourceID(source.ID), + accountId: "e1", + accountUsername: "marius", + }, + wantErr: true, + }, + { + name: "Test 3: Empty anthroveUserID", + args: args{ + ctx: ctx, + anthroveUserID: "", + sourceID: models.AnthroveSourceID(source.ID), + accountId: "e1", + accountUsername: "marius", + }, + wantErr: true, + }, + { + name: "Test 4: invalid sourceID", + args: args{ + ctx: ctx, + anthroveUserID: "1", + sourceID: "fa.net", + accountId: "e1", + accountUsername: "marius", + }, + wantErr: true, + }, + { + name: "Test 5: no accountId", + args: args{ + ctx: ctx, + anthroveUserID: "1", + sourceID: models.AnthroveSourceID(source.ID), + accountId: "", + accountUsername: "marius", + }, + wantErr: true, + }, + { + name: "Test 6: no accountUsername", + args: args{ + ctx: ctx, + anthroveUserID: "1", + sourceID: models.AnthroveSourceID(source.ID), + accountId: "aa", + accountUsername: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.CreateUserWithRelationToSource(tt.args.ctx, tt.args.anthroveUserID, tt.args.sourceID, tt.args.accountId, tt.args.accountUsername); (err != nil) != tt.wantErr { + t.Errorf("CreateUserWithRelationToSource() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_CreateSource(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validSource := &models.Source{ + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + } + + invalidSource := &models.Source{ + Domain: "", + } + + // Test + type args struct { + ctx context.Context + anthroveSource *models.Source + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid anthroveSource", + args: args{ + ctx: ctx, + anthroveSource: validSource, + }, + wantErr: false, + }, + { + name: "Test 2: inValid anthroveSource", + args: args{ + ctx: ctx, + anthroveSource: invalidSource, + }, + wantErr: true, + }, + { + name: "Test 3: unique anthroveSource", + args: args{ + ctx: ctx, + anthroveSource: validSource, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.CreateSource(tt.args.ctx, tt.args.anthroveSource); (err != nil) != tt.wantErr { + t.Errorf("CreateSource() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_CreatePost(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Tests + + validPost := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + invalidPost := &models.Post{ + Rating: "error", + } + + // Test + type args struct { + ctx context.Context + anthrovePost *models.Post + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthrovePostID and Rating", + args: args{ + ctx: context.Background(), + anthrovePost: validPost, + }, + wantErr: false, + }, + { + name: "Test 2: Invalid Rating", + args: args{ + ctx: context.Background(), + anthrovePost: invalidPost, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.CreatePost(tt.args.ctx, tt.args.anthrovePost); (err != nil) != tt.wantErr { + t.Errorf("CreatePost() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_CreateTagAndReferenceToPost(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = postgres.CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal(err) + } + + tag := &models.Tag{ + Name: "JayTheFerret", + Type: "artist", + } + + // Test + type args struct { + ctx context.Context + anthrovePostID models.AnthrovePostID + anthroveTag *models.Tag + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid PostID and Tag", + args: args{ + ctx: ctx, + anthrovePostID: models.AnthrovePostID(post.ID), + anthroveTag: tag, + }, + wantErr: false, + }, + { + name: "Test 2: Valid PostID and no Tag", + args: args{ + ctx: ctx, + anthrovePostID: models.AnthrovePostID(post.ID), + anthroveTag: nil, + }, + wantErr: true, + }, + { + name: "Test 3: Invalid PostID and valid Tag", + args: args{ + ctx: ctx, + anthrovePostID: "123456", + anthroveTag: tag, + }, + wantErr: true, + }, + { + name: "Test 4: No PostID and valid Tag", + args: args{ + ctx: ctx, + anthrovePostID: "", + anthroveTag: tag, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.CreateTagAndReferenceToPost(tt.args.ctx, tt.args.anthrovePostID, tt.args.anthroveTag); (err != nil) != tt.wantErr { + t.Errorf("CreateTagAndReferenceToPost() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = postgres.CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal(err) + } + + source := &models.Source{ + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + } + err = postgres.CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + anthrovePostID models.AnthrovePostID + sourceDomain models.AnthroveSourceDomain + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthrovePostID and anthroveSourceDomain", + args: args{ + ctx: ctx, + anthrovePostID: models.AnthrovePostID(post.ID), + sourceDomain: "e621.net", + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthrovePostID and Valid anthroveSourceDomain", + args: args{ + ctx: ctx, + anthrovePostID: "123456", + sourceDomain: "e621.net", + }, + wantErr: true, + }, + { + name: "Test 3: Invalid anthroveSourceDomain and Valid AnthrovePostID", + args: args{ + ctx: ctx, + anthrovePostID: "1234", + sourceDomain: "fa.banana", + }, + wantErr: true, + }, + { + name: "Test 4: Invalid anthroveSourceDomain and Invalid AnthrovePostID", + args: args{ + ctx: ctx, + anthrovePostID: "696969", + sourceDomain: "hehe.funny.number", + }, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.CreateReferenceBetweenPostAndSource(tt.args.ctx, tt.args.anthrovePostID, tt.args.sourceDomain); (err != nil) != tt.wantErr { + t.Errorf("CreateReferenceBetweenPostAndSource() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_CreateReferenceBetweenUserAndPost(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + err = postgres.CreateUser(ctx, gormDB, "1") + if err != nil { + t.Fatal(err) + } + + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = postgres.CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + anthrovePostID models.AnthrovePostID + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveUserID and AnthrovePostID", + args: args{ + ctx: ctx, + anthroveUserID: "1", + anthrovePostID: models.AnthrovePostID(post.ID), + }, + wantErr: false, + }, + { + name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", + args: args{ + ctx: ctx, + anthroveUserID: "1", + anthrovePostID: "123456", + }, + wantErr: true, + }, + { + name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + anthroveUserID: "123", + anthrovePostID: "1234", + }, + wantErr: true, + }, + { + name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + anthroveUserID: "123", + anthrovePostID: "123456", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.CreateReferenceBetweenUserAndPost(tt.args.ctx, tt.args.anthroveUserID, tt.args.anthrovePostID); (err != nil) != tt.wantErr { + t.Errorf("CreateReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + err = postgres.CreateUser(ctx, gormDB, "1") + if err != nil { + t.Fatal(err) + } + + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = postgres.CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal(err) + } + + err = postgres.CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + anthrovePostID models.AnthrovePostID + } + tests := []struct { + name string + args args + want bool + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveUserID and AnthrovePostID", + args: args{ + ctx: ctx, + anthroveUserID: "1", + anthrovePostID: models.AnthrovePostID(post.ID), + }, + want: true, + wantErr: false, + }, + { + name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", + args: args{ + ctx: ctx, + anthroveUserID: "1", + anthrovePostID: "qadw", + }, + want: false, + wantErr: false, + }, + { + name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + anthroveUserID: "123", + anthrovePostID: models.AnthrovePostID(post.ID), + }, + want: false, + wantErr: false, + }, + { + name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + anthroveUserID: "123", + anthrovePostID: "123456", + }, + want: false, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.anthroveUserID, tt.args.anthrovePostID) + if (err != nil) != tt.wantErr { + t.Errorf("CheckReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("CheckReferenceBetweenUserAndPost() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetPostByAnthroveID(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Tests + + post := &models.Post{ + BaseModel: models.BaseModel{ + ID: fmt.Sprintf("%025s", "1"), + }, + Rating: "safe", + } + + err = postgres.CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal("Could not create post", err) + } + + // Test + type args struct { + ctx context.Context + anthrovePost models.AnthrovePostID + } + tests := []struct { + name string + args args + want *models.Post + wantErr bool + }{ + { + name: "Test 1: Valid anthrovePostID", + args: args{ + ctx: ctx, + anthrovePost: models.AnthrovePostID(post.ID), + }, + want: post, + wantErr: false, + }, + { + name: "Test 2: No anthrovePostID", + args: args{ + ctx: ctx, + anthrovePost: "nil", + }, + want: nil, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetPostByAnthroveID(tt.args.ctx, tt.args.anthrovePost) + if (err != nil) != tt.wantErr { + t.Errorf("GetPostByAnthroveID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkPost(got, tt.want) { + t.Errorf("GetPostByAnthroveID() got = %v, want %v", got, tt.want) + } + }) + } +} + +func checkPost(got *models.Post, want *models.Post) bool { + + if got == nil && want == nil { + return true + } else if got == nil || want == nil { + return false + } + + if got.ID != want.ID { + return false + } + + if got.Rating != want.Rating { + return false + } + + return true +} diff --git a/test/helper.go b/test/helper.go index 501ac62..6fed12e 100644 --- a/test/helper.go +++ b/test/helper.go @@ -3,11 +3,15 @@ package test import ( "context" "database/sql" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" migrate "github.com/rubenv/sql-migrate" postgrescontainer "github.com/testcontainers/testcontainers-go/modules/postgres" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" + "net/url" + "strconv" + "strings" "time" "github.com/testcontainers/testcontainers-go" @@ -78,3 +82,41 @@ func getGormDB(connectionString string) (*gorm.DB, error) { Logger: logger.Default.LogMode(logger.Info), }) } + +func DatabaseModesFromConnectionString(ctx context.Context, pgContainer *postgrescontainer.PostgresContainer) (*models.DatabaseConfig, error) { + var err error + + connectionString, err := pgContainer.ConnectionString(ctx) + if err != nil { + return nil, err + } + + url, err := url.Parse(connectionString) + if err != nil { + return nil, err + } + + split := strings.Split(url.Host, ":") + host := split[0] + + port, err := strconv.Atoi(split[1]) + if err != nil { + return nil, err + } + + database := strings.TrimPrefix(url.Path, "/") + + username := url.User.Username() + password, _ := url.User.Password() + + return &models.DatabaseConfig{ + Endpoint: host, + Username: username, + Password: password, + Database: database, + Port: port, + SSL: false, + Timezone: "Europe/Berlin", + Debug: true, + }, nil +} From 8ea3369744c1f9e61ec88d9b90e4ffd9be1e05bd Mon Sep 17 00:00:00 2001 From: soxx Date: Mon, 24 Jun 2024 22:18:34 +0200 Subject: [PATCH 077/124] docs(postgres): added all the sonarqube badges Signed-off-by: soxx --- README.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ffd7f3f..af7e618 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,18 @@ # OtterSpace SDK +[![Bugs](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=bugs&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Code Smells](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=code_smells&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Coverage](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=coverage&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Duplicated Lines (%)](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=duplicated_lines_density&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Lines of Code](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=ncloc&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Maintainability Rating](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=sqale_rating&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Quality Gate Status](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=alert_status&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Reliability Rating](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=reliability_rating&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Security Hotspots](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=security_hotspots&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Security Rating](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=security_rating&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Technical Debt](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=sqale_index&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +[![Vulnerabilities](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=vulnerabilities&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) + The OtterSpace SDK is a Go package for interacting with the OtterSpace API. It provides methods for connecting to the API, adding and linking users, posts, and sources, and retrieving information about users and posts. ## Installation @@ -19,28 +32,21 @@ package main import ( "context" "fmt" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/pkg/database" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" ) func main() { var err error dbDebug := false ctx := context.Background() - + pgClient := database.NewPostgresqlConnection(dbDebug) err = pgClient.Connect(ctx, "your-endpoint", "your-username", "your-password", "anthrove", 5432, "disable", "Europe/Berlin") if err != nil { fmt.Println(err) return } - - graphClient := database.NewGraphConnection(dbDebug) - err = graphClient.Connect(ctx, "your-endpoint", "your-username", "your-password", "NOT USED",0,"NOT USED","NOT USED") - if err != nil { - fmt.Println(err) - return - } // further usage of the client... } ``` From df14171badd2a442069b9ec0bbffc7a45b2bee40 Mon Sep 17 00:00:00 2001 From: soxx Date: Mon, 24 Jun 2024 22:29:01 +0200 Subject: [PATCH 078/124] docs(postgres): added all the sonarqube badges Signed-off-by: soxx --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index af7e618..fd6a43f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # OtterSpace SDK +#### ALL THE BADGES GIT + +![Build Check Runner](https://git.dragse.it/anthrove/otter-space-sdk/actions/workflows/build_check.yaml/badge.svg) + +#### ALL THE BADGES SONARQUBE [![Bugs](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=bugs&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Code Smells](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=code_smells&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Coverage](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=coverage&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) @@ -10,7 +15,6 @@ [![Reliability Rating](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=reliability_rating&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Security Hotspots](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=security_hotspots&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Security Rating](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=security_rating&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) -[![Technical Debt](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=sqale_index&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Vulnerabilities](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=vulnerabilities&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) The OtterSpace SDK is a Go package for interacting with the OtterSpace API. It provides methods for connecting to the API, adding and linking users, posts, and sources, and retrieving information about users and posts. From 895c4cd436c3a77178d33f901edc3e90eaf62439 Mon Sep 17 00:00:00 2001 From: soxx Date: Mon, 24 Jun 2024 22:30:05 +0200 Subject: [PATCH 079/124] docs(postgres): rearranged Signed-off-by: soxx --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fd6a43f..a01f593 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ -# OtterSpace SDK - -#### ALL THE BADGES GIT +#### ALL THE BADGES: GIT ![Build Check Runner](https://git.dragse.it/anthrove/otter-space-sdk/actions/workflows/build_check.yaml/badge.svg) -#### ALL THE BADGES SONARQUBE +#### ALL THE BADGES: SONARQUBE + [![Bugs](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=bugs&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Code Smells](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=code_smells&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Coverage](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=coverage&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) @@ -17,6 +16,8 @@ [![Security Rating](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=security_rating&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Vulnerabilities](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=vulnerabilities&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) +# OtterSpace SDK + The OtterSpace SDK is a Go package for interacting with the OtterSpace API. It provides methods for connecting to the API, adding and linking users, posts, and sources, and retrieving information about users and posts. ## Installation From d90736b1b6154177db1f9291541543387d2fc518 Mon Sep 17 00:00:00 2001 From: soxx Date: Mon, 24 Jun 2024 22:30:57 +0200 Subject: [PATCH 080/124] docs(postgres): rearranged Signed-off-by: soxx --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a01f593..57ec96e 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,14 @@ -#### ALL THE BADGES: GIT ![Build Check Runner](https://git.dragse.it/anthrove/otter-space-sdk/actions/workflows/build_check.yaml/badge.svg) - -#### ALL THE BADGES: SONARQUBE - [![Bugs](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=bugs&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Code Smells](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=code_smells&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Coverage](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=coverage&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) + [![Duplicated Lines (%)](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=duplicated_lines_density&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Lines of Code](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=ncloc&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Maintainability Rating](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=sqale_rating&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Quality Gate Status](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=alert_status&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) + [![Reliability Rating](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=reliability_rating&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Security Hotspots](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=security_hotspots&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) [![Security Rating](https://sonarqube.dragse.de/api/project_badges/measure?project=Anthrove---OtterSpace-SDK&metric=security_rating&token=sqb_96012ffdd64ce721d7f9c82bfa77aa27a5c1fd38)](https://sonarqube.dragse.de/dashboard?id=Anthrove---OtterSpace-SDK) From 31c424912910ae9d670041fbc03415da76a0706d Mon Sep 17 00:00:00 2001 From: soxx Date: Mon, 24 Jun 2024 22:31:18 +0200 Subject: [PATCH 081/124] refactor(postgres): use generics for IDs Signed-off-by: soxx --- pkg/models/orm.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/models/orm.go b/pkg/models/orm.go index 7e74329..7235e57 100644 --- a/pkg/models/orm.go +++ b/pkg/models/orm.go @@ -7,27 +7,26 @@ import ( ) type ID interface { - AnthroveUserID - AnthroveSourceID - AnthrovePostID + AnthroveUserID | AnthroveSourceID | AnthrovePostID } -type BaseModel struct { - ID string `gorm:"primaryKey"` +type BaseModel[T ID] struct { + ID T `gorm:"primaryKey"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } -func (base *BaseModel) BeforeCreate(db *gorm.DB) error { +func (base *BaseModel[T]) BeforeCreate(db *gorm.DB) error { + var defaultVar T - if base.ID == "" { + if base.ID == defaultVar { id, err := gonanoid.New(25) if err != nil { return err } - base.ID = id + base.ID = T(id) } return nil From 5aac1f2916ad99c1ca48e97019a949ae4311d633 Mon Sep 17 00:00:00 2001 From: soxx Date: Tue, 25 Jun 2024 09:09:18 +0200 Subject: [PATCH 082/124] feat(postgres): start implementing new generic orm model Signed-off-by: soxx --- internal/postgres/post_test.go | 30 +++++++----- internal/postgres/relationships.go | 2 +- internal/postgres/relationships_test.go | 20 ++++---- internal/postgres/tag.go | 4 +- internal/postgres/tag_test.go | 4 +- internal/postgres/user.go | 12 ++--- internal/postgres/user_test.go | 64 +++++++++++++------------ pkg/models/post.go | 2 +- pkg/models/source.go | 2 +- pkg/models/user.go | 2 +- 10 files changed, 75 insertions(+), 67 deletions(-) diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index 70d2b37..389e339 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -23,8 +23,8 @@ func TestCreateAnthrovePostNode(t *testing.T) { // Setup Tests validPost := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -84,8 +84,8 @@ func TestGetPostByAnthroveID(t *testing.T) { // Setup Tests post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -112,7 +112,7 @@ func TestGetPostByAnthroveID(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, }, want: post, wantErr: false, @@ -163,8 +163,8 @@ func TestGetPostBySourceURL(t *testing.T) { // Setup Tests post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -175,7 +175,9 @@ func TestGetPostBySourceURL(t *testing.T) { } source := models.Source{ - BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1")), + }, DisplayName: "e621", Domain: "e621.net", Icon: "https://e621.net/icon.ico", @@ -260,8 +262,8 @@ func TestGetPostBySourceID(t *testing.T) { // Setup Tests post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -272,7 +274,9 @@ func TestGetPostBySourceID(t *testing.T) { } source := models.Source{ - BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1")), + }, DisplayName: "e621", Domain: "e621.net", Icon: "https://e621.net/icon.ico", @@ -283,7 +287,7 @@ func TestGetPostBySourceID(t *testing.T) { t.Fatal("Could not create source", err) } - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, models.AnthrovePostID(post.ID), models.AnthroveSourceDomain(source.Domain)) + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain)) if err != nil { t.Fatal("Could not create source reference", err) } @@ -306,7 +310,7 @@ func TestGetPostBySourceID(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, }, want: post, wantErr: false, diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index f719704..b52f37e 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -20,7 +20,7 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr // Establish the relationship err = db.WithContext(ctx).Create(models.PostReference{ PostID: string(anthrovePostID), - SourceID: source.ID, + SourceID: string(source.ID), URL: string(sourceDomain), }).Error diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go index cc763a0..e56b461 100644 --- a/internal/postgres/relationships_test.go +++ b/internal/postgres/relationships_test.go @@ -26,8 +26,8 @@ func TestCheckUserToPostLink(t *testing.T) { } post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -61,7 +61,7 @@ func TestCheckUserToPostLink(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, }, want: true, wantErr: false, @@ -83,7 +83,7 @@ func TestCheckUserToPostLink(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "123", - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, }, want: false, wantErr: false, @@ -125,8 +125,8 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { // Setup Test post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -164,7 +164,7 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, sourceDomain: "e621.net", }, wantErr: false, @@ -225,8 +225,8 @@ func TestEstablishUserToPostLink(t *testing.T) { } post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -254,7 +254,7 @@ func TestEstablishUserToPostLink(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, }, wantErr: false, }, diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index a20b352..d0aa2e0 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -35,8 +35,8 @@ func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, PostID models } pgPost := models.Post{ - BaseModel: models.BaseModel{ - ID: string(PostID), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: PostID, }, } diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index bc94c77..a100774 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -21,8 +21,8 @@ func TestCreateTagNodeWitRelation(t *testing.T) { // Setup Test post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 9cdc2da..359533f 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -15,8 +15,8 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove } user := models.User{ - BaseModel: models.BaseModel{ - ID: string(anthroveUserID), + BaseModel: models.BaseModel[models.AnthroveUserID]{ + ID: anthroveUserID, }, } @@ -51,7 +51,7 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs } source := models.Source{ - BaseModel: models.BaseModel{ID: string(sourceID)}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: sourceID}, } if err := db.WithContext(ctx).Where(&source).First(&source).Error; err != nil { @@ -62,8 +62,8 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs } userSource := models.UserSource{ - User: models.User{BaseModel: models.BaseModel{ID: string(anthroveUserID)}}, - SourceID: source.ID, + User: models.User{BaseModel: models.BaseModel[models.AnthroveUserID]{ID: anthroveUserID}}, + SourceID: string(source.ID), AccountUsername: accountUsername, AccountID: accountId, UserID: string(anthroveUserID), @@ -248,7 +248,7 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse favoritePosts = append(favoritePosts, models.Post{ - BaseModel: models.BaseModel{ID: post.ID}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: post.ID}, Rating: post.Rating, }) } diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 6a701da..1983612 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -72,7 +72,9 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { // Setup Test source := &models.Source{ - BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1")), + }, DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", @@ -102,7 +104,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, userID: "e1", username: "marius", }, @@ -114,7 +116,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "2", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, userID: "e1", username: "marius", }, @@ -126,7 +128,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, userID: "e1", username: "marius", }, @@ -150,7 +152,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, userID: "", username: "marius", }, @@ -162,7 +164,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, userID: "aa", username: "", }, @@ -255,7 +257,9 @@ func TestGetUserSourceBySourceID(t *testing.T) { } source := &models.Source{ - BaseModel: models.BaseModel{ID: expectedResult["e621"].Source.ID}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: expectedResult["e621"].Source.ID, + }, DisplayName: expectedResult["e621"].Source.DisplayName, Domain: expectedResult["e621"].Source.Domain, } @@ -289,7 +293,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "1", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, }, want: expectedResult, wantErr: false, @@ -300,7 +304,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "22", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, }, want: nil, wantErr: true, @@ -322,7 +326,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { ctx: ctx, db: gormDB, anthroveUserID: "", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, }, want: nil, wantErr: true, @@ -377,28 +381,28 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { expectedResultPosts := []models.Post{ { - BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post1")}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post1"))}, Rating: "safe", }, { - BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post2")}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post2"))}, Rating: "safe", }, { - BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post3")}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post3"))}, Rating: "explicit", }, { - BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post4")}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post4"))}, Rating: "explicit", }, { - BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post5")}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post5"))}, Rating: "questionable", }, { - BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post6")}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post6"))}, Rating: "safe", }, } @@ -511,27 +515,27 @@ func TestGetUserFavoritesCount(t *testing.T) { expectedResultPosts := []models.Post{ { - BaseModel: models.BaseModel{ID: "Post1"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post1"}, Rating: "safe", }, { - BaseModel: models.BaseModel{ID: "Post2"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post2"}, Rating: "safe", }, { - BaseModel: models.BaseModel{ID: "Post3"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post3"}, Rating: "explicit", }, { - BaseModel: models.BaseModel{ID: "Post4"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post4"}, Rating: "explicit", }, { - BaseModel: models.BaseModel{ID: "Post5"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post5"}, Rating: "questionable", }, { - BaseModel: models.BaseModel{ID: "Post6"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post6"}, Rating: "safe", }, } @@ -615,7 +619,7 @@ func TestGetUserSourceLinks(t *testing.T) { // Setup Test eSource := &models.Source{ - BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1"))}, DisplayName: "e621", Domain: "e621.net", } @@ -625,7 +629,7 @@ func TestGetUserSourceLinks(t *testing.T) { } faSource := &models.Source{ - BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "2")}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "2"))}, DisplayName: "fa", Domain: "fa.net", } @@ -652,11 +656,11 @@ func TestGetUserSourceLinks(t *testing.T) { }, } - err = CreateUserWithRelationToSource(ctx, gormDB, "1", models.AnthroveSourceID(eSource.ID), expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, "1", eSource.ID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } - err = CreateUserWithRelationToSource(ctx, gormDB, "1", models.AnthroveSourceID(faSource.ID), expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, "1", faSource.ID, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) if err != nil { t.Fatal(err) } @@ -714,9 +718,9 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { } posts := []models.Post{ - {BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post1")}, Rating: "safe"}, - {BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post2")}, Rating: "safe"}, - {BaseModel: models.BaseModel{ID: fmt.Sprintf("%-25s", "Post3")}, Rating: "explicit"}, + {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post1"))}, Rating: "safe"}, + {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post2"))}, Rating: "safe"}, + {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post3"))}, Rating: "explicit"}, } for _, post := range posts { @@ -737,7 +741,7 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { } for i, tag := range tags { - err = CreateTagAndReferenceToPost(ctx, gormDB, models.AnthrovePostID(posts[i].ID), &tag) + err = CreateTagAndReferenceToPost(ctx, gormDB, posts[i].ID, &tag) if err != nil { t.Fatal(err) } diff --git a/pkg/models/post.go b/pkg/models/post.go index 9aef5e7..bfe9946 100644 --- a/pkg/models/post.go +++ b/pkg/models/post.go @@ -2,7 +2,7 @@ package models // Post model type Post struct { - BaseModel + BaseModel[AnthrovePostID] Rating Rating `gorm:"type:enum('safe','questionable','explicit')"` Tags []Tag `gorm:"many2many:post_tags;"` Favorites []UserFavorites `gorm:"foreignKey:PostID"` diff --git a/pkg/models/source.go b/pkg/models/source.go index 0860b81..200b48e 100644 --- a/pkg/models/source.go +++ b/pkg/models/source.go @@ -2,7 +2,7 @@ package models // Source model type Source struct { - BaseModel + BaseModel[AnthroveSourceID] DisplayName string Domain string `gorm:"not null;unique"` Icon string `gorm:"not null"` diff --git a/pkg/models/user.go b/pkg/models/user.go index 7f723e6..95ba75d 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -2,7 +2,7 @@ package models // User model type User struct { - BaseModel + BaseModel[AnthroveUserID] Favorites []UserFavorites `gorm:"foreignKey:UserID"` Sources []UserSource `gorm:"foreignKey:UserID"` } From c0cae140f12bc978e0a6a87171e9d545406f804e Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 14:50:56 +0200 Subject: [PATCH 083/124] test(postgres): finished test migrations to generic orm base Signed-off-by: SoXX --- pkg/database/postgres_test.go | 55 ++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index d14a354..f4cd28f 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -3,10 +3,11 @@ package database import ( "context" "fmt" + "testing" + "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" - "testing" ) func TestNewPostgresqlConnection(t *testing.T) { @@ -96,7 +97,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { // Setup Test source := &models.Source{ - BaseModel: models.BaseModel{ID: fmt.Sprintf("%025s", "1")}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1"))}, DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", @@ -124,7 +125,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { args: args{ ctx: ctx, anthroveUserID: "1", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, accountId: "e1", accountUsername: "marius", }, @@ -135,7 +136,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { args: args{ ctx: ctx, anthroveUserID: "2", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, accountId: "e1", accountUsername: "marius", }, @@ -146,7 +147,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { args: args{ ctx: ctx, anthroveUserID: "", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, accountId: "e1", accountUsername: "marius", }, @@ -168,7 +169,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { args: args{ ctx: ctx, anthroveUserID: "1", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, accountId: "", accountUsername: "marius", }, @@ -179,7 +180,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { args: args{ ctx: ctx, anthroveUserID: "1", - sourceID: models.AnthroveSourceID(source.ID), + sourceID: source.ID, accountId: "aa", accountUsername: "", }, @@ -280,8 +281,8 @@ func Test_postgresqlConnection_CreatePost(t *testing.T) { // Setup Tests validPost := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -342,8 +343,8 @@ func Test_postgresqlConnection_CreateTagAndReferenceToPost(t *testing.T) { // Setup Test post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -373,7 +374,7 @@ func Test_postgresqlConnection_CreateTagAndReferenceToPost(t *testing.T) { name: "Test 1: Valid PostID and Tag", args: args{ ctx: ctx, - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, anthroveTag: tag, }, wantErr: false, @@ -382,7 +383,7 @@ func Test_postgresqlConnection_CreateTagAndReferenceToPost(t *testing.T) { name: "Test 2: Valid PostID and no Tag", args: args{ ctx: ctx, - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, anthroveTag: nil, }, wantErr: true, @@ -430,8 +431,8 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) // Setup Test post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -466,7 +467,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) name: "Test 1: Valid AnthrovePostID and anthroveSourceDomain", args: args{ ctx: ctx, - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, sourceDomain: "e621.net", }, wantErr: false, @@ -527,8 +528,8 @@ func Test_postgresqlConnection_CreateReferenceBetweenUserAndPost(t *testing.T) { } post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -554,7 +555,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenUserAndPost(t *testing.T) { args: args{ ctx: ctx, anthroveUserID: "1", - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, }, wantErr: false, }, @@ -615,8 +616,8 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { } post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -626,7 +627,7 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { t.Fatal(err) } - err = postgres.CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) + err = postgres.CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", post.ID) if err != nil { t.Fatal(err) } @@ -648,7 +649,7 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { args: args{ ctx: ctx, anthroveUserID: "1", - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, }, want: true, wantErr: false, @@ -668,7 +669,7 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { args: args{ ctx: ctx, anthroveUserID: "123", - anthrovePostID: models.AnthrovePostID(post.ID), + anthrovePostID: post.ID, }, want: false, wantErr: false, @@ -714,8 +715,8 @@ func Test_postgresqlConnection_GetPostByAnthroveID(t *testing.T) { // Setup Tests post := &models.Post{ - BaseModel: models.BaseModel{ - ID: fmt.Sprintf("%025s", "1"), + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, Rating: "safe", } @@ -740,7 +741,7 @@ func Test_postgresqlConnection_GetPostByAnthroveID(t *testing.T) { name: "Test 1: Valid anthrovePostID", args: args{ ctx: ctx, - anthrovePost: models.AnthrovePostID(post.ID), + anthrovePost: post.ID, }, want: post, wantErr: false, From d3c05992633050d701ea15f0a20b12ca58a50b69 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 14:55:25 +0200 Subject: [PATCH 084/124] ci: disable check for latest go Signed-off-by: SoXX --- .gitea/workflows/ build_check.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/ build_check.yaml b/.gitea/workflows/ build_check.yaml index 193bcfd..f0e769d 100644 --- a/.gitea/workflows/ build_check.yaml +++ b/.gitea/workflows/ build_check.yaml @@ -23,7 +23,7 @@ jobs: # Path to the go.mod file. go-version-file: ./go.mod # optional # Set this option to true if you want the action to always check for the latest available version that satisfies the version spec - check-latest: true # optional + check-latest: false # optional # Used to specify whether caching is needed. Set to true, if you'd like to enable caching. cache: true # optional From d8f338332b36cd68deb6579ab1c38354535f5d67 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 14:56:08 +0200 Subject: [PATCH 085/124] ci: disable cache Signed-off-by: SoXX --- .gitea/workflows/ build_check.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/ build_check.yaml b/.gitea/workflows/ build_check.yaml index f0e769d..92dbbf8 100644 --- a/.gitea/workflows/ build_check.yaml +++ b/.gitea/workflows/ build_check.yaml @@ -25,7 +25,7 @@ jobs: # Set this option to true if you want the action to always check for the latest available version that satisfies the version spec check-latest: false # optional # Used to specify whether caching is needed. Set to true, if you'd like to enable caching. - cache: true # optional + cache: false # optional - name: Execute Go Test files with coverage report run: go test -v ./... -json -coverprofile="coverage.out" > "test-report.out" From 07b69f6c1823653c0cee4bd5d52442a684671ee5 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 15:00:44 +0200 Subject: [PATCH 086/124] test(postgres): fixed to use new ORM Generic Signed-off-by: SoXX --- pkg/models/orm_test.go | 7 ++++--- pkg/models/post_test.go | 2 +- pkg/models/source_test.go | 2 +- pkg/models/user_test.go | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/models/orm_test.go b/pkg/models/orm_test.go index d18fd2b..cf9e1a4 100644 --- a/pkg/models/orm_test.go +++ b/pkg/models/orm_test.go @@ -1,9 +1,10 @@ package models import ( - "gorm.io/gorm" "testing" "time" + + "gorm.io/gorm" ) func TestBaseModel_BeforeCreate(t *testing.T) { @@ -41,8 +42,8 @@ func TestBaseModel_BeforeCreate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - base := &BaseModel{ - ID: tt.fields.ID, + base := &BaseModel[AnthrovePostID]{ + ID: AnthrovePostID(tt.fields.ID), CreatedAt: tt.fields.CreatedAt, UpdatedAt: tt.fields.UpdatedAt, DeletedAt: tt.fields.DeletedAt, diff --git a/pkg/models/post_test.go b/pkg/models/post_test.go index c90852e..2e7228d 100644 --- a/pkg/models/post_test.go +++ b/pkg/models/post_test.go @@ -4,7 +4,7 @@ import "testing" func TestPost_TableName(t *testing.T) { type fields struct { - BaseModel BaseModel + BaseModel BaseModel[AnthrovePostID] Rating Rating Tags []Tag Favorites []UserFavorites diff --git a/pkg/models/source_test.go b/pkg/models/source_test.go index 1a5ff8c..e65b2c8 100644 --- a/pkg/models/source_test.go +++ b/pkg/models/source_test.go @@ -4,7 +4,7 @@ import "testing" func TestSource_TableName(t *testing.T) { type fields struct { - BaseModel BaseModel + BaseModel BaseModel[AnthroveSourceID] DisplayName string Domain string Icon string diff --git a/pkg/models/user_test.go b/pkg/models/user_test.go index fa2c511..c31745b 100644 --- a/pkg/models/user_test.go +++ b/pkg/models/user_test.go @@ -4,7 +4,7 @@ import "testing" func TestUser_TableName(t *testing.T) { type fields struct { - BaseModel BaseModel + BaseModel BaseModel[AnthroveUserID] Favorites []UserFavorites Sources []UserSource } From 819dc7055afb2c149b91f0954b43eb990b3bec0b Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 15:09:39 +0200 Subject: [PATCH 087/124] feat(postgres): updated go mod Signed-off-by: SoXX --- go.mod | 6 ------ go.sum | 4 ---- 2 files changed, 10 deletions(-) diff --git a/go.mod b/go.mod index a25e991..fe9ef40 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,10 @@ module git.dragse.it/anthrove/otter-space-sdk go 1.22.0 require ( - github.com/brianvoe/gofakeit/v7 v7.0.3 github.com/lib/pq v1.10.9 github.com/matoous/go-nanoid/v2 v2.1.0 - github.com/neo4j/neo4j-go-driver/v5 v5.17.0 github.com/rubenv/sql-migrate v1.6.1 github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.31.0 github.com/testcontainers/testcontainers-go/modules/postgres v0.31.0 gorm.io/driver/postgres v1.5.7 @@ -25,7 +22,6 @@ require ( github.com/containerd/containerd v1.7.15 // indirect github.com/containerd/log v0.1.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.5.0 // indirect github.com/docker/docker v25.0.5+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -55,7 +51,6 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -75,5 +70,4 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d // indirect google.golang.org/grpc v1.58.3 // indirect google.golang.org/protobuf v1.33.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 3b9b10a..a54ced4 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,6 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= -github.com/brianvoe/gofakeit/v7 v7.0.3 h1:tGCt+eYfhTMWE1ko5G2EO1f/yE44yNpIwUb4h32O0wo= -github.com/brianvoe/gofakeit/v7 v7.0.3/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/containerd/containerd v1.7.15 h1:afEHXdil9iAm03BmhjzKyXnnEBtjaLJefdU7DV0IFes= @@ -96,8 +94,6 @@ github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/neo4j/neo4j-go-driver/v5 v5.17.0 h1:Bdqg1Y8Hd3uLYToXtBjysDYXTdMiP7zeUNUEwfbJkSo= -github.com/neo4j/neo4j-go-driver/v5 v5.17.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= From f34cc637ec9e6a0099b7aaa80614a19d8ee34e28 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 15:11:47 +0200 Subject: [PATCH 088/124] ci: readable cache and check for latest Signed-off-by: SoXX --- .gitea/workflows/ build_check.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/ build_check.yaml b/.gitea/workflows/ build_check.yaml index 92dbbf8..193bcfd 100644 --- a/.gitea/workflows/ build_check.yaml +++ b/.gitea/workflows/ build_check.yaml @@ -23,9 +23,9 @@ jobs: # Path to the go.mod file. go-version-file: ./go.mod # optional # Set this option to true if you want the action to always check for the latest available version that satisfies the version spec - check-latest: false # optional + check-latest: true # optional # Used to specify whether caching is needed. Set to true, if you'd like to enable caching. - cache: false # optional + cache: true # optional - name: Execute Go Test files with coverage report run: go test -v ./... -json -coverprofile="coverage.out" > "test-report.out" From c246f661ff8655cd660bc630f98a146d0b9dac2b Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 15:13:52 +0200 Subject: [PATCH 089/124] ci: update version of steps Signed-off-by: SoXX --- .gitea/workflows/ build_check.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/ build_check.yaml b/.gitea/workflows/ build_check.yaml index 193bcfd..5a50130 100644 --- a/.gitea/workflows/ build_check.yaml +++ b/.gitea/workflows/ build_check.yaml @@ -11,12 +11,12 @@ jobs: Build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Setup Go environment - uses: https://github.com/actions/setup-go@v3 + uses: https://github.com/actions/setup-go@v5 with: # The Go version to download (if necessary) and use. Supports semver spec and ranges. go-version: 1.22.0 # optional From 63e74219ed245b6eabe1c5d8baec540d8aba31da Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 16:02:08 +0200 Subject: [PATCH 090/124] feat(error): added first steps for custom errors Signed-off-by: SoXX --- error/database.go | 19 +++++++++++++++++++ error/validation.go | 7 +++++++ internal/postgres/post.go | 26 ++++++++++++++++++-------- 3 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 error/database.go create mode 100644 error/validation.go diff --git a/error/database.go b/error/database.go new file mode 100644 index 0000000..c842614 --- /dev/null +++ b/error/database.go @@ -0,0 +1,19 @@ +package error + +type EntityAlreadyExists struct{} + +type NoDataWritten struct{} + +type NoDataFound struct{} + +func (e *EntityAlreadyExists) Error() string { + return "EntityAlreadyExists error" +} + +func (e *NoDataWritten) Error() string { + return "NoDataWritten error" +} + +func (e *NoDataFound) Error() string { + return "NoDataFound error" +} diff --git a/error/validation.go b/error/validation.go new file mode 100644 index 0000000..b6b4245 --- /dev/null +++ b/error/validation.go @@ -0,0 +1,7 @@ +package error + +type MissingAnthrovePostIDError struct{} + +func (e *MissingAnthrovePostIDError) Error() string { + return "AnthrovePostID is empty" +} diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 2dde49a..ffe74be 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -3,16 +3,24 @@ package postgres import ( "context" "errors" - "fmt" + + error2 "git.dragse.it/anthrove/otter-space-sdk/error" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error { - err := db.WithContext(ctx).Create(&anthrovePost).Error - if err != nil { - return err + result := db.WithContext(ctx).Create(&anthrovePost) + + if result.RowsAffected == 0 { + return &error2.NoDataWritten{} + } + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrDuplicatedKey) { + return &error2.EntityAlreadyExists{} + } } log.WithFields(log.Fields{ @@ -25,13 +33,15 @@ 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) { if anthrovePostID == "" { - return nil, fmt.Errorf("anthrovePostID is required") + return nil, &error2.MissingAnthrovePostIDError{} } var post models.Post - err := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID).Error - if err != nil { - return nil, err + result := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &error2.NoDataFound{} + } } return &post, nil From d94ae83c2f52692b573ec38c5b5ce9650993ec33 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 21:55:43 +0200 Subject: [PATCH 091/124] feat(errors): implemented custom errors Signed-off-by: SoXX --- error/validation.go | 7 - internal/postgres/post.go | 57 ++++--- internal/postgres/relationships.go | 87 +++++++++-- internal/postgres/source.go | 20 ++- internal/postgres/tag.go | 46 ++++-- internal/postgres/user.go | 230 ++++++++++++++++++----------- {error => pkg/errors}/database.go | 16 +- pkg/errors/validation.go | 11 ++ 8 files changed, 324 insertions(+), 150 deletions(-) delete mode 100644 error/validation.go rename {error => pkg/errors}/database.go (70%) create mode 100644 pkg/errors/validation.go diff --git a/error/validation.go b/error/validation.go deleted file mode 100644 index b6b4245..0000000 --- a/error/validation.go +++ /dev/null @@ -1,7 +0,0 @@ -package error - -type MissingAnthrovePostIDError struct{} - -func (e *MissingAnthrovePostIDError) Error() string { - return "AnthrovePostID is empty" -} diff --git a/internal/postgres/post.go b/internal/postgres/post.go index ffe74be..2206e00 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -3,24 +3,29 @@ package postgres import ( "context" "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" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error { - result := db.WithContext(ctx).Create(&anthrovePost) - if result.RowsAffected == 0 { - return &error2.NoDataWritten{} + if anthrovePost == nil { + return &errors2.EntityValidationFailed{Reason: "anthrovePost is nil"} } + result := db.WithContext(ctx).Create(&anthrovePost) if result.Error != nil { 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{ @@ -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) { + 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 result := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &error2.NoDataFound{} + return nil, &errors2.NoDataFound{} } + return nil, result.Error } return &post, nil } 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 errors.Is(err, gorm.ErrRecordNotFound) { - return nil, nil + if sourceURL == "" { + return nil, &errors2.EntityValidationFailed{Reason: "sourceURL is not set"} + } + + 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 } 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 errors.Is(err, gorm.ErrRecordNotFound) { - return nil, nil + if sourceID == "" { + return nil, &errors2.EntityValidationFailed{Reason: "sourceID is not set"} + } + + 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 diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index b52f37e..c072241 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -2,6 +2,8 @@ package postgres import ( "context" + "errors" + errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -9,23 +11,44 @@ import ( func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { 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 - err = db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&source).Error - if err != nil { - return err + result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&source) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return &errors2.NoDataFound{} + } + return result.Error } // Establish the relationship - err = db.WithContext(ctx).Create(models.PostReference{ + result = db.WithContext(ctx).Create(models.PostReference{ PostID: string(anthrovePostID), SourceID: string(source.ID), URL: string(sourceDomain), - }).Error + }) - if err != nil { - return err + 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{ @@ -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 { + + 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{ UserID: string(anthroveUserID), PostID: string(anthrovePostID), } - err := db.WithContext(ctx).Create(&userFavorite).Error - if err != nil { - return err + result := db.WithContext(ctx).Create(&userFavorite) + 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{ @@ -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) { 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 { - return false, err + + if anthrovePostID == "" { + 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 diff --git a/internal/postgres/source.go b/internal/postgres/source.go index da13fc3..1238a87 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -2,7 +2,8 @@ package postgres import ( "context" - "fmt" + "errors" + errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" @@ -13,15 +14,22 @@ import ( func CreateSource(ctx context.Context, db *gorm.DB, anthroveSource *models.Source) error { 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) 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{ "node_source_url": anthroveSource.Domain, "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) 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 } @@ -53,12 +64,15 @@ func GetSourceByDomain(ctx context.Context, db *gorm.DB, sourceDomain models.Ant var sources models.Source 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) if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &errors2.NoDataFound{} + } return nil, result.Error } diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index d0aa2e0..248a6a7 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -2,7 +2,8 @@ package postgres import ( "context" - "fmt" + "errors" + errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -10,10 +11,20 @@ import ( 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 { - return resultTag.Error + result := db.WithContext(ctx).Where(tag).Create(tag) + 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{ @@ -24,30 +35,36 @@ func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { 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 == "" { - return fmt.Errorf("PostID is empty") + 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 tag == nil { - return fmt.Errorf("tag is nill") + return &errors2.EntityValidationFailed{Reason: "Tag is nil"} } pgPost := models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: PostID, + ID: anthrovePostID, }, } err := db.WithContext(ctx).Model(&pgPost).Association("Tags").Append(tag) - if err != nil { - return err + if errors.Is(err, gorm.ErrRecordNotFound) { + return &errors2.NoDataFound{} + } + return errors.Join(err, &errors2.NoRelationCreated{}) } log.WithFields(log.Fields{ - "anthrove_post_id": PostID, + "anthrove_post_id": anthrovePostID, "tag_name": tag.Name, "tag_type": tag.Type, }).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) { var tags []models.Tag + result := db.WithContext(ctx).Find(&tags) + 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 } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 359533f..0e4070b 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -2,7 +2,8 @@ package postgres import ( "context" - "fmt" + "errors" + errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -11,7 +12,11 @@ import ( func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { 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{ @@ -20,12 +25,16 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove }, } - err := db.WithContext(ctx).FirstOrCreate(&user).Error - if err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Error("database: failed to create user") - return err + result := db.WithContext(ctx).FirstOrCreate(&user) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrDuplicatedKey) { + return &errors2.EntityAlreadyExists{} + } + return result.Error + } + + if result.RowsAffected == 0 { + return &errors2.NoDataWritten{} } 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 { 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 == "" { - return fmt.Errorf("account_id cannot be empty") + return &errors2.EntityValidationFailed{Reason: "accountID cannot be empty"} } if accountUsername == "" { - return fmt.Errorf("account_username cannot be empty") + return &errors2.EntityValidationFailed{Reason: "accountUsername cannot be empty"} } 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}, } - if err := db.WithContext(ctx).Where(&source).First(&source).Error; err != nil { - log.WithFields(log.Fields{ - "source_id": sourceID, - }).Error("database: failed to find source") - return err + result := db.WithContext(ctx).Where(&source).First(&source) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return &errors2.NoDataFound{} + } + return result.Error } userSource := models.UserSource{ @@ -69,14 +83,13 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs UserID: string(anthroveUserID), } - if err := db.WithContext(ctx).FirstOrCreate(&userSource).Error; err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "source_id": sourceID, - "account_username": accountUsername, - "account_id": accountId, - }).Error("database: failed to create user-source relationship") - return err + result = db.WithContext(ctx).FirstOrCreate(&userSource) + if result.Error != nil { + return errors.Join(result.Error, &errors2.NoRelationCreated{}) + } + + if result.RowsAffected == 0 { + return &errors2.NoDataWritten{} } 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) { + var count int64 + if anthroveUserID == "" { - return 0, fmt.Errorf("anthroveUserID cannot be empty") + return 0, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} } - var count int64 - err := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Count(&count).Error - if err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Error("database: failed to get user favorites count") - return 0, err + if len(anthroveUserID) != 25 { + return 0, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + } + + result := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Count(&count) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return 0, &errors2.NoDataFound{} + } + return 0, result.Error } log.WithFields(log.Fields{ @@ -115,22 +133,30 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models. var userSources []models.UserSource userSourceMap := make(map[string]models.UserSource) - err := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources).Error - if err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Error("database: failed to get user source link") - return nil, err + 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"} + } + + 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 { var source models.Source - err = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error - if err != nil { - log.WithFields(log.Fields{ - "source_id": userSource.SourceID, - }).Error("database: failed to get source") - return nil, err + result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &errors2.NoDataFound{} + } + return nil, result.Error } 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) { - if anthroveUserID == "" { - return nil, fmt.Errorf("anthroveUserID cannot be empty") - } - - if sourceID == "" { - return nil, fmt.Errorf("sourceID cannot be empty") - } - var userSources []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 err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "source_id": sourceID, - }).Error("database: failed to get specified user source link") - return nil, err + 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"} + } + + 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 { var source models.Source - err = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source).Error - if err != nil { - log.WithFields(log.Fields{ - "source_id": userSource.SourceID, - }).Error("database: failed to get source") - return nil, err + result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &errors2.NoDataFound{} + } + return nil, result.Error } userSourceMap[source.DisplayName] = models.UserSource{ @@ -205,14 +238,16 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU var users []models.User var userIDs []models.AnthroveUserID - err := db.WithContext(ctx).Model(&models.User{}).Find(&users).Error - if err != nil { - log.Error("database: failed to get all anthrove user IDs") - return nil, err + result := db.WithContext(ctx).Model(&models.User{}).Find(&users) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &errors2.NoDataFound{} + } + return nil, result.Error } for _, user := range users { - userIDs = append(userIDs, models.AnthroveUserID(user.ID)) + userIDs = append(userIDs, user.ID) } log.WithFields(log.Fields{ @@ -226,13 +261,19 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse var userFavorites []models.UserFavorites 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 if err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - "skip": skip, - "limit": limit, - }).Error("database: failed to get user favorites with pagination") + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &errors2.NoDataFound{} + } return nil, err } @@ -240,9 +281,9 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse var post models.Post err = db.WithContext(ctx).Model(&models.Post{}).Where("id = ?", userFavorite.PostID).First(&post).Error if err != nil { - log.WithFields(log.Fields{ - "post_id": userFavorite.PostID, - }).Error("database: failed to get post") + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &errors2.NoDataFound{} + } 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) { var userFavorites []models.UserFavorites - err := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites).Error - if err != nil { - log.WithFields(log.Fields{ - "anthrove_user_id": anthroveUserID, - }).Error("database: failed to get user favorites") - return nil, err + + 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"} + } + + 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 { @@ -278,12 +328,12 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov for _, userFavorite := range userFavorites { var post models.Post - err = db.WithContext(ctx).Preload("Tags").First(&post, "id = ?", userFavorite.PostID).Error - if err != nil { - log.WithFields(log.Fields{ - "post_id": userFavorite.PostID, - }).Error("database: failed to get post tags") - return nil, err + result = db.WithContext(ctx).Preload("Tags").First(&post, "id = ?", userFavorite.PostID) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &errors2.NoDataFound{} + } + return nil, result.Error } for _, tag := range post.Tags { diff --git a/error/database.go b/pkg/errors/database.go similarity index 70% rename from error/database.go rename to pkg/errors/database.go index c842614..5559b95 100644 --- a/error/database.go +++ b/pkg/errors/database.go @@ -1,19 +1,25 @@ -package error +package errors type EntityAlreadyExists struct{} -type NoDataWritten struct{} - -type NoDataFound struct{} - func (e *EntityAlreadyExists) Error() string { return "EntityAlreadyExists error" } +type NoDataWritten struct{} + func (e *NoDataWritten) Error() string { return "NoDataWritten error" } +type NoDataFound struct{} + func (e *NoDataFound) Error() string { return "NoDataFound error" } + +type NoRelationCreated struct{} + +func (e *NoRelationCreated) Error() string { + return "relationship creation error" +} diff --git a/pkg/errors/validation.go b/pkg/errors/validation.go new file mode 100644 index 0000000..a04ac75 --- /dev/null +++ b/pkg/errors/validation.go @@ -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) +} From f66fc6b6d7a19cd0fd152734d85093b25288d211 Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 25 Jun 2024 22:22:05 +0200 Subject: [PATCH 092/124] tests(errors): fix test cases to reflect the new validation and error handling Signed-off-by: SoXX --- internal/postgres/post_test.go | 8 ++--- internal/postgres/relationships.go | 4 +++ internal/postgres/relationships_test.go | 48 +++++++++++++++---------- internal/postgres/source_test.go | 6 +++- internal/postgres/user_test.go | 42 +++++++++++++++------- 5 files changed, 72 insertions(+), 36 deletions(-) diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index 389e339..1b1bc83 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -223,7 +223,7 @@ func TestGetPostBySourceURL(t *testing.T) { sourceURL: "1234", }, want: nil, - wantErr: false, + wantErr: true, }, { name: "Test 3: No sourceURL", @@ -233,7 +233,7 @@ func TestGetPostBySourceURL(t *testing.T) { sourceURL: "", }, want: nil, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { @@ -323,7 +323,7 @@ func TestGetPostBySourceID(t *testing.T) { sourceID: "1234", }, want: nil, - wantErr: false, + wantErr: true, }, { name: "Test 3: No sourceID", @@ -333,7 +333,7 @@ func TestGetPostBySourceID(t *testing.T) { sourceID: "", }, want: nil, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index c072241..6be3bde 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -113,6 +113,10 @@ func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthrove return false, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} } + if len(anthroveUserID) != 25 { + return false, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + } + 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) { diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go index e56b461..a758ad2 100644 --- a/internal/postgres/relationships_test.go +++ b/internal/postgres/relationships_test.go @@ -20,14 +20,20 @@ func TestCheckUserToPostLink(t *testing.T) { defer container.Terminate(ctx) // Setup Test - err = CreateUser(ctx, gormDB, "1") + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validPostID := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + + err = CreateUser(ctx, gormDB, validUserID) if err != nil { t.Fatal(err) } post := &models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), + ID: validPostID, }, Rating: "safe", } @@ -37,7 +43,7 @@ func TestCheckUserToPostLink(t *testing.T) { t.Fatal(err) } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validUserID, post.ID) if err != nil { t.Fatal(err) } @@ -60,7 +66,7 @@ func TestCheckUserToPostLink(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, anthrovePostID: post.ID, }, want: true, @@ -71,33 +77,33 @@ func TestCheckUserToPostLink(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, anthrovePostID: "qadw", }, want: false, - wantErr: false, + wantErr: true, }, { name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "123", + anthroveUserID: invalidUserID, anthrovePostID: post.ID, }, want: false, - wantErr: false, + wantErr: true, }, { name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "123", + anthroveUserID: invalidUserID, anthrovePostID: "123456", }, want: false, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { @@ -219,14 +225,20 @@ func TestEstablishUserToPostLink(t *testing.T) { defer container.Terminate(ctx) // Setup Test - err = CreateUser(ctx, gormDB, "1") + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validPostID := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + + err = CreateUser(ctx, gormDB, validUserID) if err != nil { t.Fatal(err) } post := &models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), + ID: validPostID, }, Rating: "safe", } @@ -253,7 +265,7 @@ func TestEstablishUserToPostLink(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, anthrovePostID: post.ID, }, wantErr: false, @@ -263,18 +275,18 @@ func TestEstablishUserToPostLink(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, anthrovePostID: "123456", }, wantErr: true, }, { - name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", + name: "Test 3: invalid AnthroveUserID and valid AnthrovePostID", args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "123", - anthrovePostID: "1234", + anthroveUserID: invalidUserID, + anthrovePostID: post.ID, }, wantErr: true, }, @@ -283,7 +295,7 @@ func TestEstablishUserToPostLink(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "123", + anthroveUserID: invalidUserID, anthrovePostID: "123456", }, wantErr: true, diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go index 80c0dc8..b618017 100644 --- a/internal/postgres/source_test.go +++ b/internal/postgres/source_test.go @@ -2,6 +2,7 @@ package postgres import ( "context" + "fmt" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" @@ -19,7 +20,10 @@ func TestCreateSourceNode(t *testing.T) { // Setup Test + validPostID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Post1")) + validSource := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validPostID}, DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", @@ -65,7 +69,7 @@ func TestCreateSourceNode(t *testing.T) { db: gormDB, anthroveSource: validSource, }, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 1983612..04c270a 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -21,6 +21,9 @@ func TestCreateUser(t *testing.T) { // Setup Test + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + // Test type args struct { ctx context.Context @@ -37,7 +40,7 @@ func TestCreateUser(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, }, wantErr: false, }, @@ -46,7 +49,7 @@ func TestCreateUser(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "", + anthroveUserID: invalidUserID, }, wantErr: true, }, @@ -71,9 +74,14 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { // Setup Test + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + source := &models.Source{ BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1")), + ID: validSourceID, }, DisplayName: "e621", Domain: "e621.net", @@ -103,7 +111,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: source.ID, userID: "e1", username: "marius", @@ -115,7 +123,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "2", + anthroveUserID: invalidUserID, sourceID: source.ID, userID: "e1", username: "marius", @@ -139,7 +147,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: "fa.net", userID: "e1", username: "marius", @@ -151,7 +159,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: source.ID, userID: "", username: "marius", @@ -163,7 +171,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: source.ID, userID: "aa", username: "", @@ -190,8 +198,11 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { defer container.Terminate(ctx) // Setup Test + validUserID01 := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + validUserID02 := models.AnthroveUserID(fmt.Sprintf("%025s", "User2")) + validUserID03 := models.AnthroveUserID(fmt.Sprintf("%025s", "User3")) - users := []models.AnthroveUserID{"1", "2", "3"} + users := []models.AnthroveUserID{validUserID01, validUserID02, validUserID03} for _, user := range users { err = CreateUser(ctx, gormDB, user) @@ -246,6 +257,9 @@ func TestGetUserSourceBySourceID(t *testing.T) { // Setup Test + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + expectedResult := make(map[string]models.UserSource) expectedResult["e621"] = models.UserSource{ UserID: "e1", @@ -269,7 +283,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { t.Fatal(err) } - err = CreateUserWithRelationToSource(ctx, gormDB, "1", models.AnthroveSourceID(expectedResult["e621"].SourceID), expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, models.AnthroveSourceID(expectedResult["e621"].SourceID), expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } @@ -292,7 +306,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: source.ID, }, want: expectedResult, @@ -303,7 +317,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "22", + anthroveUserID: invalidUserID, sourceID: source.ID, }, want: nil, @@ -314,7 +328,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: "fa", }, want: nil, @@ -368,6 +382,8 @@ func TestGetUserSourceBySourceID(t *testing.T) { } } +// TODO: FIX THE FOUR REMAINING TESTS + func TestGetUserFavoriteNodeWithPagination(t *testing.T) { // Setup trow away containert ctx := context.Background() From c550531a35b5c2449b820a507be8b0980cc67abb Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 09:10:04 +0200 Subject: [PATCH 093/124] tests(errors): refactored old tests to reflect new error handling Signed-off-by: SoXX --- internal/postgres/post.go | 5 +- internal/postgres/post_test.go | 5 +- internal/postgres/source.go | 3 +- internal/postgres/tag.go | 3 +- internal/postgres/user.go | 5 +- internal/postgres/user_test.go | 106 ++- pkg/database/postgres_test.go | 1229 +++++++++++++++++++++++++++++++- 7 files changed, 1281 insertions(+), 75 deletions(-) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 2206e00..edf7ac3 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -3,6 +3,7 @@ package postgres import ( "context" "errors" + errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" @@ -42,7 +43,9 @@ func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models return nil, &errors2.EntityValidationFailed{Reason: "anthrovePostID is not set"} } - //TODO maybe check ofor id length too...? + if len(anthrovePostID) != 25 { + return nil, &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} + } var post models.Post result := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID) diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index 1b1bc83..99e5b32 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -3,11 +3,12 @@ package postgres import ( "context" "fmt" + "testing" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" _ "github.com/lib/pq" "gorm.io/gorm" - "testing" ) func TestCreateAnthrovePostNode(t *testing.T) { @@ -188,7 +189,7 @@ func TestGetPostBySourceURL(t *testing.T) { t.Fatal("Could not create source", err) } - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, models.AnthrovePostID(post.ID), models.AnthroveSourceDomain(source.Domain)) + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain)) if err != nil { t.Fatal("Could not create source reference", err) } diff --git a/internal/postgres/source.go b/internal/postgres/source.go index 1238a87..9321e42 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -3,6 +3,7 @@ package postgres import ( "context" "errors" + errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" @@ -48,7 +49,7 @@ func GetAllSource(ctx context.Context, db *gorm.DB) ([]models.Source, error) { 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 } diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 248a6a7..86f60d8 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -3,6 +3,7 @@ package postgres import ( "context" "errors" + errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" @@ -78,7 +79,7 @@ func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) { result := db.WithContext(ctx).Find(&tags) 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 + if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, &errors2.NoDataFound{} } return nil, result.Error diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 0e4070b..a21b266 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -3,6 +3,7 @@ package postgres import ( "context" "errors" + errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" @@ -33,10 +34,6 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove return result.Error } - if result.RowsAffected == 0 { - return &errors2.NoDataWritten{} - } - return nil } diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 04c270a..3c63d8c 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -3,11 +3,12 @@ package postgres import ( "context" "fmt" + "reflect" + "testing" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" - "reflect" - "testing" ) func TestCreateUser(t *testing.T) { @@ -382,8 +383,6 @@ func TestGetUserSourceBySourceID(t *testing.T) { } } -// TODO: FIX THE FOUR REMAINING TESTS - func TestGetUserFavoriteNodeWithPagination(t *testing.T) { // Setup trow away containert ctx := context.Background() @@ -394,31 +393,39 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { defer container.Terminate(ctx) // Setup Test + validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + validPostID2 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post2")) + validPostID3 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post3")) + validPostID4 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post4")) + validPostID5 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post5")) + validPostID6 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post6")) expectedResultPosts := []models.Post{ { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post1"))}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID1}, Rating: "safe", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post2"))}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID2}, Rating: "safe", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post3"))}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID3}, Rating: "explicit", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post4"))}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID4}, Rating: "explicit", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post5"))}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID5}, Rating: "questionable", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post6"))}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID6}, Rating: "safe", }, } @@ -432,7 +439,7 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { Posts: expectedResultPosts[:3], } - err = CreateUser(ctx, gormDB, "1") + err = CreateUser(ctx, gormDB, validAnthroveUserID) if err != nil { t.Fatal(err) } @@ -442,7 +449,7 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { if err != nil { t.Fatal(err) } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(expectedResultPost.ID)) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, expectedResultPost.ID) if err != nil { t.Fatal(err) } @@ -467,7 +474,7 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validAnthroveUserID, skip: 0, limit: 2000, }, @@ -479,7 +486,7 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validAnthroveUserID, skip: 2, limit: 2000, }, @@ -491,7 +498,7 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validAnthroveUserID, skip: 0, limit: 3, }, @@ -524,44 +531,54 @@ func TestGetUserFavoritesCount(t *testing.T) { // Setup Test - err = CreateUser(ctx, gormDB, "1") - if err != nil { - t.Fatal(err) - } + validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + validPostID2 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post2")) + validPostID3 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post3")) + validPostID4 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post4")) + validPostID5 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post5")) + validPostID6 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post6")) expectedResultPosts := []models.Post{ { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post1"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID1}, Rating: "safe", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post2"}, + + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID2}, Rating: "safe", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post3"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID3}, Rating: "explicit", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post4"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID4}, Rating: "explicit", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post5"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID5}, Rating: "questionable", }, { - BaseModel: models.BaseModel[models.AnthrovePostID]{ID: "Post6"}, + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID6}, Rating: "safe", }, } + err = CreateUser(ctx, gormDB, validAnthroveUserID) + if err != nil { + t.Fatal(err) + } + for _, post := range expectedResultPosts { err = CreatePost(ctx, gormDB, &post) if err != nil { t.Fatal(err) } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, post.ID) if err != nil { t.Fatal(err) } @@ -584,7 +601,7 @@ func TestGetUserFavoritesCount(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validAnthroveUserID, }, want: 6, wantErr: false, @@ -597,7 +614,7 @@ func TestGetUserFavoritesCount(t *testing.T) { anthroveUserID: "2", }, want: 0, - wantErr: false, + wantErr: true, }, { name: "Test 3: no anthroveUserID and 6 favorite posts", @@ -634,8 +651,13 @@ func TestGetUserSourceLinks(t *testing.T) { defer container.Terminate(ctx) // Setup Test + validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + + validSourceID1 := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + validSourceID2 := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source2")) + eSource := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1"))}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validSourceID1}, DisplayName: "e621", Domain: "e621.net", } @@ -645,7 +667,7 @@ func TestGetUserSourceLinks(t *testing.T) { } faSource := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "2"))}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validSourceID2}, DisplayName: "fa", Domain: "fa.net", } @@ -672,11 +694,11 @@ func TestGetUserSourceLinks(t *testing.T) { }, } - err = CreateUserWithRelationToSource(ctx, gormDB, "1", eSource.ID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, validAnthroveUserID, eSource.ID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } - err = CreateUserWithRelationToSource(ctx, gormDB, "1", faSource.ID, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, validAnthroveUserID, faSource.ID, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) if err != nil { t.Fatal(err) } @@ -698,7 +720,7 @@ func TestGetUserSourceLinks(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validAnthroveUserID, }, want: expectedResult, wantErr: false, @@ -728,15 +750,21 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { defer container.Terminate(ctx) // Setup Test - err = CreateUser(ctx, gormDB, "1") + validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + validPostID2 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post2")) + validPostID3 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post3")) + + err = CreateUser(ctx, gormDB, validAnthroveUserID) if err != nil { t.Fatal(err) } posts := []models.Post{ - {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post1"))}, Rating: "safe"}, - {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post2"))}, Rating: "safe"}, - {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: models.AnthrovePostID(fmt.Sprintf("%-25s", "Post3"))}, Rating: "explicit"}, + {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID1}, Rating: "safe"}, + {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID2}, Rating: "safe"}, + {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID3}, Rating: "explicit"}, } for _, post := range posts { @@ -744,7 +772,7 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { if err != nil { t.Fatal(err) } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", models.AnthrovePostID(post.ID)) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, models.AnthrovePostID(post.ID)) if err != nil { t.Fatal(err) } @@ -804,7 +832,7 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveUserID: "1", + anthroveUserID: validAnthroveUserID, }, want: expectedResult, wantErr: false, diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index f4cd28f..4103607 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -3,11 +3,13 @@ package database import ( "context" "fmt" + "reflect" "testing" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" + "gorm.io/gorm" ) func TestNewPostgresqlConnection(t *testing.T) { @@ -95,9 +97,11 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { defer container.Terminate(ctx) // Setup Test + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + validSourceID1 := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) source := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1"))}, + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validSourceID1}, DisplayName: "e621", Domain: "e621.net", Icon: "icon.e621.net", @@ -124,7 +128,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { name: "Test 1: Valid anthroveUserID, sourceID, accountId, accountUsername", args: args{ ctx: ctx, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: source.ID, accountId: "e1", accountUsername: "marius", @@ -157,7 +161,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { name: "Test 4: invalid sourceID", args: args{ ctx: ctx, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: "fa.net", accountId: "e1", accountUsername: "marius", @@ -168,7 +172,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { name: "Test 5: no accountId", args: args{ ctx: ctx, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: source.ID, accountId: "", accountUsername: "marius", @@ -179,7 +183,7 @@ func Test_postgresqlConnection_CreateUserWithRelationToSource(t *testing.T) { name: "Test 6: no accountUsername", args: args{ ctx: ctx, - anthroveUserID: "1", + anthroveUserID: validUserID, sourceID: source.ID, accountId: "aa", accountUsername: "", @@ -253,7 +257,7 @@ func Test_postgresqlConnection_CreateSource(t *testing.T) { ctx: ctx, anthroveSource: validSource, }, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { @@ -280,9 +284,11 @@ func Test_postgresqlConnection_CreatePost(t *testing.T) { // Setup Tests + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + validPost := &models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), + ID: validPostID1, }, Rating: "safe", } @@ -341,10 +347,11 @@ func Test_postgresqlConnection_CreateTagAndReferenceToPost(t *testing.T) { defer container.Terminate(ctx) // Setup Test + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) post := &models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), + ID: validPostID1, }, Rating: "safe", } @@ -430,23 +437,28 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) defer container.Terminate(ctx) // Setup Test + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + validSourceID1 := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + post := &models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), + ID: validPostID1, }, Rating: "safe", } + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validSourceID1}, + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + } + err = postgres.CreatePost(ctx, gormDB, post) if err != nil { t.Fatal(err) } - source := &models.Source{ - DisplayName: "e621", - Domain: "e621.net", - Icon: "icon.e621.net", - } err = postgres.CreateSource(ctx, gormDB, source) if err != nil { t.Fatal(err) @@ -522,14 +534,17 @@ func Test_postgresqlConnection_CreateReferenceBetweenUserAndPost(t *testing.T) { defer container.Terminate(ctx) // Setup Test - err = postgres.CreateUser(ctx, gormDB, "1") + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + + err = postgres.CreateUser(ctx, gormDB, validUserID) if err != nil { t.Fatal(err) } post := &models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), + ID: validPostID1, }, Rating: "safe", } @@ -554,7 +569,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenUserAndPost(t *testing.T) { name: "Test 1: Valid AnthroveUserID and AnthrovePostID", args: args{ ctx: ctx, - anthroveUserID: "1", + anthroveUserID: validUserID, anthrovePostID: post.ID, }, wantErr: false, @@ -563,7 +578,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenUserAndPost(t *testing.T) { name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", args: args{ ctx: ctx, - anthroveUserID: "1", + anthroveUserID: validUserID, anthrovePostID: "123456", }, wantErr: true, @@ -610,14 +625,17 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { defer container.Terminate(ctx) // Setup Test - err = postgres.CreateUser(ctx, gormDB, "1") + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + + err = postgres.CreateUser(ctx, gormDB, validUserID) if err != nil { t.Fatal(err) } post := &models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), + ID: validPostID1, }, Rating: "safe", } @@ -627,7 +645,7 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { t.Fatal(err) } - err = postgres.CreateReferenceBetweenUserAndPost(ctx, gormDB, "1", post.ID) + err = postgres.CreateReferenceBetweenUserAndPost(ctx, gormDB, validUserID, post.ID) if err != nil { t.Fatal(err) } @@ -648,7 +666,7 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { name: "Test 1: Valid AnthroveUserID and AnthrovePostID", args: args{ ctx: ctx, - anthroveUserID: "1", + anthroveUserID: validUserID, anthrovePostID: post.ID, }, want: true, @@ -658,11 +676,11 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", args: args{ ctx: ctx, - anthroveUserID: "1", + anthroveUserID: validUserID, anthrovePostID: "qadw", }, want: false, - wantErr: false, + wantErr: true, }, { name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", @@ -672,7 +690,7 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { anthrovePostID: post.ID, }, want: false, - wantErr: false, + wantErr: true, }, { name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", @@ -682,7 +700,7 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { anthrovePostID: "123456", }, want: false, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { @@ -713,10 +731,11 @@ func Test_postgresqlConnection_GetPostByAnthroveID(t *testing.T) { defer container.Terminate(ctx) // Setup Tests + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) post := &models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), + ID: validPostID1, }, Rating: "safe", } @@ -773,6 +792,1107 @@ func Test_postgresqlConnection_GetPostByAnthroveID(t *testing.T) { } } +func Test_postgresqlConnection_GetPostByURL(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Tests + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + + post := &models.Post{ + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: validPostID1, + }, + Rating: "safe", + } + + err = postgres.CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal("Could not create post", err) + } + + source := models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: models.AnthroveSourceID(fmt.Sprintf("%025s", "1")), + }, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.net/icon.ico", + } + + err = postgres.CreateSource(ctx, gormDB, &source) + if err != nil { + t.Fatal("Could not create source", err) + } + + err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain)) + if err != nil { + t.Fatal("Could not create source reference", err) + } + + // Test + type args struct { + ctx context.Context + sourceUrl string + } + tests := []struct { + name string + args args + want *models.Post + wantErr bool + }{ + { + name: "Test 1: Valid sourceUrl", + args: args{ + ctx: ctx, + sourceUrl: source.Domain, + }, + want: post, + wantErr: false, + }, + { + name: "Test 2: Invalid sourceUrl", + args: args{ + ctx: ctx, + sourceUrl: "1234", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: No sourceUrl", + args: args{ + ctx: ctx, + sourceUrl: "", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetPostByURL(tt.args.ctx, tt.args.sourceUrl) + if (err != nil) != tt.wantErr { + t.Errorf("GetPostByURL() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkPost(got, tt.want) { + t.Errorf("GetPostByURL() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetPostBySourceID(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Tests + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + validSourceID1 := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + + post := &models.Post{ + BaseModel: models.BaseModel[models.AnthrovePostID]{ + ID: validPostID1, + }, + Rating: "safe", + } + + source := models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: validSourceID1, + }, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.net/icon.ico", + } + + err = postgres.CreatePost(ctx, gormDB, post) + if err != nil { + t.Fatal("Could not create post", err) + } + + err = postgres.CreateSource(ctx, gormDB, &source) + if err != nil { + t.Fatal("Could not create source", err) + } + + err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain)) + if err != nil { + t.Fatal("Could not create source reference", err) + } + + // Test + type args struct { + ctx context.Context + sourceID models.AnthroveSourceID + } + tests := []struct { + name string + args args + want *models.Post + wantErr bool + }{ + { + name: "Test 1: Valid sourceID", + args: args{ + ctx: ctx, + sourceID: source.ID, + }, + want: post, + wantErr: false, + }, + { + name: "Test 2: Invalid sourceID", + args: args{ + ctx: ctx, + sourceID: "1234", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: No sourceID", + args: args{ + ctx: ctx, + sourceID: "", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetPostBySourceID(tt.args.ctx, tt.args.sourceID) + if (err != nil) != tt.wantErr { + t.Errorf("GetPostBySourceID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkPost(got, tt.want) { + t.Errorf("GetPostBySourceID() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetUserFavoritesCount(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + validPostID2 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post2")) + validPostID3 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post3")) + validPostID4 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post4")) + validPostID5 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post5")) + validPostID6 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post6")) + + expectedResultPosts := []models.Post{ + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID1}, + Rating: "safe", + }, + { + + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID2}, + Rating: "safe", + }, + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID3}, + Rating: "explicit", + }, + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID4}, + Rating: "explicit", + }, + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID5}, + Rating: "questionable", + }, + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID6}, + Rating: "safe", + }, + } + + err = postgres.CreateUser(ctx, gormDB, validAnthroveUserID) + if err != nil { + t.Fatal(err) + } + + for _, post := range expectedResultPosts { + err = postgres.CreatePost(ctx, gormDB, &post) + if err != nil { + t.Fatal(err) + } + err = postgres.CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, post.ID) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + } + tests := []struct { + name string + args args + want int64 + wantErr bool + }{ + { + name: "Test 1: Valid anthroveUserID and 6 favorite posts", + args: args{ + ctx: ctx, + anthroveUserID: validAnthroveUserID, + }, + want: 6, + wantErr: false, + }, + { + name: "Test 2: Invalid anthroveUserID and 6 favorite posts", + args: args{ + ctx: ctx, + anthroveUserID: "2", + }, + want: 0, + wantErr: true, + }, + { + name: "Test 3: no anthroveUserID and 6 favorite posts", + args: args{ + ctx: ctx, + anthroveUserID: "", + }, + want: 0, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetUserFavoritesCount(tt.args.ctx, tt.args.anthroveUserID) + if (err != nil) != tt.wantErr { + t.Errorf("GetUserFavoritesCount() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetUserFavoritesCount() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetUserSourceLinks(t *testing.T) { + // Setup trow away containert + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + + validSourceID1 := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + validSourceID2 := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source2")) + + eSource := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validSourceID1}, + DisplayName: "e621", + Domain: "e621.net", + } + err = postgres.CreateSource(ctx, gormDB, eSource) + if err != nil { + t.Fatal(err) + } + + faSource := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validSourceID2}, + DisplayName: "fa", + Domain: "fa.net", + } + err = postgres.CreateSource(ctx, gormDB, faSource) + if err != nil { + t.Fatal(err) + } + + expectedResult := make(map[string]models.UserSource) + expectedResult["e621"] = models.UserSource{ + UserID: "e1", + AccountUsername: "e621-user", + Source: models.Source{ + DisplayName: eSource.DisplayName, + Domain: eSource.Domain, + }, + } + expectedResult["fa"] = models.UserSource{ + UserID: "fa1", + AccountUsername: "fa-user", + Source: models.Source{ + DisplayName: faSource.DisplayName, + Domain: faSource.Domain, + }, + } + + err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validAnthroveUserID, eSource.ID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + if err != nil { + t.Fatal(err) + } + err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validAnthroveUserID, faSource.ID, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + } + tests := []struct { + name string + args args + want map[string]models.UserSource + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + anthroveUserID: validAnthroveUserID, + }, + want: expectedResult, + wantErr: false, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetUserSourceLinks(tt.args.ctx, tt.args.anthroveUserID) + if (err != nil) != tt.wantErr { + t.Errorf("GetUserSourceLinks() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetUserSourceLinks() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + expectedResult := make(map[string]models.UserSource) + expectedResult["e621"] = models.UserSource{ + UserID: "e1", + AccountUsername: "euser", + Source: models.Source{ + DisplayName: "e621", + Domain: "e621.net", + }, + } + + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: expectedResult["e621"].Source.ID, + }, + DisplayName: expectedResult["e621"].Source.DisplayName, + Domain: expectedResult["e621"].Source.Domain, + } + + err = postgres.CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, models.AnthroveSourceID(expectedResult["e621"].SourceID), expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + sourceID models.AnthroveSourceID + } + tests := []struct { + name string + args args + want map[string]models.UserSource + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveUserID and sourceID", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: source.ID, + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveUserID and valid sourceID", + args: args{ + ctx: ctx, + anthroveUserID: invalidUserID, + sourceID: source.ID, + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: Valid AnthroveUserID and invalid sourceID", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: "fa", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 4: No AnthroveUserID and Valid sourceID", + args: args{ + ctx: ctx, + anthroveUserID: "", + sourceID: source.ID, + }, + want: nil, + wantErr: true, + }, + { + name: "Test 5: Valid AnthroveUserID and No SourceDisplayName", + args: args{ + ctx: ctx, + anthroveUserID: "1", + sourceID: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 6: No AnthroveUserID and No SourceDisplayName", + args: args{ + ctx: ctx, + anthroveUserID: "", + sourceID: "", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetUserSourceBySourceID(tt.args.ctx, tt.args.anthroveUserID, tt.args.sourceID) + if (err != nil) != tt.wantErr { + t.Errorf("GetUserSourceBySourceID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetUserSourceBySourceID() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validUserID01 := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + validUserID02 := models.AnthroveUserID(fmt.Sprintf("%025s", "User2")) + validUserID03 := models.AnthroveUserID(fmt.Sprintf("%025s", "User3")) + + users := []models.AnthroveUserID{validUserID01, validUserID02, validUserID03} + + for _, user := range users { + err = postgres.CreateUser(ctx, gormDB, user) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + } + tests := []struct { + name string + args args + want []models.AnthroveUserID + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + }, + want: users, + wantErr: false, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllAnthroveUserIDs(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllAnthroveUserIDs() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllAnthroveUserIDs() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetUserFavoriteWithPagination(t *testing.T) { + // Setup trow away containert + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + validPostID2 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post2")) + validPostID3 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post3")) + validPostID4 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post4")) + validPostID5 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post5")) + validPostID6 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post6")) + + expectedResultPosts := []models.Post{ + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID1}, + Rating: "safe", + }, + { + + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID2}, + Rating: "safe", + }, + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID3}, + Rating: "explicit", + }, + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID4}, + Rating: "explicit", + }, + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID5}, + Rating: "questionable", + }, + { + BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID6}, + Rating: "safe", + }, + } + expectedResult := &models.FavoriteList{ + Posts: expectedResultPosts, + } + expectedResult2 := &models.FavoriteList{ + Posts: expectedResultPosts[2:], + } + expectedResult3 := &models.FavoriteList{ + Posts: expectedResultPosts[:3], + } + + err = postgres.CreateUser(ctx, gormDB, validAnthroveUserID) + if err != nil { + t.Fatal(err) + } + + for _, expectedResultPost := range expectedResultPosts { + err = postgres.CreatePost(ctx, gormDB, &expectedResultPost) + if err != nil { + t.Fatal(err) + } + err = postgres.CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, expectedResultPost.ID) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + skip int + limit int + } + tests := []struct { + name string + args args + want *models.FavoriteList + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveUserID", + args: args{ + ctx: ctx, + anthroveUserID: validAnthroveUserID, + skip: 0, + limit: 2000, + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: Skip first two", + args: args{ + ctx: ctx, + anthroveUserID: validAnthroveUserID, + skip: 2, + limit: 2000, + }, + want: expectedResult2, + wantErr: false, + }, + { + name: "Test 3: Limit of 3", + args: args{ + ctx: ctx, + anthroveUserID: validAnthroveUserID, + skip: 0, + limit: 3, + }, + want: expectedResult3, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetUserFavoriteWithPagination(tt.args.ctx, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) + if (err != nil) != tt.wantErr { + t.Errorf("GetUserFavoriteWithPagination() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetUserFavoriteWithPagination() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetUserTagWitRelationToFavedPosts(t *testing.T) { + // Setup trow away containert + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validAnthroveUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + + validPostID1 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + validPostID2 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post2")) + validPostID3 := models.AnthrovePostID(fmt.Sprintf("%025s", "Post3")) + + err = postgres.CreateUser(ctx, gormDB, validAnthroveUserID) + if err != nil { + t.Fatal(err) + } + + posts := []models.Post{ + {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID1}, Rating: "safe"}, + {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID2}, Rating: "safe"}, + {BaseModel: models.BaseModel[models.AnthrovePostID]{ID: validPostID3}, Rating: "explicit"}, + } + + for _, post := range posts { + err = postgres.CreatePost(ctx, gormDB, &post) + if err != nil { + t.Fatal(err) + } + err = postgres.CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, models.AnthrovePostID(post.ID)) + if err != nil { + t.Fatal(err) + } + } + + tags := []models.Tag{ + {Name: "JayTheFerret", Type: "artist"}, + {Name: "Ferret", Type: "species"}, + {Name: "Jay", Type: "character"}, + } + + for i, tag := range tags { + err = postgres.CreateTagAndReferenceToPost(ctx, gormDB, posts[i].ID, &tag) + if err != nil { + t.Fatal(err) + } + } + + expectedResult := []models.TagsWithFrequency{ + { + Frequency: 1, + Tags: models.Tag{ + Name: tags[0].Name, + Type: tags[0].Type, + }, + }, + { + Frequency: 1, + Tags: models.Tag{ + Name: tags[1].Name, + Type: tags[1].Type, + }, + }, + { + Frequency: 1, + Tags: models.Tag{ + Name: tags[2].Name, + Type: tags[2].Type, + }, + }, + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + } + tests := []struct { + name string + args args + want []models.TagsWithFrequency + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + anthroveUserID: validAnthroveUserID, + }, + want: expectedResult, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetUserTagWitRelationToFavedPosts(tt.args.ctx, tt.args.anthroveUserID) + if (err != nil) != tt.wantErr { + t.Errorf("GetUserTagWitRelationToFavedPosts() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetUserTagWitRelationToFavedPosts() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetAllTags(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + tags := []models.Tag{ + { + Name: "JayTheFerret", + Type: "artist", + }, + { + Name: "anthro", + Type: "general", + }, + { + Name: "soxx", + Type: "character", + }, + } + + for _, tag := range tags { + err = postgres.CreateTag(ctx, gormDB, &tag) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + } + tests := []struct { + name string + args args + want []models.Tag + wantErr bool + }{ + { + name: "Test 1: Get Tags", + args: args{ + ctx: ctx, + }, + want: tags, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllTags(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTags() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTags() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetAllSources(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + sources := []models.Source{ + { + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + }, + { + DisplayName: "furaffinity", + Domain: "furaffinity.net", + Icon: "icon.furaffinity.net", + }, + { + DisplayName: "fenpaws", + Domain: "fenpa.ws", + Icon: "icon.fenpa.ws", + }, + } + + for _, source := range sources { + err = postgres.CreateSource(ctx, gormDB, &source) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + } + tests := []struct { + name string + args args + want []models.Source + wantErr bool + }{ + { + name: "Test 1: Get all entries", + args: args{ + ctx: ctx, + }, + want: sources, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllSources(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllSources() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkSources(got, tt.want) { + t.Errorf("GetAllSources() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetSourceByDomain(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + source := &models.Source{ + DisplayName: "e621", + Domain: "e621.net", + Icon: "icon.e621.net", + } + + err = postgres.CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + sourceDomain models.AnthroveSourceDomain + } + tests := []struct { + name string + args args + want *models.Source + wantErr bool + }{ + { + name: "Test 1: Valid URL", + args: args{ + ctx: ctx, + sourceDomain: "e621.net", + }, + want: source, + wantErr: false, + }, + { + name: "Test 2: Invalid URL", + args: args{ + ctx: ctx, + sourceDomain: "eeeee.net", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 2: No URL", + args: args{ + ctx: ctx, + sourceDomain: "", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetSourceByDomain(tt.args.ctx, tt.args.sourceDomain) + if (err != nil) != tt.wantErr { + t.Errorf("GetSourceByDomain() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkSource(got, tt.want) { + t.Errorf("GetSourceByDomain() got = %v, want %v", got, tt.want) + } + }) + } +} + +func checkSource(got *models.Source, want *models.Source) bool { + + if want == nil && got == nil { + return true + } + + if got.Domain != want.Domain { + return false + } + + return true + +} + func checkPost(got *models.Post, want *models.Post) bool { if got == nil && want == nil { @@ -791,3 +1911,58 @@ func checkPost(got *models.Post, want *models.Post) bool { return true } + +func checkSources(got []models.Source, want []models.Source) bool { + for i, source := range want { + if source.DisplayName != got[i].DisplayName { + return false + } + if source.Domain != got[i].Domain { + return false + } + if source.Icon != got[i].Icon { + return false + } + } + + return true +} + +func Test_postgresqlConnection_migrateDatabase(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + // Test + type args struct { + dbPool *gorm.DB + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Migrate Databases", + args: args{dbPool: gormDB}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.migrateDatabase(tt.args.dbPool); (err != nil) != tt.wantErr { + t.Errorf("migrateDatabase() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 4fa936d774bc773d12e8cb36e4216cf6d1194517 Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 09:20:52 +0200 Subject: [PATCH 094/124] fix(errors): added const Signed-off-by: SoXX --- internal/postgres/relationships.go | 13 +++++++------ internal/postgres/user.go | 28 ++++++++++++++-------------- pkg/errors/validation.go | 5 +++++ 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index 6be3bde..d66106b 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -3,6 +3,7 @@ package postgres import ( "context" "errors" + errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" @@ -13,11 +14,11 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr var source models.Source if anthrovePostID == "" { - return &errors2.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"} + return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthrovePostID) != 25 { - return &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} + return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } if sourceDomain == "" { @@ -62,11 +63,11 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr 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"} + return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthrovePostID) != 25 { - return &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} + return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } if anthroveUserID == "" { @@ -102,11 +103,11 @@ func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthrove var count int64 if anthrovePostID == "" { - return false, &errors2.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"} + return false, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthrovePostID) != 25 { - return false, &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} + return false, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } if anthroveUserID == "" { diff --git a/internal/postgres/user.go b/internal/postgres/user.go index a21b266..55a1d54 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -13,11 +13,11 @@ import ( func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { if anthroveUserID == "" { - return &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} + return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } user := models.User{ @@ -40,11 +40,11 @@ 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 { if anthroveUserID == "" { - return &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} + return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } if accountId == "" { @@ -103,11 +103,11 @@ func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID mode var count int64 if anthroveUserID == "" { - return 0, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} + return 0, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return 0, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + return 0, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } result := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Count(&count) @@ -131,11 +131,11 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models. userSourceMap := make(map[string]models.UserSource) if anthroveUserID == "" { - return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} + return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } result := db.WithContext(ctx).Model(&models.UserSource{}).Where("user_id = ?", string(anthroveUserID)).Find(&userSources) @@ -179,11 +179,11 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo userSourceMap := make(map[string]models.UserSource) if anthroveUserID == "" { - return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} + return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } if sourceID == "" { @@ -259,11 +259,11 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse var favoritePosts []models.Post if anthroveUserID == "" { - return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} + return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } err := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error @@ -303,11 +303,11 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov var userFavorites []models.UserFavorites if anthroveUserID == "" { - return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} + return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} } result := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites) diff --git a/pkg/errors/validation.go b/pkg/errors/validation.go index a04ac75..69efe47 100644 --- a/pkg/errors/validation.go +++ b/pkg/errors/validation.go @@ -2,6 +2,11 @@ package errors import "fmt" +const ( + AnthroveUserIDIsEmpty = "anthrovePostID cannot be empty" + AnthroveUserIDToShort = "anthrovePostID needs to be 25 characters long" +) + type EntityValidationFailed struct { Reason string } From 6e3edfc1fa110cc1b77f610f457948b245117665 Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 10:02:54 +0200 Subject: [PATCH 095/124] fix(errors): renamed error package Signed-off-by: SoXX --- internal/postgres/post.go | 22 +++++----- internal/postgres/relationships.go | 34 +++++++-------- internal/postgres/source.go | 14 +++--- internal/postgres/tag.go | 20 ++++----- internal/postgres/user.go | 66 ++++++++++++++--------------- pkg/{errors => error}/database.go | 2 +- pkg/{errors => error}/validation.go | 2 +- 7 files changed, 80 insertions(+), 80 deletions(-) rename pkg/{errors => error}/database.go (96%) rename pkg/{errors => error}/validation.go (95%) diff --git a/internal/postgres/post.go b/internal/postgres/post.go index edf7ac3..3679132 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -4,7 +4,7 @@ import ( "context" "errors" - errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" + otterError "git.dragse.it/anthrove/otter-space-sdk/pkg/error" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" @@ -14,19 +14,19 @@ import ( func CreatePost(ctx context.Context, db *gorm.DB, anthrovePost *models.Post) error { if anthrovePost == nil { - return &errors2.EntityValidationFailed{Reason: "anthrovePost is nil"} + return &otterError.EntityValidationFailed{Reason: "anthrovePost is nil"} } result := db.WithContext(ctx).Create(&anthrovePost) if result.Error != nil { if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &errors2.EntityAlreadyExists{} + return &otterError.EntityAlreadyExists{} } return result.Error } if result.RowsAffected == 0 { - return &errors2.NoDataWritten{} + return &otterError.NoDataWritten{} } log.WithFields(log.Fields{ @@ -40,18 +40,18 @@ 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) { if anthrovePostID == "" { - return nil, &errors2.EntityValidationFailed{Reason: "anthrovePostID is not set"} + return nil, &otterError.EntityValidationFailed{Reason: "anthrovePostID is not set"} } if len(anthrovePostID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} + return nil, &otterError.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} } var post models.Post result := db.WithContext(ctx).First(&post, "id = ?", anthrovePostID) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } @@ -62,7 +62,7 @@ func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models func GetPostByURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.Post, error) { if sourceURL == "" { - return nil, &errors2.EntityValidationFailed{Reason: "sourceURL is not set"} + return nil, &otterError.EntityValidationFailed{Reason: "sourceURL is not set"} } var post models.Post @@ -70,7 +70,7 @@ func GetPostByURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.P if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } @@ -81,7 +81,7 @@ func GetPostByURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.P func GetPostBySourceID(ctx context.Context, db *gorm.DB, sourceID models.AnthroveSourceID) (*models.Post, error) { if sourceID == "" { - return nil, &errors2.EntityValidationFailed{Reason: "sourceID is not set"} + return nil, &otterError.EntityValidationFailed{Reason: "sourceID is not set"} } var post models.Post @@ -89,7 +89,7 @@ func GetPostBySourceID(ctx context.Context, db *gorm.DB, sourceID models.Anthrov if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index d66106b..8aa1079 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -4,7 +4,7 @@ import ( "context" "errors" - errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" + otterError "git.dragse.it/anthrove/otter-space-sdk/pkg/error" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -14,22 +14,22 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr var source models.Source if anthrovePostID == "" { - return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthrovePostID) != 25 { - return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } if sourceDomain == "" { - return &errors2.EntityValidationFailed{Reason: "sourceDomain cannot be empty"} + return &otterError.EntityValidationFailed{Reason: "sourceDomain cannot be empty"} } // Find the source result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&source) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return &errors2.NoDataFound{} + return &otterError.NoDataFound{} } return result.Error } @@ -43,13 +43,13 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr if result.Error != nil { if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &errors2.EntityAlreadyExists{} + return &otterError.EntityAlreadyExists{} } return result.Error } if result.RowsAffected == 0 { - return &errors2.NoDataWritten{} + return &otterError.NoDataWritten{} } log.WithFields(log.Fields{ @@ -63,15 +63,15 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { if anthrovePostID == "" { - return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthrovePostID) != 25 { - return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } if anthroveUserID == "" { - return &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} + return &otterError.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} } userFavorite := models.UserFavorites{ @@ -82,13 +82,13 @@ func CreateReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthrov result := db.WithContext(ctx).Create(&userFavorite) if result.Error != nil { if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &errors2.EntityAlreadyExists{} + return &otterError.EntityAlreadyExists{} } return result.Error } if result.RowsAffected == 0 { - return &errors2.NoDataWritten{} + return &otterError.NoDataWritten{} } log.WithFields(log.Fields{ @@ -103,25 +103,25 @@ func CheckReferenceBetweenUserAndPost(ctx context.Context, db *gorm.DB, anthrove var count int64 if anthrovePostID == "" { - return false, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return false, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthrovePostID) != 25 { - return false, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return false, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } if anthroveUserID == "" { - return false, &errors2.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} + return false, &otterError.EntityValidationFailed{Reason: "anthroveUserID cannot be empty"} } if len(anthroveUserID) != 25 { - return false, &errors2.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} + return false, &otterError.EntityValidationFailed{Reason: "anthroveUserID needs to be 25 characters long"} } 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, &otterError.NoDataFound{} } return false, result.Error } diff --git a/internal/postgres/source.go b/internal/postgres/source.go index 9321e42..bdb2122 100644 --- a/internal/postgres/source.go +++ b/internal/postgres/source.go @@ -4,7 +4,7 @@ import ( "context" "errors" - errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" + otterError "git.dragse.it/anthrove/otter-space-sdk/pkg/error" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" @@ -15,20 +15,20 @@ import ( func CreateSource(ctx context.Context, db *gorm.DB, anthroveSource *models.Source) error { if anthroveSource.Domain == "" { - return &errors2.EntityValidationFailed{Reason: "Domain is required"} + return &otterError.EntityValidationFailed{Reason: "Domain is required"} } result := db.WithContext(ctx).Where(models.Source{Domain: anthroveSource.Domain}).FirstOrCreate(anthroveSource) if result.Error != nil { if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &errors2.EntityAlreadyExists{} + return &otterError.EntityAlreadyExists{} } return result.Error } if result.RowsAffected == 0 { - return &errors2.NoDataWritten{} + return &otterError.NoDataWritten{} } log.WithFields(log.Fields{ @@ -48,7 +48,7 @@ func GetAllSource(ctx context.Context, db *gorm.DB) ([]models.Source, error) { if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } @@ -65,14 +65,14 @@ func GetSourceByDomain(ctx context.Context, db *gorm.DB, sourceDomain models.Ant var sources models.Source if sourceDomain == "" { - return nil, &errors2.EntityValidationFailed{Reason: "AnthroveSourceDomain is not set"} + return nil, &otterError.EntityValidationFailed{Reason: "AnthroveSourceDomain is not set"} } result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&sources) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 86f60d8..93b5467 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -4,7 +4,7 @@ import ( "context" "errors" - errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" + otterError "git.dragse.it/anthrove/otter-space-sdk/pkg/error" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -13,19 +13,19 @@ import ( func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { if tag == nil { - return &errors2.EntityValidationFailed{Reason: "Tag is nil"} + return &otterError.EntityValidationFailed{Reason: "Tag is nil"} } result := db.WithContext(ctx).Where(tag).Create(tag) if result.Error != nil { if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &errors2.EntityAlreadyExists{} + return &otterError.EntityAlreadyExists{} } return result.Error } if result.RowsAffected == 0 { - return &errors2.NoDataWritten{} + return &otterError.NoDataWritten{} } log.WithFields(log.Fields{ @@ -39,15 +39,15 @@ func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, tag *models.Tag) error { if anthrovePostID == "" { - return &errors2.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"} + return &otterError.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"} } if len(anthrovePostID) != 25 { - return &errors2.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} + return &otterError.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"} } if tag == nil { - return &errors2.EntityValidationFailed{Reason: "Tag is nil"} + return &otterError.EntityValidationFailed{Reason: "Tag is nil"} } pgPost := models.Post{ @@ -59,9 +59,9 @@ func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, anthrovePostI err := db.WithContext(ctx).Model(&pgPost).Association("Tags").Append(tag) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return &errors2.NoDataFound{} + return &otterError.NoDataFound{} } - return errors.Join(err, &errors2.NoRelationCreated{}) + return errors.Join(err, &otterError.NoRelationCreated{}) } log.WithFields(log.Fields{ @@ -80,7 +80,7 @@ func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) { if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 55a1d54..499911b 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -4,7 +4,7 @@ import ( "context" "errors" - errors2 "git.dragse.it/anthrove/otter-space-sdk/pkg/errors" + otterError "git.dragse.it/anthrove/otter-space-sdk/pkg/error" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -13,11 +13,11 @@ import ( func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { if anthroveUserID == "" { - return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } user := models.User{ @@ -29,7 +29,7 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove result := db.WithContext(ctx).FirstOrCreate(&user) if result.Error != nil { if errors.Is(result.Error, gorm.ErrDuplicatedKey) { - return &errors2.EntityAlreadyExists{} + return &otterError.EntityAlreadyExists{} } return result.Error } @@ -40,19 +40,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 { if anthroveUserID == "" { - return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } if accountId == "" { - return &errors2.EntityValidationFailed{Reason: "accountID cannot be empty"} + return &otterError.EntityValidationFailed{Reason: "accountID cannot be empty"} } if accountUsername == "" { - return &errors2.EntityValidationFailed{Reason: "accountUsername cannot be empty"} + return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"} } err := CreateUser(ctx, db, anthroveUserID) @@ -67,7 +67,7 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs result := db.WithContext(ctx).Where(&source).First(&source) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return &errors2.NoDataFound{} + return &otterError.NoDataFound{} } return result.Error } @@ -82,11 +82,11 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs result = db.WithContext(ctx).FirstOrCreate(&userSource) if result.Error != nil { - return errors.Join(result.Error, &errors2.NoRelationCreated{}) + return errors.Join(result.Error, &otterError.NoRelationCreated{}) } if result.RowsAffected == 0 { - return &errors2.NoDataWritten{} + return &otterError.NoDataWritten{} } log.WithFields(log.Fields{ @@ -103,17 +103,17 @@ func GetUserFavoritesCount(ctx context.Context, db *gorm.DB, anthroveUserID mode var count int64 if anthroveUserID == "" { - return 0, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return 0, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return 0, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return 0, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } result := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Count(&count) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return 0, &errors2.NoDataFound{} + return 0, &otterError.NoDataFound{} } return 0, result.Error } @@ -131,17 +131,17 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models. userSourceMap := make(map[string]models.UserSource) if anthroveUserID == "" { - return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } 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, &otterError.NoDataFound{} } return nil, result.Error } @@ -151,7 +151,7 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models. result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } @@ -179,25 +179,25 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo userSourceMap := make(map[string]models.UserSource) if anthroveUserID == "" { - return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } if sourceID == "" { - return nil, &errors2.EntityValidationFailed{Reason: "sourceID cannot be empty"} + return nil, &otterError.EntityValidationFailed{Reason: "sourceID cannot be empty"} } if len(sourceID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: "sourceID needs to be 25 characters long"} + return nil, &otterError.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, &otterError.NoDataFound{} } return nil, result.Error } @@ -207,7 +207,7 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } @@ -238,7 +238,7 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU result := db.WithContext(ctx).Model(&models.User{}).Find(&users) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } @@ -259,17 +259,17 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse var favoritePosts []models.Post if anthroveUserID == "" { - return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } err := db.WithContext(ctx).Model(&models.UserFavorites{}).Where("user_id = ?", string(anthroveUserID)).Offset(skip).Limit(limit).Find(&userFavorites).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, err } @@ -279,7 +279,7 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse err = db.WithContext(ctx).Model(&models.Post{}).Where("id = ?", userFavorite.PostID).First(&post).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, err } @@ -303,17 +303,17 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov var userFavorites []models.UserFavorites if anthroveUserID == "" { - return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDIsEmpty} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } if len(anthroveUserID) != 25 { - return nil, &errors2.EntityValidationFailed{Reason: errors2.AnthroveUserIDToShort} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } 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, &otterError.NoDataFound{} } return nil, result.Error } @@ -328,7 +328,7 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov result = db.WithContext(ctx).Preload("Tags").First(&post, "id = ?", userFavorite.PostID) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &errors2.NoDataFound{} + return nil, &otterError.NoDataFound{} } return nil, result.Error } diff --git a/pkg/errors/database.go b/pkg/error/database.go similarity index 96% rename from pkg/errors/database.go rename to pkg/error/database.go index 5559b95..278a043 100644 --- a/pkg/errors/database.go +++ b/pkg/error/database.go @@ -1,4 +1,4 @@ -package errors +package error type EntityAlreadyExists struct{} diff --git a/pkg/errors/validation.go b/pkg/error/validation.go similarity index 95% rename from pkg/errors/validation.go rename to pkg/error/validation.go index 69efe47..889ae13 100644 --- a/pkg/errors/validation.go +++ b/pkg/error/validation.go @@ -1,4 +1,4 @@ -package errors +package error import "fmt" From cb04347dd519875ca3e6bf2a7c6794c20bfc3523 Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 11:23:27 +0200 Subject: [PATCH 096/124] fix(errors): more tests Signed-off-by: SoXX --- internal/postgres/post_test.go | 9 ++ internal/postgres/relationships_test.go | 133 +++++++++++++++++++----- internal/postgres/source_test.go | 59 ++++++++++- internal/postgres/tag.go | 3 +- internal/postgres/tag_test.go | 72 ++++++++++++- internal/postgres/user.go | 9 +- internal/postgres/user_test.go | 90 +++++++++++++++- 7 files changed, 336 insertions(+), 39 deletions(-) diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index 99e5b32..fba733a 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -63,6 +63,15 @@ func TestCreateAnthrovePostNode(t *testing.T) { }, wantErr: true, }, + { + name: "Test 3: Nill", + args: args{ + ctx: context.Background(), + db: gormDB, + anthrovePost: nil, + }, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go index a758ad2..dec686d 100644 --- a/internal/postgres/relationships_test.go +++ b/internal/postgres/relationships_test.go @@ -3,10 +3,11 @@ package postgres import ( "context" "fmt" + "testing" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" - "testing" ) func TestCheckUserToPostLink(t *testing.T) { @@ -105,6 +106,28 @@ func TestCheckUserToPostLink(t *testing.T) { want: false, wantErr: true, }, + { + name: "Test 5: No AnthrovePostID given", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + anthrovePostID: "123456", + }, + want: false, + wantErr: true, + }, + { + name: "Test 6: No anthrovePostID given", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: invalidUserID, + anthrovePostID: "", + }, + want: false, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -120,7 +143,8 @@ func TestCheckUserToPostLink(t *testing.T) { } } -func TestEstablishAnthrovePostToSourceLink(t *testing.T) { +func TestCheckUserToPostLinkWithNoData(t *testing.T) { + // Setup trow away container ctx := context.Background() container, gormDB, err := test.StartPostgresContainer(ctx) @@ -130,9 +154,20 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { defer container.Terminate(ctx) // Setup Test + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validPostID := models.AnthrovePostID(fmt.Sprintf("%025s", "Post1")) + + err = CreateUser(ctx, gormDB, validUserID) + if err != nil { + t.Fatal(err) + } + post := &models.Post{ BaseModel: models.BaseModel[models.AnthrovePostID]{ - ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), + ID: validPostID, }, Rating: "safe", } @@ -142,74 +177,100 @@ func TestEstablishAnthrovePostToSourceLink(t *testing.T) { t.Fatal(err) } - source := &models.Source{ - DisplayName: "e621", - Domain: "e621.net", - Icon: "icon.e621.net", - } - err = CreateSource(ctx, gormDB, source) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validUserID, post.ID) if err != nil { t.Fatal(err) } // Test type args struct { - ctx context.Context - db *gorm.DB - anthrovePostID models.AnthrovePostID - sourceDomain models.AnthroveSourceDomain - anthrovePostRelationship *models.PostReference + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + anthrovePostID models.AnthrovePostID } tests := []struct { name string args args + want bool wantErr bool }{ { - name: "Test 1: Valid AnthrovePostID and anthroveSourceDomain", + name: "Test 1: Valid AnthroveUserID and AnthrovePostID", args: args{ ctx: ctx, db: gormDB, + anthroveUserID: validUserID, anthrovePostID: post.ID, - sourceDomain: "e621.net", }, + want: true, wantErr: false, }, { - name: "Test 2: Invalid AnthrovePostID and Valid anthroveSourceDomain", + name: "Test 2: Valid AnthroveUserID and invalid AnthrovePostID", args: args{ ctx: ctx, db: gormDB, + anthroveUserID: validUserID, + anthrovePostID: "qadw", + }, + want: false, + wantErr: true, + }, + { + name: "Test 3: Valid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: invalidUserID, + anthrovePostID: post.ID, + }, + want: false, + wantErr: true, + }, + { + name: "Test 4: Invalid AnthrovePostID and invalid AnthroveUserID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: invalidUserID, anthrovePostID: "123456", - sourceDomain: "e621.net", }, + want: false, wantErr: true, }, { - name: "Test 3: Invalid anthroveSourceDomain and Valid AnthrovePostID", + name: "Test 5: No AnthrovePostID given", args: args{ ctx: ctx, db: gormDB, - anthrovePostID: "1234", - sourceDomain: "fa.banana", + anthroveUserID: "", + anthrovePostID: "123456", }, + want: false, wantErr: true, }, { - name: "Test 4: Invalid anthroveSourceDomain and Invalid AnthrovePostID", + name: "Test 6: No anthrovePostID given", args: args{ ctx: ctx, db: gormDB, - anthrovePostID: "696969", - sourceDomain: "hehe.funny.number", + anthroveUserID: invalidUserID, + anthrovePostID: "", }, + want: false, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CreateReferenceBetweenPostAndSource(tt.args.ctx, tt.args.db, tt.args.anthrovePostID, tt.args.sourceDomain); (err != nil) != tt.wantErr { - t.Errorf("CreateReferenceBetweenPostAndSource() error = %v, wantErr %v", err, tt.wantErr) + got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) + if (err != nil) != tt.wantErr { + t.Errorf("CheckReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("CheckReferenceBetweenUserAndPost() got = %v, want %v", got, tt.want) } }) } @@ -300,6 +361,26 @@ func TestEstablishUserToPostLink(t *testing.T) { }, wantErr: true, }, + { + name: "Test 5: AnthrovePostID is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: invalidUserID, + anthrovePostID: "", + }, + wantErr: true, + }, + { + name: "Test 6: anthroveUserID is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + anthrovePostID: validPostID, + }, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go index b618017..bcb38bd 100644 --- a/internal/postgres/source_test.go +++ b/internal/postgres/source_test.go @@ -3,10 +3,11 @@ package postgres import ( "context" "fmt" + "testing" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" - "testing" ) func TestCreateSourceNode(t *testing.T) { @@ -30,7 +31,13 @@ func TestCreateSourceNode(t *testing.T) { } invalidSource := &models.Source{ - Domain: "", + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validPostID}, + Domain: "notfound.intern", + } + + invalidSourceDomain := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: validPostID}, + Domain: "", } // Test @@ -58,7 +65,7 @@ func TestCreateSourceNode(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveSource: invalidSource, + anthroveSource: invalidSourceDomain, }, wantErr: true, }, @@ -67,7 +74,7 @@ func TestCreateSourceNode(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - anthroveSource: validSource, + anthroveSource: invalidSource, }, wantErr: true, }, @@ -152,6 +159,50 @@ func TestGetAllSourceNodes(t *testing.T) { } } +func TestGetAllSourceWithNoData(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Test + type args struct { + ctx context.Context + db *gorm.DB + } + tests := []struct { + name string + args args + want []models.Source + wantErr bool + }{ + { + name: "Test 1: Get all entries", + args: args{ + ctx: ctx, + db: gormDB, + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllSource(tt.args.ctx, tt.args.db) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllSource() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkSourcesNode(got, tt.want) { + t.Errorf("GetAllSource() got = %v, want %v", got, tt.want) + } + }) + } +} + func TestGetSourceNodesByURL(t *testing.T) { // Setup trow away container ctx := context.Background() diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 93b5467..23e23ef 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -16,7 +16,7 @@ func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { return &otterError.EntityValidationFailed{Reason: "Tag is nil"} } - result := db.WithContext(ctx).Where(tag).Create(tag) + result := db.WithContext(ctx).Create(tag) if result.Error != nil { if errors.Is(result.Error, gorm.ErrDuplicatedKey) { return &otterError.EntityAlreadyExists{} @@ -77,7 +77,6 @@ func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) { var tags []models.Tag result := db.WithContext(ctx).Find(&tags) - if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, &otterError.NoDataFound{} diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index a100774..045cd96 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -3,10 +3,11 @@ package postgres import ( "context" "fmt" + "testing" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" - "testing" ) func TestCreateTagNodeWitRelation(t *testing.T) { @@ -54,7 +55,7 @@ func TestCreateTagNodeWitRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - PostID: models.AnthrovePostID(post.ID), + PostID: post.ID, tag: tag, }, wantErr: false, @@ -64,7 +65,7 @@ func TestCreateTagNodeWitRelation(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - PostID: models.AnthrovePostID(post.ID), + PostID: post.ID, tag: nil, }, wantErr: true, @@ -180,3 +181,68 @@ func checkTag(got []models.Tag, want []models.Tag) bool { return true } + +func TestCreateTag(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTag := models.Tag{ + Name: "JayTheFerret", + Type: "artist", + } + + invalidTag := models.Tag{} + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tag *models.Tag + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Tag", + args: args{ + ctx: ctx, + db: gormDB, + tag: &validTag, + }, + wantErr: false, + }, + { + name: "Test 2: Duplicate Tag", + args: args{ + ctx: ctx, + db: gormDB, + tag: &validTag, + }, + wantErr: true, + }, + { + name: "Test 3: Invalid Tag", + args: args{ + ctx: ctx, + db: gormDB, + tag: &invalidTag, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CreateTag(tt.args.ctx, tt.args.db, tt.args.tag); (err != nil) != tt.wantErr { + t.Errorf("CreateTag() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 499911b..e10495e 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -34,6 +34,10 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove return result.Error } + if result.RowsAffected == 0 { + return &otterError.EntityAlreadyExists{} + } + return nil } @@ -325,7 +329,10 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov for _, userFavorite := range userFavorites { var post models.Post - result = db.WithContext(ctx).Preload("Tags").First(&post, "id = ?", userFavorite.PostID) + result = db.WithContext(ctx).Preload("Tags", func(db *gorm.DB) *gorm.DB { + return db.Order("tag_type ASC") + }).First(&post, "id = ?", userFavorite.PostID) + if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, &otterError.NoDataFound{} diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 3c63d8c..4477bea 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -54,6 +54,15 @@ func TestCreateUser(t *testing.T) { }, wantErr: true, }, + { + name: "Test 3: No anthroveUserID given", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + }, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -347,7 +356,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { wantErr: true, }, { - name: "Test 5: Valid AnthroveUserID and No SourceDisplayName", + name: "Test 5: Valid AnthroveUserID and No anthroveUserID", args: args{ ctx: ctx, db: gormDB, @@ -358,7 +367,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { wantErr: true, }, { - name: "Test 6: No AnthroveUserID and No SourceDisplayName", + name: "Test 6: No AnthroveUserID and No anthroveUserID", args: args{ ctx: ctx, db: gormDB, @@ -368,6 +377,17 @@ func TestGetUserSourceBySourceID(t *testing.T) { want: nil, wantErr: true, }, + { + name: "Test 7: No anthroveUserID given", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: "", + }, + want: nil, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -505,6 +525,30 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { want: expectedResult3, wantErr: false, }, + { + name: "Test 4: No anthroveUserID given", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + skip: 0, + limit: 3, + }, + want: nil, + wantErr: true, + }, + { + name: "Test 5: Short anthroveUserID given", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "aaa", + skip: 0, + limit: 3, + }, + want: nil, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -725,6 +769,26 @@ func TestGetUserSourceLinks(t *testing.T) { want: expectedResult, wantErr: false, }, + { + name: "Test 3: No AnthroveID", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 1: AnthroveID to short", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "aaa", + }, + want: nil, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -772,7 +836,7 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { if err != nil { t.Fatal(err) } - err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, models.AnthrovePostID(post.ID)) + err = CreateReferenceBetweenUserAndPost(ctx, gormDB, validAnthroveUserID, post.ID) if err != nil { t.Fatal(err) } @@ -837,6 +901,26 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { want: expectedResult, wantErr: false, }, + { + name: "Test 2: No anthroveUserID given", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: short anthroveUserID given", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "aaa", + }, + want: nil, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 615a6b1a25e8eddeabdfbd915a53adc256fa74a7 Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 11:31:42 +0200 Subject: [PATCH 097/124] fix(errors): fix unneeded error handling Signed-off-by: SoXX --- internal/postgres/source_test.go | 44 -------------------------------- internal/postgres/user.go | 5 +--- internal/postgres/user_test.go | 8 +++--- 3 files changed, 5 insertions(+), 52 deletions(-) diff --git a/internal/postgres/source_test.go b/internal/postgres/source_test.go index bcb38bd..dc5c58e 100644 --- a/internal/postgres/source_test.go +++ b/internal/postgres/source_test.go @@ -159,50 +159,6 @@ func TestGetAllSourceNodes(t *testing.T) { } } -func TestGetAllSourceWithNoData(t *testing.T) { - // Setup trow away container - ctx := context.Background() - container, gormDB, err := test.StartPostgresContainer(ctx) - if err != nil { - t.Fatalf("Could not start PostgreSQL container: %v", err) - } - defer container.Terminate(ctx) - - // Test - type args struct { - ctx context.Context - db *gorm.DB - } - tests := []struct { - name string - args args - want []models.Source - wantErr bool - }{ - { - name: "Test 1: Get all entries", - args: args{ - ctx: ctx, - db: gormDB, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GetAllSource(tt.args.ctx, tt.args.db) - if (err != nil) != tt.wantErr { - t.Errorf("GetAllSource() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !checkSourcesNode(got, tt.want) { - t.Errorf("GetAllSource() got = %v, want %v", got, tt.want) - } - }) - } -} - func TestGetSourceNodesByURL(t *testing.T) { // Setup trow away container ctx := context.Background() diff --git a/internal/postgres/user.go b/internal/postgres/user.go index e10495e..9346cb5 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -28,16 +28,13 @@ func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.Anthrove result := db.WithContext(ctx).FirstOrCreate(&user) if result.Error != nil { + if errors.Is(result.Error, gorm.ErrDuplicatedKey) { return &otterError.EntityAlreadyExists{} } return result.Error } - if result.RowsAffected == 0 { - return &otterError.EntityAlreadyExists{} - } - return nil } diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 4477bea..dd0932b 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -707,7 +707,7 @@ func TestGetUserSourceLinks(t *testing.T) { } err = CreateSource(ctx, gormDB, eSource) if err != nil { - t.Fatal(err) + t.Fatal("Create Source e621:", err) } faSource := &models.Source{ @@ -717,7 +717,7 @@ func TestGetUserSourceLinks(t *testing.T) { } err = CreateSource(ctx, gormDB, faSource) if err != nil { - t.Fatal(err) + t.Fatal("Create Source fa:", err) } expectedResult := make(map[string]models.UserSource) @@ -740,11 +740,11 @@ func TestGetUserSourceLinks(t *testing.T) { err = CreateUserWithRelationToSource(ctx, gormDB, validAnthroveUserID, eSource.ID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { - t.Fatal(err) + t.Fatal("CreateUserWithRelationToSource e621:", err) } err = CreateUserWithRelationToSource(ctx, gormDB, validAnthroveUserID, faSource.ID, expectedResult["fa"].UserID, expectedResult["fa"].AccountUsername) if err != nil { - t.Fatal(err) + t.Fatal("CreateUserWithRelationToSource fa:", err) } // Test From a026563835604312e3f9e3b2a318caddbfa51c57 Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 11:48:25 +0200 Subject: [PATCH 098/124] fix(errors): added more tests Signed-off-by: SoXX --- pkg/error/database_test.go | 83 ++++++++++++++++++++++++++++++++++++ pkg/error/validation_test.go | 30 +++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 pkg/error/database_test.go create mode 100644 pkg/error/validation_test.go diff --git a/pkg/error/database_test.go b/pkg/error/database_test.go new file mode 100644 index 0000000..5fd2e1f --- /dev/null +++ b/pkg/error/database_test.go @@ -0,0 +1,83 @@ +package error + +import "testing" + +func TestEntityAlreadyExists_Error(t *testing.T) { + tests := []struct { + name string + want string + }{ + { + name: "Test : Valid error String", + want: "EntityAlreadyExists error", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &EntityAlreadyExists{} + if got := e.Error(); got != tt.want { + t.Errorf("Error() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNoDataFound_Error(t *testing.T) { + tests := []struct { + name string + want string + }{ + { + name: "Test : Valid error String", + want: "NoDataFound error", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &NoDataFound{} + if got := e.Error(); got != tt.want { + t.Errorf("Error() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNoDataWritten_Error(t *testing.T) { + tests := []struct { + name string + want string + }{ + { + name: "Test : Valid error String", + want: "NoDataWritten error", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &NoDataWritten{} + if got := e.Error(); got != tt.want { + t.Errorf("Error() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNoRelationCreated_Error(t *testing.T) { + tests := []struct { + name string + want string + }{ + { + name: "Test : Valid error String", + want: "relationship creation error", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &NoRelationCreated{} + if got := e.Error(); got != tt.want { + t.Errorf("Error() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/error/validation_test.go b/pkg/error/validation_test.go new file mode 100644 index 0000000..88e9d3c --- /dev/null +++ b/pkg/error/validation_test.go @@ -0,0 +1,30 @@ +package error + +import "testing" + +func TestEntityValidationFailed_Error(t *testing.T) { + type fields struct { + Reason string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "Test 1: Reason", + fields: fields{Reason: "TEST ERROR"}, + want: "Entity validation failed: TEST ERROR", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := EntityValidationFailed{ + Reason: tt.fields.Reason, + } + if got := e.Error(); got != tt.want { + t.Errorf("Error() = %v, want %v", got, tt.want) + } + }) + } +} From 0a5359d7231fec6a28ec9aebfb6a5be093c49226 Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 12:07:55 +0200 Subject: [PATCH 099/124] ci: fix go command to show in log Signed-off-by: SoXX --- .gitea/workflows/ build_check.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/ build_check.yaml b/.gitea/workflows/ build_check.yaml index 5a50130..cede029 100644 --- a/.gitea/workflows/ build_check.yaml +++ b/.gitea/workflows/ build_check.yaml @@ -28,7 +28,7 @@ jobs: cache: true # optional - name: Execute Go Test files with coverage report - run: go test -v ./... -json -coverprofile="coverage.out" > "test-report.out" + run: go test -v ./... -json -coverprofile="coverage.out" | tee "test-report.out" - uses: sonarsource/sonarqube-scan-action@master env: From 97d314ba3e44babc74e92d6109a96d68affed68d Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 12:20:38 +0200 Subject: [PATCH 100/124] ci: fix go command to show in log Signed-off-by: SoXX --- .gitea/workflows/ build_check.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/ build_check.yaml b/.gitea/workflows/ build_check.yaml index cede029..4d35c68 100644 --- a/.gitea/workflows/ build_check.yaml +++ b/.gitea/workflows/ build_check.yaml @@ -28,7 +28,7 @@ jobs: cache: true # optional - name: Execute Go Test files with coverage report - run: go test -v ./... -json -coverprofile="coverage.out" | tee "test-report.out" + run: TESTCONTAINERS_RYUK_DISABLED=true go test -v ./... -json -coverprofile="coverage.out" | tee "test-report.out" - uses: sonarsource/sonarqube-scan-action@master env: From a9a21581bdac2966972a445a5e27d90fd938aa8d Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 12:40:59 +0200 Subject: [PATCH 101/124] test(helper): extend the waiting time to 10 seconds Signed-off-by: SoXX --- test/helper.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/helper.go b/test/helper.go index 6fed12e..bb3f057 100644 --- a/test/helper.go +++ b/test/helper.go @@ -3,16 +3,17 @@ package test import ( "context" "database/sql" + "net/url" + "strconv" + "strings" + "time" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" migrate "github.com/rubenv/sql-migrate" postgrescontainer "github.com/testcontainers/testcontainers-go/modules/postgres" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" - "net/url" - "strconv" - "strings" - "time" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -34,7 +35,7 @@ func StartPostgresContainer(ctx context.Context) (*postgrescontainer.PostgresCon postgrescontainer.WithPassword(databasePassword), testcontainers.WithWaitStrategy( wait.ForLog("database system is ready to accept connections"). - WithOccurrence(2).WithStartupTimeout(5*time.Second)), + WithOccurrence(2).WithStartupTimeout(10*time.Second)), ) if err != nil { return nil, nil, err From e29cea6e3cb8a768186984ba0aa736f8f5a0f04e Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 16:12:10 +0200 Subject: [PATCH 102/124] feat(functions): enhanced function with RAW SQL Signed-off-by: SoXX --- internal/postgres/relationships.go | 22 +++------- internal/postgres/user.go | 41 ++++++------------- pkg/database/database.go | 2 +- .../migrations/001_inital_database.sql | 2 +- pkg/database/postgres.go | 6 +-- pkg/models/const.go | 1 + 6 files changed, 23 insertions(+), 51 deletions(-) diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index 8aa1079..5e8e8e6 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -10,9 +10,7 @@ import ( "gorm.io/gorm" ) -func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { - var source models.Source - +func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error { if anthrovePostID == "" { return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } @@ -25,26 +23,16 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr return &otterError.EntityValidationFailed{Reason: "sourceDomain cannot be empty"} } - // Find the source - result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&source) + result := db.WithContext(ctx).Exec(`INSERT INTO "PostReference" (post_id, source_id, url) SELECT $1, source.id, $2 FROM "Source" AS source WHERE domain = $3;`, anthrovePostID, postURL, sourceDomain) + if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return &otterError.NoDataFound{} } - return result.Error - } - - // Establish the relationship - result = db.WithContext(ctx).Create(models.PostReference{ - PostID: string(anthrovePostID), - SourceID: string(source.ID), - URL: string(sourceDomain), - }) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrDuplicatedKey) { + if errors.Is(result.Error, gorm.ErrCheckConstraintViolated) { return &otterError.EntityAlreadyExists{} } + return result.Error } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 9346cb5..404c32c 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -56,46 +56,29 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"} } - err := CreateUser(ctx, db, anthroveUserID) - if err != nil { - return err - } + result := db.WithContext(ctx).Exec(`WITH userObj AS ( + INSERT INTO "User" (id) + VALUES ($1) + ON CONFLICT (id) DO NOTHING + ) + INSERT INTO "UserSource" (user_id, source_id, account_username, account_id) + SELECT $2, source.id, $3, $4 + FROM "Source" AS source + WHERE source.id = $5;`, anthroveUserID, anthroveUserID, accountUsername, accountId, sourceID) - source := models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: sourceID}, - } - - result := db.WithContext(ctx).Where(&source).First(&source) if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return &otterError.NoDataFound{} + if errors.Is(result.Error, gorm.ErrDuplicatedKey) { + return &otterError.EntityAlreadyExists{} } return result.Error } - userSource := models.UserSource{ - User: models.User{BaseModel: models.BaseModel[models.AnthroveUserID]{ID: anthroveUserID}}, - SourceID: string(source.ID), - AccountUsername: accountUsername, - AccountID: accountId, - UserID: string(anthroveUserID), - } - - result = db.WithContext(ctx).FirstOrCreate(&userSource) - if result.Error != nil { - return errors.Join(result.Error, &otterError.NoRelationCreated{}) - } - - if result.RowsAffected == 0 { - return &otterError.NoDataWritten{} - } - log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, "source_id": sourceID, "account_username": accountUsername, "account_id": accountId, - }).Trace("database: created user-source relationship") + }).Info("database: created user-source relationship") return nil } diff --git a/pkg/database/database.go b/pkg/database/database.go index 10d203a..f8be8ef 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -23,7 +23,7 @@ type OtterSpace interface { CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error // CreateReferenceBetweenPostAndSource links a post with a source. - CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error + CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error // CreateReferenceBetweenUserAndPost links a user with a post. CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index e6758e3..d580538 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -95,7 +95,7 @@ CREATE TABLE "UserSource" account_username TEXT, account_id TEXT, PRIMARY KEY (user_id, source_id), - UNIQUE (account_username, account_id) + UNIQUE (source_id, account_username, account_id) ); CREATE TABLE "post_tags" diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 4245c9b..676d308 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -47,7 +47,7 @@ func (p *postgresqlConnection) Connect(_ context.Context, config models.Database dbLogger := logger2.New(log2.New(os.Stdout, "\r\n", log2.LstdFlags), logger2.Config{ SlowThreshold: 200 * time.Millisecond, - LogLevel: logger2.Warn, + LogLevel: logger2.Info, IgnoreRecordNotFoundError: true, Colorful: true, }) @@ -88,8 +88,8 @@ func (p *postgresqlConnection) CreateTagAndReferenceToPost(ctx context.Context, return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag) } -func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { - return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain) +func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error { + return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain, postURL) } func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { diff --git a/pkg/models/const.go b/pkg/models/const.go index 5b0e59a..f95434f 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -4,6 +4,7 @@ type AnthroveUserID string type AnthrovePostID string type AnthroveSourceID string type AnthroveSourceDomain string +type AnthrovePostURL string type Rating string type TagType string From a71f75976325e21177110ac93174f2274552ca3b Mon Sep 17 00:00:00 2001 From: SoXX Date: Thu, 27 Jun 2024 16:11:16 +0200 Subject: [PATCH 103/124] feat(functions): fixing bugs Signed-off-by: SoXX --- internal/postgres/post_test.go | 7 ++-- internal/postgres/user.go | 59 ++++++++++++---------------------- internal/postgres/user_test.go | 28 +++++++++------- pkg/database/database.go | 2 +- 4 files changed, 41 insertions(+), 55 deletions(-) diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index fba733a..735f6b5 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -176,6 +176,7 @@ func TestGetPostBySourceURL(t *testing.T) { BaseModel: models.BaseModel[models.AnthrovePostID]{ ID: models.AnthrovePostID(fmt.Sprintf("%025s", "1")), }, + Rating: "safe", } @@ -198,7 +199,7 @@ func TestGetPostBySourceURL(t *testing.T) { t.Fatal("Could not create source", err) } - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain)) + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.org") if err != nil { t.Fatal("Could not create source reference", err) } @@ -220,7 +221,7 @@ func TestGetPostBySourceURL(t *testing.T) { args: args{ ctx: ctx, db: gormDB, - sourceURL: source.Domain, + sourceURL: "http://test.org", }, want: post, wantErr: false, @@ -297,7 +298,7 @@ func TestGetPostBySourceID(t *testing.T) { t.Fatal("Could not create source", err) } - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain)) + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.otg") if err != nil { t.Fatal("Could not create source reference", err) } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 404c32c..aa5d5a5 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -283,8 +283,15 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse return &models.FavoriteList{Posts: favoritePosts}, nil } +// Workaround, should be changed later maybe, but its not that bad right now +type selectFrequencyTag struct { + tagName string `gorm:"tag_name"` + count int64 `gorm:"count"` + tagType models.TagType `gorm:"tag_type"` +} + func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { - var userFavorites []models.UserFavorites + var queryUserFavorites []selectFrequencyTag if anthroveUserID == "" { return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} @@ -294,7 +301,11 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } - result := db.WithContext(ctx).Where("user_id = ?", string(anthroveUserID)).Find(&userFavorites) + result := db.WithContext(ctx).Raw( + `WITH user_posts AS ( + SELECT post_id FROM "UserFavorites" WHERE user_id = $1 + ) + SELECT post_tags.tag_name AS tag_name, count(*) AS count, (SELECT tag_type FROM "Tag" WHERE "Tag".name = post_tags.tag_name LIMIT 1) AS tag_type FROM post_tags, user_posts WHERE post_tags.post_id IN (user_posts.post_id) GROUP BY post_tags.tag_name`, anthroveUserID).Scan(&queryUserFavorites) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, &otterError.NoDataFound{} @@ -302,47 +313,17 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov return nil, result.Error } - tagFrequency := make(map[struct { - name string - typeName string - }]int) - - for _, userFavorite := range userFavorites { - var post models.Post - result = db.WithContext(ctx).Preload("Tags", func(db *gorm.DB) *gorm.DB { - return db.Order("tag_type ASC") - }).First(&post, "id = ?", userFavorite.PostID) - - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - for _, tag := range post.Tags { - tagFrequency[struct { - name string - typeName string - }{name: tag.Name, typeName: string(tag.Type)}]++ - } - } - - var tagsWithFrequency []models.TagsWithFrequency - for data, frequency := range tagFrequency { - tagsWithFrequency = append(tagsWithFrequency, models.TagsWithFrequency{ - Frequency: int64(frequency), - Tags: models.Tag{ - Name: data.name, - Type: models.TagType(data.typeName), - }, - }) + var userFavoritesFrequency = make([]models.TagsWithFrequency, len(queryUserFavorites)) + for i, query := range queryUserFavorites { + userFavoritesFrequency[i].Frequency = query.count + userFavoritesFrequency[i].Tags.Name = query.tagName + userFavoritesFrequency[i].Tags.Type = query.tagType } log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, - "tag_amount": len(tagsWithFrequency), + "tag_amount": len(queryUserFavorites), }).Trace("database: got user tag node with relation to faved posts") - return tagsWithFrequency, nil + return userFavoritesFrequency, nil } diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index dd0932b..168829a 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -162,7 +162,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { userID: "e1", username: "marius", }, - wantErr: true, + wantErr: false, }, { name: "Test 5: no userID", @@ -270,30 +270,33 @@ func TestGetUserSourceBySourceID(t *testing.T) { validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) invalidUserID := models.AnthroveUserID("XXX") + validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: validSourceID, + }, + DisplayName: "e621", + Domain: "e621.net", + } + expectedResult := make(map[string]models.UserSource) expectedResult["e621"] = models.UserSource{ UserID: "e1", AccountUsername: "euser", Source: models.Source{ - DisplayName: "e621", - Domain: "e621.net", + DisplayName: source.DisplayName, + Domain: source.Domain, + Icon: source.Icon, }, } - source := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: expectedResult["e621"].Source.ID, - }, - DisplayName: expectedResult["e621"].Source.DisplayName, - Domain: expectedResult["e621"].Source.Domain, - } - err = CreateSource(ctx, gormDB, source) if err != nil { t.Fatal(err) } - err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, models.AnthroveSourceID(expectedResult["e621"].SourceID), expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } @@ -389,6 +392,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { wantErr: true, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := GetUserSourceBySourceID(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID) diff --git a/pkg/database/database.go b/pkg/database/database.go index f8be8ef..0060744 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -35,7 +35,7 @@ type OtterSpace interface { GetPostByAnthroveID(ctx context.Context, anthrovePostID models.AnthrovePostID) (*models.Post, error) // GetPostByURL retrieves a post by its source URL. - GetPostByURL(ctx context.Context, sourceUrl string) (*models.Post, error) + GetPostByURL(ctx context.Context, postURL string) (*models.Post, error) // GetPostBySourceID retrieves a post by its source ID. GetPostBySourceID(ctx context.Context, sourceID models.AnthroveSourceID) (*models.Post, error) From da4fda3597e39951b9de9e4a693b4d890a255b19 Mon Sep 17 00:00:00 2001 From: SoXX Date: Thu, 27 Jun 2024 21:37:29 +0200 Subject: [PATCH 104/124] refactor(postgres): a lot of things happened here Signed-off-by: SoXX --- internal/postgres/user.go | 37 +++++++++++++++++--------- internal/postgres/user_test.go | 8 +++--- pkg/database/postgres_test.go | 48 ++++++++++++++++++++-------------- 3 files changed, 57 insertions(+), 36 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index aa5d5a5..d7b365a 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -73,6 +73,10 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs return result.Error } + if result.RowsAffected == 0 { + return &otterError.NoDataWritten{} + } + log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, "source_id": sourceID, @@ -301,23 +305,32 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} } - result := db.WithContext(ctx).Raw( + rows, err := db.WithContext(ctx).Raw( `WITH user_posts AS ( - SELECT post_id FROM "UserFavorites" WHERE user_id = $1 - ) - SELECT post_tags.tag_name AS tag_name, count(*) AS count, (SELECT tag_type FROM "Tag" WHERE "Tag".name = post_tags.tag_name LIMIT 1) AS tag_type FROM post_tags, user_posts WHERE post_tags.post_id IN (user_posts.post_id) GROUP BY post_tags.tag_name`, anthroveUserID).Scan(&queryUserFavorites) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { + SELECT post_id FROM "UserFavorites" WHERE user_id = $1 + ) + SELECT post_tags.tag_name AS tag_name, count(*) AS count, (SELECT tag_type FROM "Tag" WHERE "Tag".name = post_tags.tag_name LIMIT 1) AS tag_type FROM post_tags, user_posts WHERE post_tags.post_id IN (user_posts.post_id) GROUP BY post_tags.tag_name ORDER BY tag_type DESC, tag_name DESC`, anthroveUserID).Rows() + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { return nil, &otterError.NoDataFound{} } - return nil, result.Error + return nil, err } - var userFavoritesFrequency = make([]models.TagsWithFrequency, len(queryUserFavorites)) - for i, query := range queryUserFavorites { - userFavoritesFrequency[i].Frequency = query.count - userFavoritesFrequency[i].Tags.Name = query.tagName - userFavoritesFrequency[i].Tags.Type = query.tagType + var userFavoritesFrequency = make([]models.TagsWithFrequency, 0) + defer rows.Close() + for rows.Next() { + var tagName string + var count int64 + var tagType string + rows.Scan(&tagName, &count, &tagType) + userFavoritesFrequency = append(userFavoritesFrequency, models.TagsWithFrequency{ + Frequency: count, + Tags: models.Tag{ + Name: tagName, + Type: models.TagType(tagType), + }, + }) } log.WithFields(log.Fields{ diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 168829a..ea9f2ad 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -870,15 +870,15 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { { Frequency: 1, Tags: models.Tag{ - Name: tags[1].Name, - Type: tags[1].Type, + Name: tags[2].Name, + Type: tags[2].Type, }, }, { Frequency: 1, Tags: models.Tag{ - Name: tags[2].Name, - Type: tags[2].Type, + Name: tags[1].Name, + Type: tags[1].Type, }, }, } diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index 4103607..bef6428 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -469,6 +469,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) ctx context.Context anthrovePostID models.AnthrovePostID sourceDomain models.AnthroveSourceDomain + postURl models.AnthrovePostURL } tests := []struct { name string @@ -481,6 +482,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) ctx: ctx, anthrovePostID: post.ID, sourceDomain: "e621.net", + postURl: "http://e621.net/post/eeasd", }, wantErr: false, }, @@ -490,6 +492,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) ctx: ctx, anthrovePostID: "123456", sourceDomain: "e621.net", + postURl: "", }, wantErr: true, }, @@ -499,6 +502,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) ctx: ctx, anthrovePostID: "1234", sourceDomain: "fa.banana", + postURl: "", }, wantErr: true, }, @@ -507,7 +511,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) args: args{ ctx: ctx, anthrovePostID: "696969", - sourceDomain: "hehe.funny.number", + postURl: "", }, wantErr: true, }} @@ -517,7 +521,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) db: gormDB, debug: true, } - if err := p.CreateReferenceBetweenPostAndSource(tt.args.ctx, tt.args.anthrovePostID, tt.args.sourceDomain); (err != nil) != tt.wantErr { + if err := p.CreateReferenceBetweenPostAndSource(tt.args.ctx, tt.args.anthrovePostID, tt.args.sourceDomain, tt.args.postURl); (err != nil) != tt.wantErr { t.Errorf("CreateReferenceBetweenPostAndSource() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -830,7 +834,7 @@ func Test_postgresqlConnection_GetPostByURL(t *testing.T) { t.Fatal("Could not create source", err) } - err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain)) + err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "https://e62asdwad.com/asdas") if err != nil { t.Fatal("Could not create source reference", err) } @@ -850,7 +854,7 @@ func Test_postgresqlConnection_GetPostByURL(t *testing.T) { name: "Test 1: Valid sourceUrl", args: args{ ctx: ctx, - sourceUrl: source.Domain, + sourceUrl: "https://e62asdwad.com/asdas", }, want: post, wantErr: false, @@ -931,7 +935,7 @@ func Test_postgresqlConnection_GetPostBySourceID(t *testing.T) { t.Fatal("Could not create source", err) } - err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain)) + err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "https://easd15aed.de/asd") if err != nil { t.Fatal("Could not create source reference", err) } @@ -1228,30 +1232,34 @@ func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) { validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) invalidUserID := models.AnthroveUserID("XXX") + validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + expectedResult := make(map[string]models.UserSource) + + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: validSourceID, + }, + DisplayName: "e621", + Domain: "e621.net", + } + expectedResult["e621"] = models.UserSource{ UserID: "e1", AccountUsername: "euser", Source: models.Source{ - DisplayName: "e621", - Domain: "e621.net", + DisplayName: source.DisplayName, + Domain: source.Domain, + Icon: source.Icon, }, } - source := &models.Source{ - BaseModel: models.BaseModel[models.AnthroveSourceID]{ - ID: expectedResult["e621"].Source.ID, - }, - DisplayName: expectedResult["e621"].Source.DisplayName, - Domain: expectedResult["e621"].Source.Domain, - } - err = postgres.CreateSource(ctx, gormDB, source) if err != nil { t.Fatal(err) } - err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, models.AnthroveSourceID(expectedResult["e621"].SourceID), expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) if err != nil { t.Fatal(err) } @@ -1605,15 +1613,15 @@ func Test_postgresqlConnection_GetUserTagWitRelationToFavedPosts(t *testing.T) { { Frequency: 1, Tags: models.Tag{ - Name: tags[1].Name, - Type: tags[1].Type, + Name: tags[2].Name, + Type: tags[2].Type, }, }, { Frequency: 1, Tags: models.Tag{ - Name: tags[2].Name, - Type: tags[2].Type, + Name: tags[1].Name, + Type: tags[1].Type, }, }, } From 56bb414f9df6786a44299b3982d73af52855520d Mon Sep 17 00:00:00 2001 From: SoXX Date: Thu, 27 Jun 2024 22:05:21 +0200 Subject: [PATCH 105/124] feat(PostReference): added the ability to add missing filed in db Signed-off-by: SoXX --- internal/postgres/post_test.go | 4 ++-- internal/postgres/relationships.go | 4 ++-- internal/postgres/user_test.go | 2 +- pkg/database/database.go | 12 +++++++++++- pkg/database/postgres.go | 4 ++-- pkg/database/postgres_test.go | 6 +++--- pkg/models/postReference.go | 10 +++++++--- 7 files changed, 28 insertions(+), 14 deletions(-) diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index 735f6b5..f679eaa 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -199,7 +199,7 @@ func TestGetPostBySourceURL(t *testing.T) { t.Fatal("Could not create source", err) } - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.org") + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.org", models.PostReferenceConfig{}) if err != nil { t.Fatal("Could not create source reference", err) } @@ -298,7 +298,7 @@ func TestGetPostBySourceID(t *testing.T) { t.Fatal("Could not create source", err) } - err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.otg") + err = CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "http://test.otg", models.PostReferenceConfig{}) if err != nil { t.Fatal("Could not create source reference", err) } diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index 5e8e8e6..bda9569 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -10,7 +10,7 @@ import ( "gorm.io/gorm" ) -func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error { +func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error { if anthrovePostID == "" { return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} } @@ -23,7 +23,7 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr return &otterError.EntityValidationFailed{Reason: "sourceDomain cannot be empty"} } - result := db.WithContext(ctx).Exec(`INSERT INTO "PostReference" (post_id, source_id, url) SELECT $1, source.id, $2 FROM "Source" AS source WHERE domain = $3;`, anthrovePostID, postURL, sourceDomain) + result := db.WithContext(ctx).Exec(`INSERT INTO "PostReference" (post_id, source_id, url, full_file_url, preview_file_url, sample_file_url, source_post_id) SELECT $1, source.id, $2, $4, $5, $6, $7 FROM "Source" AS source WHERE domain = $3;`, anthrovePostID, postURL, sourceDomain, config.FullFileURL, config.PreviewFileURL, config.SampleFileURL, config.SourcePostID) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index ea9f2ad..b146d52 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -162,7 +162,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { userID: "e1", username: "marius", }, - wantErr: false, + wantErr: true, }, { name: "Test 5: no userID", diff --git a/pkg/database/database.go b/pkg/database/database.go index 0060744..fc2e5ed 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -23,7 +23,7 @@ type OtterSpace interface { CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error // CreateReferenceBetweenPostAndSource links a post with a source. - CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error + CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error // CreateReferenceBetweenUserAndPost links a user with a post. CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error @@ -66,4 +66,14 @@ type OtterSpace interface { // GetSourceByDomain retrieves a source by its URL. GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) + /* + CreateTagAlias() + DeleteTagAlias() + UpdateTagWithAlias() + + CreateTagGroup() + DeleteTagGroup() + UpdateTagWithGroup() + + UpdateUserWithScrapeTimeInterval()*/ } diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 676d308..fb53ec9 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -88,8 +88,8 @@ func (p *postgresqlConnection) CreateTagAndReferenceToPost(ctx context.Context, return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag) } -func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error { - return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain, postURL) +func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error { + return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain, postURL, config) } func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index bef6428..c7d4996 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -521,7 +521,7 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) db: gormDB, debug: true, } - if err := p.CreateReferenceBetweenPostAndSource(tt.args.ctx, tt.args.anthrovePostID, tt.args.sourceDomain, tt.args.postURl); (err != nil) != tt.wantErr { + if err := p.CreateReferenceBetweenPostAndSource(tt.args.ctx, tt.args.anthrovePostID, tt.args.sourceDomain, tt.args.postURl, models.PostReferenceConfig{}); (err != nil) != tt.wantErr { t.Errorf("CreateReferenceBetweenPostAndSource() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -834,7 +834,7 @@ func Test_postgresqlConnection_GetPostByURL(t *testing.T) { t.Fatal("Could not create source", err) } - err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "https://e62asdwad.com/asdas") + err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "https://e62asdwad.com/asdas", models.PostReferenceConfig{}) if err != nil { t.Fatal("Could not create source reference", err) } @@ -935,7 +935,7 @@ func Test_postgresqlConnection_GetPostBySourceID(t *testing.T) { t.Fatal("Could not create source", err) } - err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "https://easd15aed.de/asd") + err = postgres.CreateReferenceBetweenPostAndSource(ctx, gormDB, post.ID, models.AnthroveSourceDomain(source.Domain), "https://easd15aed.de/asd", models.PostReferenceConfig{}) if err != nil { t.Fatal("Could not create source reference", err) } diff --git a/pkg/models/postReference.go b/pkg/models/postReference.go index 999e145..df1267c 100644 --- a/pkg/models/postReference.go +++ b/pkg/models/postReference.go @@ -1,9 +1,13 @@ package models type PostReference struct { - PostID string `gorm:"primaryKey"` - SourceID string `gorm:"primaryKey"` - URL string `gorm:"not null;unique"` + PostID string `gorm:"primaryKey"` + SourceID string `gorm:"primaryKey"` + URL string `gorm:"not null;unique"` + PostReferenceConfig +} + +type PostReferenceConfig struct { SourcePostID string FullFileURL string PreviewFileURL string From 51aa79e4c26ffc9908c6666adb961a5f1989221a Mon Sep 17 00:00:00 2001 From: SoXX Date: Thu, 27 Jun 2024 22:17:25 +0200 Subject: [PATCH 106/124] feat(newAPIs): initial structure for new api endpoints Signed-off-by: SoXX --- pkg/database/database.go | 19 +++++++++-------- pkg/database/postgres.go | 45 ++++++++++++++++++++++++++++++++++++++++ pkg/models/const.go | 6 ++++++ 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/pkg/database/database.go b/pkg/database/database.go index fc2e5ed..3f739b4 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -2,7 +2,6 @@ package database import ( "context" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" ) @@ -66,14 +65,16 @@ type OtterSpace interface { // GetSourceByDomain retrieves a source by its URL. GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) - /* - CreateTagAlias() - DeleteTagAlias() - UpdateTagWithAlias() - CreateTagGroup() - DeleteTagGroup() - UpdateTagWithGroup() + GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) + GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) + CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error + DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error - UpdateUserWithScrapeTimeInterval()*/ + GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) + GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) + CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) + DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error + + UpdateUserWithScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error } diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index fb53ec9..1770610 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -148,6 +148,51 @@ func (p *postgresqlConnection) GetSourceByDomain(ctx context.Context, sourceDoma return postgres.GetSourceByDomain(ctx, p.db, sourceDomain) } +func (p *postgresqlConnection) GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) UpdateUserWithScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error { + //TODO implement me + panic("implement me") +} + func (p *postgresqlConnection) migrateDatabase(dbPool *gorm.DB) error { dialect := "postgres" migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"} diff --git a/pkg/models/const.go b/pkg/models/const.go index f95434f..13646fe 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -1,10 +1,16 @@ package models +import "google.golang.org/genproto/googleapis/type/date" + type AnthroveUserID string type AnthrovePostID string type AnthroveSourceID string type AnthroveSourceDomain string type AnthrovePostURL string +type AnthroveTagGroupName string +type AnthroveTagAliasName string +type AnthroveTagID string +type AnthroveScrapeTimeInterval date.Date type Rating string type TagType string From 9c8a7c1e16fdf7ab6a887282ef93f8fc85ae4237 Mon Sep 17 00:00:00 2001 From: SoXX Date: Thu, 27 Jun 2024 22:18:35 +0200 Subject: [PATCH 107/124] fix(tests): remove timeout Signed-off-by: SoXX --- test/helper.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/helper.go b/test/helper.go index bb3f057..93a185e 100644 --- a/test/helper.go +++ b/test/helper.go @@ -3,17 +3,15 @@ package test import ( "context" "database/sql" - "net/url" - "strconv" - "strings" - "time" - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" migrate "github.com/rubenv/sql-migrate" postgrescontainer "github.com/testcontainers/testcontainers-go/modules/postgres" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" + "net/url" + "strconv" + "strings" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -34,9 +32,7 @@ func StartPostgresContainer(ctx context.Context) (*postgrescontainer.PostgresCon postgrescontainer.WithUsername(databaseUser), postgrescontainer.WithPassword(databasePassword), testcontainers.WithWaitStrategy( - wait.ForLog("database system is ready to accept connections"). - WithOccurrence(2).WithStartupTimeout(10*time.Second)), - ) + wait.ForLog("database system is ready to accept connections"))) if err != nil { return nil, nil, err } From 429f68899dd373d8531288a6ae4e091d233b2c86 Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 28 Jun 2024 10:43:55 +0200 Subject: [PATCH 108/124] feat(database): new fields Signed-off-by: SoXX --- internal/postgres/user.go | 13 ++++++-- pkg/database/database.go | 6 +++- .../migrations/001_inital_database.sql | 30 +++++++------------ pkg/database/postgres.go | 15 ++++++++++ pkg/models/const.go | 5 ++-- pkg/models/userSource.go | 19 +++++++----- 6 files changed, 54 insertions(+), 34 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index d7b365a..b5c0ee3 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -6,6 +6,7 @@ import ( otterError "git.dragse.it/anthrove/otter-space-sdk/pkg/error" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" + gonanoid "github.com/matoous/go-nanoid/v2" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) @@ -56,15 +57,21 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"} } + validationCode, err := gonanoid.New(25) + + if err != nil { + return err + } + result := db.WithContext(ctx).Exec(`WITH userObj AS ( INSERT INTO "User" (id) VALUES ($1) ON CONFLICT (id) DO NOTHING ) - INSERT INTO "UserSource" (user_id, source_id, account_username, account_id) - SELECT $2, source.id, $3, $4 + INSERT INTO "UserSource" (user_id, source_id, account_username, account_id, account_validate, account_validation_key) + SELECT $2, source.id, $3, $4, false, $5 FROM "Source" AS source - WHERE source.id = $5;`, anthroveUserID, anthroveUserID, accountUsername, accountId, sourceID) + WHERE source.id = $6;`, anthroveUserID, anthroveUserID, accountUsername, accountId, validationCode, sourceID) if result.Error != nil { if errors.Is(result.Error, gorm.ErrDuplicatedKey) { diff --git a/pkg/database/database.go b/pkg/database/database.go index 3f739b4..691bd98 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -2,6 +2,7 @@ package database import ( "context" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" ) @@ -76,5 +77,8 @@ type OtterSpace interface { CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error - UpdateUserWithScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error + UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error + UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error + + UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error } diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index d580538..03932c9 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -27,7 +27,7 @@ CREATE TABLE "Post" CREATE TABLE "Source" ( - id CHAR(25) PRIMARY KEY, + id CHAR(25) PRIMARY KEY, display_name TEXT NULL, icon TEXT NULL, domain TEXT NOT NULL UNIQUE, @@ -89,11 +89,14 @@ CREATE TABLE "UserFavorites" CREATE TABLE "UserSource" ( - user_id TEXT REFERENCES "User" (id), - source_id TEXT REFERENCES "Source" (id), - scrape_time_interval TEXT, - account_username TEXT, - account_id TEXT, + user_id TEXT REFERENCES "User" (id), + source_id TEXT REFERENCES "Source" (id), + scrape_time_interval INT, + account_username TEXT, + account_id TEXT, + last_scrape_time TIMESTAMP, + account_validate BOOL DEFAULT FALSE, + account_validation_key CHAR(25), PRIMARY KEY (user_id, source_id), UNIQUE (source_id, account_username, account_id) ); @@ -103,17 +106,4 @@ CREATE TABLE "post_tags" post_id TEXT REFERENCES "Post" (id), tag_name TEXT REFERENCES "Tag" (name), PRIMARY KEY (post_id, tag_name) -); - --- +migrate Down -DROP TYPE Rating; -DROP TYPE TagType; -DROP TABLE Post; -DROP TABLE Source; -DROP TABLE Tag; -DROP TABLE User; -DROP TABLE PostReference; -DROP TABLE TagAlias; -DROP TABLE TagGroup; -DROP TABLE UserFavorites; -DROP TABLE UserSource; \ No newline at end of file +); \ No newline at end of file diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 1770610..fe078dc 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -193,6 +193,21 @@ func (p *postgresqlConnection) UpdateUserWithScrapeTimeInterval(ctx context.Cont panic("implement me") } +func (p *postgresqlConnection) UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error { + //TODO implement me + panic("implement me") +} + func (p *postgresqlConnection) migrateDatabase(dbPool *gorm.DB) error { dialect := "postgres" migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"} diff --git a/pkg/models/const.go b/pkg/models/const.go index 13646fe..0e24228 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -1,7 +1,5 @@ package models -import "google.golang.org/genproto/googleapis/type/date" - type AnthroveUserID string type AnthrovePostID string type AnthroveSourceID string @@ -10,7 +8,8 @@ type AnthrovePostURL string type AnthroveTagGroupName string type AnthroveTagAliasName string type AnthroveTagID string -type AnthroveScrapeTimeInterval date.Date +type AnthroveScrapeTimeInterval int +type AnthroveUserLastScrapeTime int type Rating string type TagType string diff --git a/pkg/models/userSource.go b/pkg/models/userSource.go index 59788a1..8ac124e 100644 --- a/pkg/models/userSource.go +++ b/pkg/models/userSource.go @@ -1,13 +1,18 @@ package models +import "time" + type UserSource struct { - User User `gorm:"foreignKey:ID;references:UserID"` - UserID string `gorm:"primaryKey"` - Source Source `gorm:"foreignKey:ID;references:SourceID"` - SourceID string `gorm:"primaryKey"` - ScrapeTimeInterval string - AccountUsername string - AccountID string + User User `gorm:"foreignKey:ID;references:UserID"` + UserID string `gorm:"primaryKey"` + Source Source `gorm:"foreignKey:ID;references:SourceID"` + SourceID string `gorm:"primaryKey"` + ScrapeTimeInterval string + AccountUsername string + AccountID string + LastScrapeTime time.Time + AccountValidate bool + AccountValidationKey string } func (UserSource) TableName() string { From bc8b5bb4a7a91517b9d505c8136eb06b2f346ab8 Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 28 Jun 2024 10:54:42 +0200 Subject: [PATCH 109/124] refactor: reorganized code structure Signed-off-by: SoXX --- pkg/database/database.go | 72 ++------------------ pkg/database/post.go | 28 ++++++++ pkg/database/{ => postgres}/postgres.go | 5 +- pkg/database/{ => postgres}/postgres_test.go | 5 +- pkg/database/source.go | 19 ++++++ pkg/database/tag.go | 12 ++++ pkg/database/tagalias.go | 14 ++++ pkg/database/taggroup.go | 14 ++++ pkg/database/user.go | 29 ++++++++ pkg/database/usersource.go | 14 ++++ 10 files changed, 141 insertions(+), 71 deletions(-) create mode 100644 pkg/database/post.go rename pkg/database/{ => postgres}/postgres.go (98%) rename pkg/database/{ => postgres}/postgres_test.go (99%) create mode 100644 pkg/database/source.go create mode 100644 pkg/database/tag.go create mode 100644 pkg/database/tagalias.go create mode 100644 pkg/database/taggroup.go create mode 100644 pkg/database/user.go create mode 100644 pkg/database/usersource.go diff --git a/pkg/database/database.go b/pkg/database/database.go index 691bd98..c721eb4 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -10,75 +10,13 @@ type OtterSpace interface { // Connect establishes a connection to the database. Connect(ctx context.Context, config models.DatabaseConfig) error - // CreateUserWithRelationToSource adds a user with a relation to a source. - CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error + User - // CreateSource adds a new source to the database. - CreateSource(ctx context.Context, anthroveSource *models.Source) error + Source - // CreatePost adds a new post to the database. - CreatePost(ctx context.Context, anthrovePost *models.Post) error + TagAlias - // CreateTagAndReferenceToPost adds a tag with a relation to a post. - CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error + TagGroup - // CreateReferenceBetweenPostAndSource links a post with a source. - CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error - - // CreateReferenceBetweenUserAndPost links a user with a post. - CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error - - // CheckReferenceBetweenUserAndPost checks if a user-post link exists. - CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID models.AnthrovePostID) (bool, error) - - // GetPostByAnthroveID retrieves a post by its Anthrove ID. - GetPostByAnthroveID(ctx context.Context, anthrovePostID models.AnthrovePostID) (*models.Post, error) - - // GetPostByURL retrieves a post by its source URL. - GetPostByURL(ctx context.Context, postURL string) (*models.Post, error) - - // GetPostBySourceID retrieves a post by its source ID. - GetPostBySourceID(ctx context.Context, sourceID models.AnthroveSourceID) (*models.Post, error) - - // GetUserFavoritesCount retrieves the count of a user's favorites. - GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) - - // GetUserSourceLinks retrieves the source links of a user. - GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) - - // GetUserSourceBySourceID retrieves a specified source link of a user. - GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) - - // GetAllAnthroveUserIDs retrieves all Anthrove user IDs. - GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) - - // GetUserFavoriteWithPagination retrieves a user's favorite posts with pagination. - GetUserFavoriteWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) - - // GetUserTagWitRelationToFavedPosts retrieves a user's tags through their favorited posts. - GetUserTagWitRelationToFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) - - // GetAllTags retrieves all tags. - GetAllTags(ctx context.Context) ([]models.Tag, error) - - // GetAllSources retrieves all sources. - GetAllSources(ctx context.Context) ([]models.Source, error) - - // GetSourceByDomain retrieves a source by its URL. - GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) - - GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) - GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) - CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error - DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error - - GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) - GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) - CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) - DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error - - UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error - UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error - - UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error + UserSource } diff --git a/pkg/database/post.go b/pkg/database/post.go new file mode 100644 index 0000000..7edb191 --- /dev/null +++ b/pkg/database/post.go @@ -0,0 +1,28 @@ +package database + +import ( + "context" + + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" +) + +type Post interface { + + // CreatePost adds a new post to the database. + CreatePost(ctx context.Context, anthrovePost *models.Post) error + + // GetPostByAnthroveID retrieves a post by its Anthrove ID. + GetPostByAnthroveID(ctx context.Context, anthrovePostID models.AnthrovePostID) (*models.Post, error) + + // GetPostByURL retrieves a post by its source URL. + GetPostByURL(ctx context.Context, postURL string) (*models.Post, error) + + // GetPostBySourceID retrieves a post by its source ID. + GetPostBySourceID(ctx context.Context, sourceID models.AnthroveSourceID) (*models.Post, error) + + // CreateTagAndReferenceToPost adds a tag with a relation to a post. + CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error + + // CreateReferenceBetweenPostAndSource links a post with a source. + CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres/postgres.go similarity index 98% rename from pkg/database/postgres.go rename to pkg/database/postgres/postgres.go index fe078dc..714438a 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres/postgres.go @@ -1,4 +1,4 @@ -package database +package postgres import ( "context" @@ -9,6 +9,7 @@ import ( "time" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" + "git.dragse.it/anthrove/otter-space-sdk/pkg/database" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" _ "github.com/lib/pq" migrate "github.com/rubenv/sql-migrate" @@ -26,7 +27,7 @@ type postgresqlConnection struct { debug bool } -func NewPostgresqlConnection() OtterSpace { +func NewPostgresqlConnection() database.OtterSpace { return &postgresqlConnection{ db: nil, } diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres/postgres_test.go similarity index 99% rename from pkg/database/postgres_test.go rename to pkg/database/postgres/postgres_test.go index c7d4996..721752a 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres/postgres_test.go @@ -1,4 +1,4 @@ -package database +package postgres import ( "context" @@ -7,6 +7,7 @@ import ( "testing" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" + "git.dragse.it/anthrove/otter-space-sdk/pkg/database" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" @@ -16,7 +17,7 @@ func TestNewPostgresqlConnection(t *testing.T) { // Test tests := []struct { name string - want OtterSpace + want database.OtterSpace }{ { name: "Test 1: Create new postgresql connection", diff --git a/pkg/database/source.go b/pkg/database/source.go new file mode 100644 index 0000000..776c1d1 --- /dev/null +++ b/pkg/database/source.go @@ -0,0 +1,19 @@ +package database + +import ( + "context" + + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" +) + +type Source interface { + + // CreateSource adds a new source to the database. + CreateSource(ctx context.Context, anthroveSource *models.Source) error + + // GetAllSources retrieves all sources. + GetAllSources(ctx context.Context) ([]models.Source, error) + + // GetSourceByDomain retrieves a source by its URL. + GetSourceByDomain(ctx context.Context, sourceDomain models.AnthroveSourceDomain) (*models.Source, error) +} diff --git a/pkg/database/tag.go b/pkg/database/tag.go new file mode 100644 index 0000000..eb0f4a5 --- /dev/null +++ b/pkg/database/tag.go @@ -0,0 +1,12 @@ +package database + +import ( + "context" + + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" +) + +type Tag interface { + // GetAllTags retrieves all tags. + GetAllTags(ctx context.Context) ([]models.Tag, error) +} diff --git a/pkg/database/tagalias.go b/pkg/database/tagalias.go new file mode 100644 index 0000000..ef5f2e5 --- /dev/null +++ b/pkg/database/tagalias.go @@ -0,0 +1,14 @@ +package database + +import ( + "context" + + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" +) + +type TagAlias interface { + GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) + GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) + CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error + DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error +} diff --git a/pkg/database/taggroup.go b/pkg/database/taggroup.go new file mode 100644 index 0000000..db3918a --- /dev/null +++ b/pkg/database/taggroup.go @@ -0,0 +1,14 @@ +package database + +import ( + "context" + + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" +) + +type TagGroup interface { + GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) + GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) + CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) + DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error +} diff --git a/pkg/database/user.go b/pkg/database/user.go new file mode 100644 index 0000000..1b72e61 --- /dev/null +++ b/pkg/database/user.go @@ -0,0 +1,29 @@ +package database + +import ( + "context" + + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" +) + +type User interface { + // GetAllAnthroveUserIDs retrieves all Anthrove user IDs. + GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) + + // CreateUserWithRelationToSource adds a user with a relation to a source. + CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error + // CreateReferenceBetweenUserAndPost links a user with a post. + CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error + // CheckReferenceBetweenUserAndPost checks if a user-post link exists. + CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID models.AnthrovePostID) (bool, error) + // GetUserFavoritesCount retrieves the count of a user's favorites. + GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) + // GetUserSourceLinks retrieves the source links of a user. + GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) + // GetUserSourceBySourceID retrieves a specified source link of a user. + GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) + // GetUserFavoriteWithPagination retrieves a user's favorite posts with pagination. + GetUserFavoriteWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) + // GetUserTagWitRelationToFavedPosts retrieves a user's tags through their favorited posts. + GetUserTagWitRelationToFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) +} diff --git a/pkg/database/usersource.go b/pkg/database/usersource.go new file mode 100644 index 0000000..1f30a48 --- /dev/null +++ b/pkg/database/usersource.go @@ -0,0 +1,14 @@ +package database + +import ( + "context" + + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" +) + +type UserSource interface { + UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error + UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error + + UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error +} From 5de00e6861a438ef8a116b72f3ae7fb2f740120b Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 28 Jun 2024 10:58:07 +0200 Subject: [PATCH 110/124] refactor: reorganized code structure Signed-off-by: SoXX --- pkg/database/database.go | 5 ----- pkg/database/user.go | 5 +++++ pkg/database/usersource.go | 14 -------------- 3 files changed, 5 insertions(+), 19 deletions(-) delete mode 100644 pkg/database/usersource.go diff --git a/pkg/database/database.go b/pkg/database/database.go index c721eb4..0cd0777 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -11,12 +11,7 @@ type OtterSpace interface { Connect(ctx context.Context, config models.DatabaseConfig) error User - Source - TagAlias - TagGroup - - UserSource } diff --git a/pkg/database/user.go b/pkg/database/user.go index 1b72e61..d90ca51 100644 --- a/pkg/database/user.go +++ b/pkg/database/user.go @@ -26,4 +26,9 @@ type User interface { GetUserFavoriteWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) // GetUserTagWitRelationToFavedPosts retrieves a user's tags through their favorited posts. GetUserTagWitRelationToFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) + + UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error + UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error + + UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error } diff --git a/pkg/database/usersource.go b/pkg/database/usersource.go deleted file mode 100644 index 1f30a48..0000000 --- a/pkg/database/usersource.go +++ /dev/null @@ -1,14 +0,0 @@ -package database - -import ( - "context" - - "git.dragse.it/anthrove/otter-space-sdk/pkg/models" -) - -type UserSource interface { - UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error - UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error - - UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error -} From 4a0b7d71a9a5ccbfb88af29ad161c988d58cb429 Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 28 Jun 2024 12:15:51 +0200 Subject: [PATCH 111/124] refactor: reorganized code structure Signed-off-by: SoXX --- internal/postgres/relationships_test.go | 8 ++--- internal/postgres/user.go | 41 +++++-------------------- internal/postgres/user_test.go | 18 +++++------ pkg/database/database.go | 7 +++++ pkg/database/postgres/postgres.go | 14 ++++----- pkg/database/postgres/postgres_test.go | 28 ++++++++--------- pkg/database/tagalias.go | 7 +++-- pkg/database/taggroup.go | 7 +++-- pkg/database/user.go | 36 +++++++++++++--------- test/helper.go | 17 +++++----- 10 files changed, 89 insertions(+), 94 deletions(-) diff --git a/internal/postgres/relationships_test.go b/internal/postgres/relationships_test.go index dec686d..dd67e2a 100644 --- a/internal/postgres/relationships_test.go +++ b/internal/postgres/relationships_test.go @@ -133,11 +133,11 @@ func TestCheckUserToPostLink(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) if (err != nil) != tt.wantErr { - t.Errorf("CheckReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { - t.Errorf("CheckReferenceBetweenUserAndPost() got = %v, want %v", got, tt.want) + t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want) } }) } @@ -266,11 +266,11 @@ func TestCheckUserToPostLinkWithNoData(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.anthrovePostID) if (err != nil) != tt.wantErr { - t.Errorf("CheckReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { - t.Errorf("CheckReferenceBetweenUserAndPost() got = %v, want %v", got, tt.want) + t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want) } }) } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index b5c0ee3..8e8b2d7 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -169,9 +169,8 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models. return userSourceMap, nil } -func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) { - var userSources []models.UserSource - userSourceMap := make(map[string]models.UserSource) +func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error) { + var userSource *models.UserSource if anthroveUserID == "" { return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} @@ -189,7 +188,7 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo return nil, &otterError.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) + result := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("id = ?", sourceID)).Where("user_id = ?", string(anthroveUserID)).First(userSource) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, &otterError.NoDataFound{} @@ -197,38 +196,16 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo return nil, result.Error } - for _, userSource := range userSources { - var source models.Source - result = db.WithContext(ctx).Model(&models.Source{}).Where("id = ?", userSource.SourceID).First(&source) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return nil, &otterError.NoDataFound{} - } - return nil, result.Error - } - - userSourceMap[source.DisplayName] = models.UserSource{ - UserID: userSource.AccountID, - AccountUsername: userSource.AccountUsername, - Source: models.Source{ - DisplayName: source.DisplayName, - Domain: source.Domain, - Icon: source.Icon, - }, - } - } - log.WithFields(log.Fields{ "anthrove_user_id": anthroveUserID, "source_id": sourceID, }).Trace("database: got specified user source link") - return userSourceMap, nil + return userSource, nil } -func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveUserID, error) { +func GetAllUsers(ctx context.Context, db *gorm.DB) ([]models.User, error) { var users []models.User - var userIDs []models.AnthroveUserID result := db.WithContext(ctx).Model(&models.User{}).Find(&users) if result.Error != nil { @@ -238,15 +215,11 @@ func GetAllAnthroveUserIDs(ctx context.Context, db *gorm.DB) ([]models.AnthroveU return nil, result.Error } - for _, user := range users { - userIDs = append(userIDs, user.ID) - } - log.WithFields(log.Fields{ - "anthrove_user_id_count": len(userIDs), + "anthrove_user_id_count": len(users), }).Trace("database: got all anthrove user IDs") - return userIDs, nil + return users, nil } func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index b146d52..c4efa00 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -244,13 +244,13 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetAllAnthroveUserIDs(tt.args.ctx, tt.args.db) + got, err := GetAllUsers(tt.args.ctx, tt.args.db) if (err != nil) != tt.wantErr { - t.Errorf("GetAllAnthroveUserIDs() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetAllUsers() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAllAnthroveUserIDs() got = %v, want %v", got, tt.want) + t.Errorf("GetAllUsers() got = %v, want %v", got, tt.want) } }) } @@ -558,11 +558,11 @@ func TestGetUserFavoriteNodeWithPagination(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := GetUserFavoriteWithPagination(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) if (err != nil) != tt.wantErr { - t.Errorf("GetUserFavoriteWithPagination() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetAllUserFavoritesWithPagination() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetUserFavoriteWithPagination() got = %v, want %v", got, tt.want) + t.Errorf("GetAllUserFavoritesWithPagination() got = %v, want %v", got, tt.want) } }) } @@ -798,11 +798,11 @@ func TestGetUserSourceLinks(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := GetUserSourceLinks(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) if (err != nil) != tt.wantErr { - t.Errorf("GetUserSourceLinks() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetAllUserSources() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetUserSourceLinks() got = %v, want %v", got, tt.want) + t.Errorf("GetAllUserSources() got = %v, want %v", got, tt.want) } }) } @@ -930,11 +930,11 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := GetUserTagWitRelationToFavedPosts(tt.args.ctx, tt.args.db, tt.args.anthroveUserID) if (err != nil) != tt.wantErr { - t.Errorf("GetUserTagWitRelationToFavedPosts() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetAllTagsFromUser() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetUserTagWitRelationToFavedPosts() got = %v, want %v", got, tt.want) + t.Errorf("GetAllTagsFromUser() got = %v, want %v", got, tt.want) } }) } diff --git a/pkg/database/database.go b/pkg/database/database.go index 0cd0777..7b1aef2 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -10,8 +10,15 @@ type OtterSpace interface { // Connect establishes a connection to the database. Connect(ctx context.Context, config models.DatabaseConfig) error + // User contains all function that are needed to manage the AnthroveUser User + + // Source contains all function that are needed to manage the Source Source + + // TagAlias contains all function that are needed to manage the TagAlias TagAlias + + // TagGroup contains all function that are needed to manage the TagGroup TagGroup } diff --git a/pkg/database/postgres/postgres.go b/pkg/database/postgres/postgres.go index 714438a..da69ba8 100644 --- a/pkg/database/postgres/postgres.go +++ b/pkg/database/postgres/postgres.go @@ -97,7 +97,7 @@ func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Con return postgres.CreateReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID) } -func (p *postgresqlConnection) CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { +func (p *postgresqlConnection) CheckIfUserHasPostAsFavorite(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) (bool, error) { return postgres.CheckReferenceBetweenUserAndPost(ctx, p.db, anthroveUserID, anthrovePostID) } @@ -117,23 +117,23 @@ func (p *postgresqlConnection) GetUserFavoritesCount(ctx context.Context, anthro return postgres.GetUserFavoritesCount(ctx, p.db, anthroveUserID) } -func (p *postgresqlConnection) GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) { +func (p *postgresqlConnection) GetAllUserSources(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) { return postgres.GetUserSourceLinks(ctx, p.db, anthroveUserID) } -func (p *postgresqlConnection) GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) { +func (p *postgresqlConnection) GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error) { return postgres.GetUserSourceBySourceID(ctx, p.db, anthroveUserID, sourceID) } -func (p *postgresqlConnection) GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) { - return postgres.GetAllAnthroveUserIDs(ctx, p.db) +func (p *postgresqlConnection) GetAllUser(ctx context.Context) ([]models.User, error) { + return postgres.GetAllUsers(ctx, p.db) } -func (p *postgresqlConnection) GetUserFavoriteWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { +func (p *postgresqlConnection) GetAllUserFavoritesWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) { return postgres.GetUserFavoriteWithPagination(ctx, p.db, anthroveUserID, skip, limit) } -func (p *postgresqlConnection) GetUserTagWitRelationToFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { +func (p *postgresqlConnection) GetAllTagsFromUser(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { return postgres.GetUserTagWitRelationToFavedPosts(ctx, p.db, anthroveUserID) } diff --git a/pkg/database/postgres/postgres_test.go b/pkg/database/postgres/postgres_test.go index 721752a..bf7159f 100644 --- a/pkg/database/postgres/postgres_test.go +++ b/pkg/database/postgres/postgres_test.go @@ -714,13 +714,13 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { db: gormDB, debug: true, } - got, err := p.CheckReferenceBetweenUserAndPost(tt.args.ctx, tt.args.anthroveUserID, tt.args.anthrovePostID) + got, err := p.CheckIfUserFavouritedPost(tt.args.ctx, tt.args.anthroveUserID, tt.args.anthrovePostID) if (err != nil) != tt.wantErr { - t.Errorf("CheckReferenceBetweenUserAndPost() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { - t.Errorf("CheckReferenceBetweenUserAndPost() got = %v, want %v", got, tt.want) + t.Errorf("CheckIfUserHasPostAsFavorite() got = %v, want %v", got, tt.want) } }) } @@ -1207,13 +1207,13 @@ func Test_postgresqlConnection_GetUserSourceLinks(t *testing.T) { db: gormDB, debug: true, } - got, err := p.GetUserSourceLinks(tt.args.ctx, tt.args.anthroveUserID) + got, err := p.GetAllUserSources(tt.args.ctx, tt.args.anthroveUserID) if (err != nil) != tt.wantErr { - t.Errorf("GetUserSourceLinks() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetAllUserSources() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetUserSourceLinks() got = %v, want %v", got, tt.want) + t.Errorf("GetAllUserSources() got = %v, want %v", got, tt.want) } }) } @@ -1405,11 +1405,11 @@ func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) { } got, err := p.GetAllAnthroveUserIDs(tt.args.ctx) if (err != nil) != tt.wantErr { - t.Errorf("GetAllAnthroveUserIDs() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetAllUsers() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAllAnthroveUserIDs() got = %v, want %v", got, tt.want) + t.Errorf("GetAllUsers() got = %v, want %v", got, tt.want) } }) } @@ -1540,13 +1540,13 @@ func Test_postgresqlConnection_GetUserFavoriteWithPagination(t *testing.T) { db: gormDB, debug: true, } - got, err := p.GetUserFavoriteWithPagination(tt.args.ctx, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) + got, err := p.GetAllUserFavoritesWithPagination(tt.args.ctx, tt.args.anthroveUserID, tt.args.skip, tt.args.limit) if (err != nil) != tt.wantErr { - t.Errorf("GetUserFavoriteWithPagination() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetAllUserFavoritesWithPagination() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetUserFavoriteWithPagination() got = %v, want %v", got, tt.want) + t.Errorf("GetAllUserFavoritesWithPagination() got = %v, want %v", got, tt.want) } }) } @@ -1654,13 +1654,13 @@ func Test_postgresqlConnection_GetUserTagWitRelationToFavedPosts(t *testing.T) { db: gormDB, debug: true, } - got, err := p.GetUserTagWitRelationToFavedPosts(tt.args.ctx, tt.args.anthroveUserID) + got, err := p.GetAllTagsFromUser(tt.args.ctx, tt.args.anthroveUserID) if (err != nil) != tt.wantErr { - t.Errorf("GetUserTagWitRelationToFavedPosts() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetAllTagsFromUser() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetUserTagWitRelationToFavedPosts() got = %v, want %v", got, tt.want) + t.Errorf("GetAllTagsFromUser() got = %v, want %v", got, tt.want) } }) } diff --git a/pkg/database/tagalias.go b/pkg/database/tagalias.go index ef5f2e5..30171d4 100644 --- a/pkg/database/tagalias.go +++ b/pkg/database/tagalias.go @@ -7,8 +7,11 @@ import ( ) type TagAlias interface { - GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) - GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error + + GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) + + GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) + DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error } diff --git a/pkg/database/taggroup.go b/pkg/database/taggroup.go index db3918a..594cd1e 100644 --- a/pkg/database/taggroup.go +++ b/pkg/database/taggroup.go @@ -7,8 +7,11 @@ import ( ) type TagGroup interface { - GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) - GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) + + GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) + + GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) + DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error } diff --git a/pkg/database/user.go b/pkg/database/user.go index d90ca51..e7be12e 100644 --- a/pkg/database/user.go +++ b/pkg/database/user.go @@ -7,28 +7,36 @@ import ( ) type User interface { - // GetAllAnthroveUserIDs retrieves all Anthrove user IDs. - GetAllAnthroveUserIDs(ctx context.Context) ([]models.AnthroveUserID, error) // CreateUserWithRelationToSource adds a user with a relation to a source. CreateUserWithRelationToSource(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, accountId string, accountUsername string) error + // CreateReferenceBetweenUserAndPost links a user with a post. CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error - // CheckReferenceBetweenUserAndPost checks if a user-post link exists. - CheckReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID models.AnthrovePostID) (bool, error) - // GetUserFavoritesCount retrieves the count of a user's favorites. - GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) - // GetUserSourceLinks retrieves the source links of a user. - GetUserSourceLinks(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) - // GetUserSourceBySourceID retrieves a specified source link of a user. - GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (map[string]models.UserSource, error) - // GetUserFavoriteWithPagination retrieves a user's favorite posts with pagination. - GetUserFavoriteWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) - // GetUserTagWitRelationToFavedPosts retrieves a user's tags through their favorited posts. - GetUserTagWitRelationToFavedPosts(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error + UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error + + GetAllUser(ctx context.Context) ([]models.User, error) + + // GetUserFavoritesCount retrieves the count of a user's favorites. + GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) + + // GetAllUserSources retrieves the source links of a user. + GetAllUserSources(ctx context.Context, anthroveUserID models.AnthroveUserID) (map[string]models.UserSource, error) + + // GetUserSourceBySourceID retrieves a specified source link of a user. + GetUserSourceBySourceID(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error) + + // GetAllUserFavoritesWithPagination retrieves a user's favorite posts with pagination. + GetAllUserFavoritesWithPagination(ctx context.Context, anthroveUserID models.AnthroveUserID, skip int, limit int) (*models.FavoriteList, error) + + // GetAllTagsFromUser retrieves a user's tags through their favorite posts. + GetAllTagsFromUser(ctx context.Context, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) + + // CheckIfUserHasPostAsFavorite checks if a user-post link exists. + CheckIfUserHasPostAsFavorite(ctx context.Context, anthroveUserID models.AnthroveUserID, sourcePostID models.AnthrovePostID) (bool, error) } diff --git a/test/helper.go b/test/helper.go index 93a185e..ce571d2 100644 --- a/test/helper.go +++ b/test/helper.go @@ -3,15 +3,16 @@ package test import ( "context" "database/sql" + "net/url" + "strconv" + "strings" + "git.dragse.it/anthrove/otter-space-sdk/pkg/models" migrate "github.com/rubenv/sql-migrate" postgrescontainer "github.com/testcontainers/testcontainers-go/modules/postgres" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" - "net/url" - "strconv" - "strings" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -88,12 +89,12 @@ func DatabaseModesFromConnectionString(ctx context.Context, pgContainer *postgre return nil, err } - url, err := url.Parse(connectionString) + connectionStringUrl, err := url.Parse(connectionString) if err != nil { return nil, err } - split := strings.Split(url.Host, ":") + split := strings.Split(connectionStringUrl.Host, ":") host := split[0] port, err := strconv.Atoi(split[1]) @@ -101,10 +102,10 @@ func DatabaseModesFromConnectionString(ctx context.Context, pgContainer *postgre return nil, err } - database := strings.TrimPrefix(url.Path, "/") + database := strings.TrimPrefix(connectionStringUrl.Path, "/") - username := url.User.Username() - password, _ := url.User.Password() + username := connectionStringUrl.User.Username() + password, _ := connectionStringUrl.User.Password() return &models.DatabaseConfig{ Endpoint: host, From b5437ecc6298c3da5d807f3082ac784d8000ddc0 Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 28 Jun 2024 14:16:28 +0200 Subject: [PATCH 112/124] tests: fixed tests Signed-off-by: SoXX --- internal/postgres/tag_test.go | 2 +- internal/postgres/user.go | 6 +- internal/postgres/user_test.go | 69 +++++++++++++--- pkg/database/database.go | 3 + pkg/database/post.go | 8 +- pkg/database/{postgres => }/postgres.go | 11 ++- pkg/database/{postgres => }/postgres_test.go | 87 +++++++++++++++----- pkg/database/user.go | 2 +- pkg/models/postReference_test.go | 16 ++-- test/helper.go | 7 +- 10 files changed, 155 insertions(+), 56 deletions(-) rename pkg/database/{postgres => }/postgres.go (93%) rename pkg/database/{postgres => }/postgres_test.go (95%) diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index 045cd96..3f22c76 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -94,7 +94,7 @@ func TestCreateTagNodeWitRelation(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := CreateTagAndReferenceToPost(tt.args.ctx, tt.args.db, tt.args.PostID, tt.args.tag); (err != nil) != tt.wantErr { - t.Errorf("CreateTagAndReferenceToPost() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("CreatePostWithReferenceToTagAnd() error = %v, wantErr %v", err, tt.wantErr) } }) } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 8e8b2d7..c0a2543 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -170,7 +170,7 @@ func GetUserSourceLinks(ctx context.Context, db *gorm.DB, anthroveUserID models. } func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID) (*models.UserSource, error) { - var userSource *models.UserSource + var userSource models.UserSource if anthroveUserID == "" { return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} @@ -188,7 +188,7 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo return nil, &otterError.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(userSource) + result := db.WithContext(ctx).Model(&models.UserSource{}).InnerJoins("Source", db.Where("id = ?", sourceID)).Where("user_id = ?", string(anthroveUserID)).First(&userSource) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, &otterError.NoDataFound{} @@ -201,7 +201,7 @@ func GetUserSourceBySourceID(ctx context.Context, db *gorm.DB, anthroveUserID mo "source_id": sourceID, }).Trace("database: got specified user source link") - return userSource, nil + return &userSource, nil } func GetAllUsers(ctx context.Context, db *gorm.DB) ([]models.User, error) { diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index c4efa00..8dfa13a 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -198,7 +198,7 @@ func TestCreateUserNodeWithSourceRelation(t *testing.T) { } } -func TestGetAllAnthroveUserIDs(t *testing.T) { +func TestGetAllUsers(t *testing.T) { // Setup trow away container ctx := context.Background() container, gormDB, err := test.StartPostgresContainer(ctx) @@ -212,10 +212,20 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { validUserID02 := models.AnthroveUserID(fmt.Sprintf("%025s", "User2")) validUserID03 := models.AnthroveUserID(fmt.Sprintf("%025s", "User3")) - users := []models.AnthroveUserID{validUserID01, validUserID02, validUserID03} + users := []models.User{ + { + BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID01}, + }, + { + BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID02}, + }, + { + BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID03}, + }, + } for _, user := range users { - err = CreateUser(ctx, gormDB, user) + err = CreateUser(ctx, gormDB, user.ID) if err != nil { t.Fatal(err) } @@ -229,7 +239,7 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { tests := []struct { name string args args - want []models.AnthroveUserID + want []models.User wantErr bool }{ { @@ -249,7 +259,7 @@ func TestGetAllAnthroveUserIDs(t *testing.T) { t.Errorf("GetAllUsers() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(got, tt.want) { + if !checkUser(got, tt.want) { t.Errorf("GetAllUsers() got = %v, want %v", got, tt.want) } }) @@ -278,13 +288,14 @@ func TestGetUserSourceBySourceID(t *testing.T) { }, DisplayName: "e621", Domain: "e621.net", + Icon: "https://e621.icon", } - expectedResult := make(map[string]models.UserSource) - expectedResult["e621"] = models.UserSource{ - UserID: "e1", + expectedResult := &models.UserSource{ + UserID: string(validUserID), AccountUsername: "euser", Source: models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: source.ID}, DisplayName: source.DisplayName, Domain: source.Domain, Icon: source.Icon, @@ -296,7 +307,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { t.Fatal(err) } - err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult.UserID, expectedResult.AccountUsername) if err != nil { t.Fatal(err) } @@ -311,7 +322,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { tests := []struct { name string args args - want map[string]models.UserSource + want *models.UserSource wantErr bool }{ { @@ -400,7 +411,7 @@ func TestGetUserSourceBySourceID(t *testing.T) { t.Errorf("GetUserSourceBySourceID() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(got, tt.want) { + if !checkUserSource(got, tt.want) { t.Errorf("GetUserSourceBySourceID() got = %v, want %v", got, tt.want) } }) @@ -939,3 +950,39 @@ func TestGetUserTagNodeWitRelationToFavedPosts(t *testing.T) { }) } } + +func checkUser(got []models.User, want []models.User) bool { + for i, user := range want { + if user.ID != got[i].ID { + return false + } + } + return true +} + +func checkUserSource(got *models.UserSource, want *models.UserSource) bool { + + if got == nil && want == nil { + return true + } else if got == nil || want == nil { + return false + } + + if got.UserID != want.UserID { + return false + } + if got.AccountUsername != want.AccountUsername { + return false + } + if got.Source.DisplayName != want.Source.DisplayName { + return false + } + if got.Source.Domain != want.Source.Domain { + return false + } + if got.Source.Icon != want.Source.Icon { + return false + } + + return true +} diff --git a/pkg/database/database.go b/pkg/database/database.go index 7b1aef2..0bce2bf 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -10,6 +10,9 @@ type OtterSpace interface { // Connect establishes a connection to the database. Connect(ctx context.Context, config models.DatabaseConfig) error + // Post contains all function that are needed to manage Posts + Post + // User contains all function that are needed to manage the AnthroveUser User diff --git a/pkg/database/post.go b/pkg/database/post.go index 7edb191..0111170 100644 --- a/pkg/database/post.go +++ b/pkg/database/post.go @@ -20,9 +20,9 @@ type Post interface { // GetPostBySourceID retrieves a post by its source ID. GetPostBySourceID(ctx context.Context, sourceID models.AnthroveSourceID) (*models.Post, error) - // CreateTagAndReferenceToPost adds a tag with a relation to a post. - CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error + // CreatePostWithReferenceToTagAnd adds a tag with a relation to a post. + CreatePostWithReferenceToTagAnd(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error - // CreateReferenceBetweenPostAndSource links a post with a source. - CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error + // CreatePostReference links a post with a source. + CreatePostReference(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error } diff --git a/pkg/database/postgres/postgres.go b/pkg/database/postgres.go similarity index 93% rename from pkg/database/postgres/postgres.go rename to pkg/database/postgres.go index da69ba8..b63ca0b 100644 --- a/pkg/database/postgres/postgres.go +++ b/pkg/database/postgres.go @@ -1,4 +1,4 @@ -package postgres +package database import ( "context" @@ -9,7 +9,6 @@ import ( "time" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" - "git.dragse.it/anthrove/otter-space-sdk/pkg/database" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" _ "github.com/lib/pq" migrate "github.com/rubenv/sql-migrate" @@ -27,7 +26,7 @@ type postgresqlConnection struct { debug bool } -func NewPostgresqlConnection() database.OtterSpace { +func NewPostgresqlConnection() OtterSpace { return &postgresqlConnection{ db: nil, } @@ -85,11 +84,11 @@ func (p *postgresqlConnection) CreatePost(ctx context.Context, anthrovePost *mod return postgres.CreatePost(ctx, p.db, anthrovePost) } -func (p *postgresqlConnection) CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error { +func (p *postgresqlConnection) CreatePostWithReferenceToTagAnd(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error { return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag) } -func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error { +func (p *postgresqlConnection) CreatePostReference(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL, config models.PostReferenceConfig) error { return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain, postURL, config) } @@ -125,7 +124,7 @@ func (p *postgresqlConnection) GetUserSourceBySourceID(ctx context.Context, anth return postgres.GetUserSourceBySourceID(ctx, p.db, anthroveUserID, sourceID) } -func (p *postgresqlConnection) GetAllUser(ctx context.Context) ([]models.User, error) { +func (p *postgresqlConnection) GetAllUsers(ctx context.Context) ([]models.User, error) { return postgres.GetAllUsers(ctx, p.db) } diff --git a/pkg/database/postgres/postgres_test.go b/pkg/database/postgres_test.go similarity index 95% rename from pkg/database/postgres/postgres_test.go rename to pkg/database/postgres_test.go index bf7159f..26a46fb 100644 --- a/pkg/database/postgres/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -1,4 +1,4 @@ -package postgres +package database import ( "context" @@ -7,7 +7,6 @@ import ( "testing" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" - "git.dragse.it/anthrove/otter-space-sdk/pkg/database" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" "gorm.io/gorm" @@ -17,7 +16,7 @@ func TestNewPostgresqlConnection(t *testing.T) { // Test tests := []struct { name string - want database.OtterSpace + want OtterSpace }{ { name: "Test 1: Create new postgresql connection", @@ -421,8 +420,8 @@ func Test_postgresqlConnection_CreateTagAndReferenceToPost(t *testing.T) { db: gormDB, debug: true, } - if err := p.CreateTagAndReferenceToPost(tt.args.ctx, tt.args.anthrovePostID, tt.args.anthroveTag); (err != nil) != tt.wantErr { - t.Errorf("CreateTagAndReferenceToPost() error = %v, wantErr %v", err, tt.wantErr) + if err := p.CreatePostWithReferenceToTagAnd(tt.args.ctx, tt.args.anthrovePostID, tt.args.anthroveTag); (err != nil) != tt.wantErr { + t.Errorf("CreatePostWithReferenceToTagAnd() error = %v, wantErr %v", err, tt.wantErr) } }) } @@ -522,8 +521,8 @@ func Test_postgresqlConnection_CreateReferenceBetweenPostAndSource(t *testing.T) db: gormDB, debug: true, } - if err := p.CreateReferenceBetweenPostAndSource(tt.args.ctx, tt.args.anthrovePostID, tt.args.sourceDomain, tt.args.postURl, models.PostReferenceConfig{}); (err != nil) != tt.wantErr { - t.Errorf("CreateReferenceBetweenPostAndSource() error = %v, wantErr %v", err, tt.wantErr) + if err := p.CreatePostReference(tt.args.ctx, tt.args.anthrovePostID, tt.args.sourceDomain, tt.args.postURl, models.PostReferenceConfig{}); (err != nil) != tt.wantErr { + t.Errorf("CreatePostReference() error = %v, wantErr %v", err, tt.wantErr) } }) } @@ -714,7 +713,7 @@ func Test_postgresqlConnection_CheckReferenceBetweenUserAndPost(t *testing.T) { db: gormDB, debug: true, } - got, err := p.CheckIfUserFavouritedPost(tt.args.ctx, tt.args.anthroveUserID, tt.args.anthrovePostID) + got, err := p.CheckIfUserHasPostAsFavorite(tt.args.ctx, tt.args.anthroveUserID, tt.args.anthrovePostID) if (err != nil) != tt.wantErr { t.Errorf("CheckIfUserHasPostAsFavorite() error = %v, wantErr %v", err, tt.wantErr) return @@ -1235,20 +1234,20 @@ func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) { validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) - expectedResult := make(map[string]models.UserSource) - source := &models.Source{ BaseModel: models.BaseModel[models.AnthroveSourceID]{ ID: validSourceID, }, DisplayName: "e621", Domain: "e621.net", + Icon: "https://e621.icon", } - expectedResult["e621"] = models.UserSource{ - UserID: "e1", + expectedResult := &models.UserSource{ + UserID: string(validUserID), AccountUsername: "euser", Source: models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: source.ID}, DisplayName: source.DisplayName, Domain: source.Domain, Icon: source.Icon, @@ -1260,7 +1259,7 @@ func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) { t.Fatal(err) } - err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult["e621"].UserID, expectedResult["e621"].AccountUsername) + err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, expectedResult.UserID, expectedResult.AccountUsername) if err != nil { t.Fatal(err) } @@ -1271,10 +1270,11 @@ func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) { anthroveUserID models.AnthroveUserID sourceID models.AnthroveSourceID } + tests := []struct { name string args args - want map[string]models.UserSource + want *models.UserSource wantErr bool }{ { @@ -1349,14 +1349,14 @@ func Test_postgresqlConnection_GetUserSourceBySourceID(t *testing.T) { t.Errorf("GetUserSourceBySourceID() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(got, tt.want) { + if !checkUserSource(got, tt.want) { t.Errorf("GetUserSourceBySourceID() got = %v, want %v", got, tt.want) } }) } } -func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) { +func Test_postgresqlConnection_GetAllUsers(t *testing.T) { // Setup trow away container ctx := context.Background() container, gormDB, err := test.StartPostgresContainer(ctx) @@ -1370,10 +1370,20 @@ func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) { validUserID02 := models.AnthroveUserID(fmt.Sprintf("%025s", "User2")) validUserID03 := models.AnthroveUserID(fmt.Sprintf("%025s", "User3")) - users := []models.AnthroveUserID{validUserID01, validUserID02, validUserID03} + users := []models.User{ + { + BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID01}, + }, + { + BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID02}, + }, + { + BaseModel: models.BaseModel[models.AnthroveUserID]{ID: validUserID03}, + }, + } for _, user := range users { - err = postgres.CreateUser(ctx, gormDB, user) + err = postgres.CreateUser(ctx, gormDB, user.ID) if err != nil { t.Fatal(err) } @@ -1386,7 +1396,7 @@ func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) { tests := []struct { name string args args - want []models.AnthroveUserID + want []models.User wantErr bool }{ { @@ -1403,12 +1413,12 @@ func Test_postgresqlConnection_GetAllAnthroveUserIDs(t *testing.T) { db: gormDB, debug: true, } - got, err := p.GetAllAnthroveUserIDs(tt.args.ctx) + got, err := p.GetAllUsers(tt.args.ctx) if (err != nil) != tt.wantErr { t.Errorf("GetAllUsers() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(got, tt.want) { + if !checkUser(got, tt.want) { t.Errorf("GetAllUsers() got = %v, want %v", got, tt.want) } }) @@ -1975,3 +1985,38 @@ func Test_postgresqlConnection_migrateDatabase(t *testing.T) { }) } } + +func checkUser(got []models.User, want []models.User) bool { + for i, user := range want { + if user.ID != got[i].ID { + return false + } + } + return true +} +func checkUserSource(got *models.UserSource, want *models.UserSource) bool { + + if got == nil && want == nil { + return true + } else if got == nil || want == nil { + return false + } + + if got.UserID != want.UserID { + return false + } + if got.AccountUsername != want.AccountUsername { + return false + } + if got.Source.DisplayName != want.Source.DisplayName { + return false + } + if got.Source.Domain != want.Source.Domain { + return false + } + if got.Source.Icon != want.Source.Icon { + return false + } + + return true +} diff --git a/pkg/database/user.go b/pkg/database/user.go index e7be12e..b74d672 100644 --- a/pkg/database/user.go +++ b/pkg/database/user.go @@ -20,7 +20,7 @@ type User interface { UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error - GetAllUser(ctx context.Context) ([]models.User, error) + GetAllUsers(ctx context.Context) ([]models.User, error) // GetUserFavoritesCount retrieves the count of a user's favorites. GetUserFavoritesCount(ctx context.Context, anthroveUserID models.AnthroveUserID) (int64, error) diff --git a/pkg/models/postReference_test.go b/pkg/models/postReference_test.go index 232a695..d203024 100644 --- a/pkg/models/postReference_test.go +++ b/pkg/models/postReference_test.go @@ -26,13 +26,15 @@ func TestPostReference_TableName(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { po := PostReference{ - PostID: tt.fields.PostID, - SourceID: tt.fields.SourceID, - URL: tt.fields.URL, - SourcePostID: tt.fields.SourcePostID, - FullFileURL: tt.fields.FullFileURL, - PreviewFileURL: tt.fields.PreviewFileURL, - SampleFileURL: tt.fields.SampleFileURL, + PostID: tt.fields.PostID, + SourceID: tt.fields.SourceID, + URL: tt.fields.URL, + PostReferenceConfig: PostReferenceConfig{ + SourcePostID: tt.fields.SourcePostID, + FullFileURL: tt.fields.FullFileURL, + PreviewFileURL: tt.fields.PreviewFileURL, + SampleFileURL: tt.fields.SampleFileURL, + }, } if got := po.TableName(); got != tt.want { t.Errorf("TableName() = %v, want %v", got, tt.want) diff --git a/test/helper.go b/test/helper.go index ce571d2..b16d9d1 100644 --- a/test/helper.go +++ b/test/helper.go @@ -6,6 +6,7 @@ import ( "net/url" "strconv" "strings" + "time" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" migrate "github.com/rubenv/sql-migrate" @@ -22,7 +23,7 @@ const ( databaseName = "anthrove" databaseUser = "anthrove" databasePassword = "anthrove" - migrationSource = "../../pkg/database/migrations" + migrationSource = "../../pkg/database/migrations/" ) func StartPostgresContainer(ctx context.Context) (*postgrescontainer.PostgresContainer, *gorm.DB, error) { @@ -33,7 +34,9 @@ func StartPostgresContainer(ctx context.Context) (*postgrescontainer.PostgresCon postgrescontainer.WithUsername(databaseUser), postgrescontainer.WithPassword(databasePassword), testcontainers.WithWaitStrategy( - wait.ForLog("database system is ready to accept connections"))) + wait.ForLog("database system is ready to accept connections"). + WithOccurrence(2).WithStartupTimeout(60*time.Second)), + ) if err != nil { return nil, nil, err } From bb456583103ae1de98cfca78a765d25d0b95c58b Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 28 Jun 2024 15:13:40 +0200 Subject: [PATCH 113/124] feat(TagAlias): added function and tests Signed-off-by: SoXX --- internal/postgres/tag.go | 94 ++++++++++++++++ internal/postgres/tag_test.go | 98 +++++++++++++++++ pkg/database/postgres.go | 86 ++++++++------- pkg/database/postgres_test.go | 194 +++++++++++++++++++++++++--------- 4 files changed, 379 insertions(+), 93 deletions(-) diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 23e23ef..729d57a 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -90,3 +90,97 @@ func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) { return tags, nil } + +func CreateTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error { + + if tagAliasName == "" { + return &otterError.EntityValidationFailed{Reason: "tagAliasName cannot be empty"} + } + if tagID == "" { + return &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + } + + result := db.WithContext(ctx).Create(&models.TagAlias{ + Name: string(tagAliasName), + TagID: string(tagID), + }) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrDuplicatedKey) { + return &otterError.EntityAlreadyExists{} + } + return result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_name": tagAliasName, + "tag_alias_tag_id": tagID, + }).Trace("database: created tagAlias") + + return nil +} + +func GetAllTagAlias(ctx context.Context, db *gorm.DB) ([]models.TagAlias, error) { + var tagAliases []models.TagAlias + + result := db.WithContext(ctx).Find(&tagAliases) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &otterError.NoDataFound{} + } + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_length": len(tagAliases), + }).Trace("database: created tagAlias") + + return tagAliases, nil +} + +func GetAllTagAliasByTag(ctx context.Context, db *gorm.DB, tagID models.AnthroveTagID) ([]models.TagAlias, error) { + var tagAliases []models.TagAlias + + if tagID == "" { + return nil, &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + } + + result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagAliases) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &otterError.NoDataFound{} + } + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_length": len(tagAliases), + "tag_alias_tag_id": tagID, + }).Trace("database: get specific tagAlias") + + return tagAliases, nil +} + +func DeleteTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.AnthroveTagAliasName) error { + + if tagAliasName == "" { + return &otterError.EntityValidationFailed{Reason: "tagAliasName cannot be empty"} + } + + result := db.WithContext(ctx).Delete(&models.TagAlias{Name: string(tagAliasName)}) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return &otterError.NoDataFound{} + } + return result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_name": tagAliasName, + }).Trace("database: deleted tagAlias") + + return nil +} diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index 3f22c76..c18712a 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -246,3 +246,101 @@ func TestCreateTag(t *testing.T) { }) } } + +func TestCreateTagAlias(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validTagAliasName01 := models.AnthroveTagAliasName("httyd") + validTagAliasName02 := models.AnthroveTagAliasName("dragon") + + validTagID := models.AnthroveTagID("toothless") + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagAliasName models.AnthroveTagAliasName + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + db: gormDB, + tagAliasName: validTagAliasName01, + tagID: validTagID, + }, + wantErr: false, + }, + { + name: "Test 2: No TagAliasName", + args: args{ + ctx: ctx, + db: gormDB, + tagAliasName: "", + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 4: No tagID", + args: args{ + ctx: ctx, + db: gormDB, + tagAliasName: validTagAliasName01, + tagID: "", + }, + wantErr: true, + }, + { + name: "Test 5: Duplicate tagID", + args: args{ + ctx: ctx, + db: gormDB, + tagAliasName: validTagAliasName01, + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 6: Invalide tagID", + args: args{ + ctx: ctx, + db: gormDB, + tagAliasName: validTagAliasName02, + tagID: "aaa", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CreateTagAlias(tt.args.ctx, tt.args.db, tt.args.tagAliasName, tt.args.tagID); (err != nil) != tt.wantErr { + t.Errorf("CreateTagAlias() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index b63ca0b..d511a84 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -148,50 +148,7 @@ func (p *postgresqlConnection) GetSourceByDomain(ctx context.Context, sourceDoma return postgres.GetSourceByDomain(ctx, p.db, sourceDomain) } -func (p *postgresqlConnection) GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) { - //TODO implement me - panic("implement me") -} - -func (p *postgresqlConnection) GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) { - //TODO implement me - panic("implement me") -} - -func (p *postgresqlConnection) CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error { - //TODO implement me - panic("implement me") -} - -func (p *postgresqlConnection) DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error { - //TODO implement me - panic("implement me") -} - -func (p *postgresqlConnection) GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) { - //TODO implement me - panic("implement me") -} - -func (p *postgresqlConnection) GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) { - //TODO implement me - panic("implement me") -} - -func (p *postgresqlConnection) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) { - //TODO implement me - panic("implement me") -} - -func (p *postgresqlConnection) DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error { - //TODO implement me - panic("implement me") -} - -func (p *postgresqlConnection) UpdateUserWithScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error { - //TODO implement me - panic("implement me") -} +// NEW FUNCTIONS func (p *postgresqlConnection) UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error { //TODO implement me @@ -208,6 +165,47 @@ func (p *postgresqlConnection) UpdateUserSourceValidation(ctx context.Context, a panic("implement me") } +func (p *postgresqlConnection) CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error { + return postgres.CreateTagAlias(ctx, p.db, tagAliasName, tagID) +} + +func (p *postgresqlConnection) GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error { + //TODO implement me + panic("implement me") +} + +// HELPER + func (p *postgresqlConnection) migrateDatabase(dbPool *gorm.DB) error { dialect := "postgres" migrations := &migrate.EmbedFileSystemMigrationSource{FileSystem: embedMigrations, Root: "migrations"} diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index 26a46fb..6950118 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -1898,55 +1898,6 @@ func Test_postgresqlConnection_GetSourceByDomain(t *testing.T) { } } -func checkSource(got *models.Source, want *models.Source) bool { - - if want == nil && got == nil { - return true - } - - if got.Domain != want.Domain { - return false - } - - return true - -} - -func checkPost(got *models.Post, want *models.Post) bool { - - if got == nil && want == nil { - return true - } else if got == nil || want == nil { - return false - } - - if got.ID != want.ID { - return false - } - - if got.Rating != want.Rating { - return false - } - - return true -} - -func checkSources(got []models.Source, want []models.Source) bool { - for i, source := range want { - if source.DisplayName != got[i].DisplayName { - return false - } - if source.Domain != got[i].Domain { - return false - } - if source.Icon != got[i].Icon { - return false - } - } - - return true -} - func Test_postgresqlConnection_migrateDatabase(t *testing.T) { // Setup trow away container ctx := context.Background() @@ -1986,6 +1937,53 @@ func Test_postgresqlConnection_migrateDatabase(t *testing.T) { } } +// Helper functions for validation purposes +func checkSource(got *models.Source, want *models.Source) bool { + + if want == nil && got == nil { + return true + } + + if got.Domain != want.Domain { + return false + } + + return true + +} +func checkPost(got *models.Post, want *models.Post) bool { + + if got == nil && want == nil { + return true + } else if got == nil || want == nil { + return false + } + + if got.ID != want.ID { + return false + } + + if got.Rating != want.Rating { + return false + } + + return true +} +func checkSources(got []models.Source, want []models.Source) bool { + for i, source := range want { + if source.DisplayName != got[i].DisplayName { + return false + } + if source.Domain != got[i].Domain { + return false + } + if source.Icon != got[i].Icon { + return false + } + } + + return true +} func checkUser(got []models.User, want []models.User) bool { for i, user := range want { if user.ID != got[i].ID { @@ -2020,3 +2018,101 @@ func checkUserSource(got *models.UserSource, want *models.UserSource) bool { return true } + +//------------------------- + +func Test_postgresqlConnection_CreateTagAlias(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validTagAliasName01 := models.AnthroveTagAliasName("httyd") + validTagAliasName02 := models.AnthroveTagAliasName("dragon") + + validTagID := models.AnthroveTagID("toothless") + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + tagAliasName models.AnthroveTagAliasName + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + tagAliasName: validTagAliasName01, + tagID: validTagID, + }, + wantErr: false, + }, + { + name: "Test 2: No TagAliasName", + args: args{ + ctx: ctx, + tagAliasName: "", + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 4: No tagID", + args: args{ + ctx: ctx, + tagAliasName: validTagAliasName01, + tagID: "", + }, + wantErr: true, + }, + { + name: "Test 5: Duplicate tagID", + args: args{ + ctx: ctx, + tagAliasName: validTagAliasName01, + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 6: Invalide tagID", + args: args{ + ctx: ctx, + tagAliasName: validTagAliasName02, + tagID: "aaa", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.CreateTagAlias(tt.args.ctx, tt.args.tagAliasName, tt.args.tagID); (err != nil) != tt.wantErr { + t.Errorf("CreateTagAlias() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 26178eb64d6c0949005e6748d9a734ef2a49cb0d Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 28 Jun 2024 22:14:27 +0200 Subject: [PATCH 114/124] feat(TagAlias): added function and tests Signed-off-by: SoXX --- internal/postgres/tag_test.go | 78 +++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +- pkg/database/postgres_test.go | 77 ++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 2 deletions(-) diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index c18712a..8e51eb9 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -3,6 +3,7 @@ package postgres import ( "context" "fmt" + "reflect" "testing" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" @@ -344,3 +345,80 @@ func TestCreateTagAlias(t *testing.T) { }) } } + +func TestGetAllTagAlias(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagAliases := []models.AnthroveTagAliasName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagAlias{ + { + Name: string(validTagAliases[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagAliases[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagAliases[2]), + TagID: string(validTagID), + }, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagAliasName := range validTagAliases { + err = CreateTagAlias(ctx, gormDB, tagAliasName, validTagID) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + } + tests := []struct { + name string + args args + want []models.TagAlias + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + db: gormDB, + }, + want: expectedResult, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllTagAlias(tt.args.ctx, tt.args.db) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagAlias() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagAlias() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index d511a84..bb1e8c0 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -170,8 +170,7 @@ func (p *postgresqlConnection) CreateTagAlias(ctx context.Context, tagAliasName } func (p *postgresqlConnection) GetAllTagAlias(ctx context.Context) ([]models.TagAlias, error) { - //TODO implement me - panic("implement me") + return postgres.GetAllTagAlias(ctx, p.db) } func (p *postgresqlConnection) GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) { diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index 6950118..dbcd844 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -2116,3 +2116,80 @@ func Test_postgresqlConnection_CreateTagAlias(t *testing.T) { }) } } + +func Test_postgresqlConnection_GetAllTagAlias(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagAliases := []models.AnthroveTagAliasName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagAlias{ + { + Name: string(validTagAliases[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagAliases[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagAliases[2]), + TagID: string(validTagID), + }, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagAliasName := range validTagAliases { + err = postgres.CreateTagAlias(ctx, gormDB, tagAliasName, validTagID) + } + + // Test + type args struct { + ctx context.Context + } + tests := []struct { + name string + args args + want []models.TagAlias + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ctx: ctx}, + want: expectedResult, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllTagAlias(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagAlias() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagAlias() got = %v, want %v", got, tt.want) + } + }) + } +} From 702870db1e87036a8965633409437a77bd19269b Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 28 Jun 2024 22:27:31 +0200 Subject: [PATCH 115/124] feat(TagAlias): added function and tests Signed-off-by: SoXX --- internal/postgres/tag_test.go | 174 ++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 6 +- pkg/database/postgres_test.go | 174 ++++++++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+), 4 deletions(-) diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index 8e51eb9..54f8c03 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -422,3 +422,177 @@ func TestGetAllTagAlias(t *testing.T) { }) } } + +func TestGetAllTagAliasByTag(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagAliases := []models.AnthroveTagAliasName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagAlias{ + { + Name: string(validTagAliases[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagAliases[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagAliases[2]), + TagID: string(validTagID), + }, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagAliasName := range validTagAliases { + err = CreateTagAlias(ctx, gormDB, tagAliasName, validTagID) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + want []models.TagAlias + wantErr bool + }{ + { + name: "Test 1: Valid TagID", + args: args{ + ctx: ctx, + db: gormDB, + tagID: validTagID, + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: No TagID", + args: args{ + ctx: ctx, + db: gormDB, + tagID: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: Invalid TagID", + args: args{ + ctx: ctx, + db: gormDB, + tagID: "adads", + }, + want: []models.TagAlias{}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllTagAliasByTag(tt.args.ctx, tt.args.db, tt.args.tagID) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagAliasByTag() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagAliasByTag() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDeleteTagAlias(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagAliases := []models.AnthroveTagAliasName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagAliasName := range validTagAliases { + err = CreateTagAlias(ctx, gormDB, tagAliasName, validTagID) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagAliasName models.AnthroveTagAliasName + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveTagAliasName", + args: args{ + ctx: ctx, + db: gormDB, + tagAliasName: validTagAliases[0], + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveTagAliasName", + args: args{ + ctx: ctx, + db: gormDB, + tagAliasName: "asdad", + }, + wantErr: false, + }, + { + name: "Test 3: No AnthroveTagAliasName", + args: args{ + ctx: ctx, + db: gormDB, + tagAliasName: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := DeleteTagAlias(tt.args.ctx, tt.args.db, tt.args.tagAliasName); (err != nil) != tt.wantErr { + t.Errorf("DeleteTagAlias() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index bb1e8c0..1eb22de 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -174,13 +174,11 @@ func (p *postgresqlConnection) GetAllTagAlias(ctx context.Context) ([]models.Tag } func (p *postgresqlConnection) GetAllTagAliasByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagAlias, error) { - //TODO implement me - panic("implement me") + return postgres.GetAllTagAliasByTag(ctx, p.db, tagID) } func (p *postgresqlConnection) DeleteTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName) error { - //TODO implement me - panic("implement me") + return postgres.DeleteTagAlias(ctx, p.db, tagAliasName) } func (p *postgresqlConnection) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) { diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index dbcd844..acd0b0e 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -2193,3 +2193,177 @@ func Test_postgresqlConnection_GetAllTagAlias(t *testing.T) { }) } } + +func Test_postgresqlConnection_GetAllTagAliasByTag(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagAliases := []models.AnthroveTagAliasName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagAlias{ + { + Name: string(validTagAliases[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagAliases[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagAliases[2]), + TagID: string(validTagID), + }, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagAliasName := range validTagAliases { + err = postgres.CreateTagAlias(ctx, gormDB, tagAliasName, validTagID) + } + + // Test + type args struct { + ctx context.Context + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + want []models.TagAlias + wantErr bool + }{ + { + name: "Test 1: Valid TagID", + args: args{ + ctx: ctx, + tagID: validTagID, + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: No TagID", + args: args{ + ctx: ctx, + tagID: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: Invalid TagID", + args: args{ + ctx: ctx, + tagID: "adads", + }, + want: []models.TagAlias{}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllTagAliasByTag(tt.args.ctx, tt.args.tagID) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagAliasByTag() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagAliasByTag() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_DeleteTagAlias(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagAliases := []models.AnthroveTagAliasName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagAliasName := range validTagAliases { + err = postgres.CreateTagAlias(ctx, gormDB, tagAliasName, validTagID) + } + + // Test + type args struct { + ctx context.Context + tagAliasName models.AnthroveTagAliasName + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveTagAliasName", + args: args{ + ctx: ctx, + tagAliasName: validTagAliases[0], + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveTagAliasName", + args: args{ + ctx: ctx, + tagAliasName: "asdad", + }, + wantErr: false, + }, + { + name: "Test 3: No AnthroveTagAliasName", + args: args{ + ctx: ctx, + tagAliasName: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.DeleteTagAlias(tt.args.ctx, tt.args.tagAliasName); (err != nil) != tt.wantErr { + t.Errorf("DeleteTagAlias() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From d759e072f77751f725e3f2f46fa34f79b3781917 Mon Sep 17 00:00:00 2001 From: SoXX Date: Fri, 28 Jun 2024 22:39:12 +0200 Subject: [PATCH 116/124] feat(TagGroup): added function and tests Signed-off-by: SoXX --- internal/postgres/tag.go | 94 +++++++++ internal/postgres/tag_test.go | 349 ++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 14 +- pkg/database/postgres_test.go | 349 ++++++++++++++++++++++++++++++++++ pkg/database/taggroup.go | 2 +- 5 files changed, 798 insertions(+), 10 deletions(-) diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 729d57a..4e851e2 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -184,3 +184,97 @@ func DeleteTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.Anthro return nil } + +func CreateTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error { + + if tagGroupName == "" { + return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"} + } + if tagID == "" { + return &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + } + + result := db.WithContext(ctx).Create(&models.TagGroup{ + Name: string(tagGroupName), + TagID: string(tagID), + }) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrDuplicatedKey) { + return &otterError.EntityAlreadyExists{} + } + return result.Error + } + + log.WithFields(log.Fields{ + "tag_group_name": tagGroupName, + "tag_group_tag_id": tagID, + }).Trace("database: created tagGroup") + + return nil +} + +func GetAllTagGroup(ctx context.Context, db *gorm.DB) ([]models.TagGroup, error) { + var tagGroups []models.TagGroup + + result := db.WithContext(ctx).Find(&tagGroups) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &otterError.NoDataFound{} + } + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_length": len(tagGroups), + }).Trace("database: created tagGroup") + + return tagGroups, nil +} + +func GetAllTagGroupByTag(ctx context.Context, db *gorm.DB, tagID models.AnthroveTagID) ([]models.TagGroup, error) { + var tagGroups []models.TagGroup + + if tagID == "" { + return nil, &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + } + + result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagGroups) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &otterError.NoDataFound{} + } + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_length": len(tagGroups), + "tag_alias_tag_id": tagID, + }).Trace("database: get specific tagGroup") + + return tagGroups, nil +} + +func DeleteTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName) error { + + if tagGroupName == "" { + return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"} + } + + result := db.WithContext(ctx).Delete(&models.TagGroup{Name: string(tagGroupName)}) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return &otterError.NoDataFound{} + } + return result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_name": tagGroupName, + }).Trace("database: deleted tagAlias") + + return nil +} diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index 54f8c03..adbc867 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -596,3 +596,352 @@ func TestDeleteTagAlias(t *testing.T) { }) } } + +func TestCreateTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validTagGroupName01 := models.AnthroveTagGroupName("httyd") + validTagGroupName02 := models.AnthroveTagGroupName("dragon") + + validTagID := models.AnthroveTagID("toothless") + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagGroupName models.AnthroveTagGroupName + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupName01, + tagID: validTagID, + }, + wantErr: false, + }, + { + name: "Test 2: No TagGroupName", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: "", + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 4: No tagID", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupName01, + tagID: "", + }, + wantErr: true, + }, + { + name: "Test 5: Duplicate tagID", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupName01, + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 6: Invalide tagID", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupName02, + tagID: "aaa", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CreateTagGroup(tt.args.ctx, tt.args.db, tt.args.tagGroupName, tt.args.tagID); (err != nil) != tt.wantErr { + t.Errorf("CreateTagGroup() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestGetAllTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagGroup{ + { + Name: string(validTagGroupes[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[2]), + TagID: string(validTagID), + }, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + } + tests := []struct { + name string + args args + want []models.TagGroup + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + db: gormDB, + }, + want: expectedResult, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllTagGroup(tt.args.ctx, tt.args.db) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagGroup() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagGroup() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetAllTagGroupByTag(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagGroup{ + { + Name: string(validTagGroupes[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[2]), + TagID: string(validTagID), + }, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + want []models.TagGroup + wantErr bool + }{ + { + name: "Test 1: Valid TagID", + args: args{ + ctx: ctx, + db: gormDB, + tagID: validTagID, + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: No TagID", + args: args{ + ctx: ctx, + db: gormDB, + tagID: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: Invalid TagID", + args: args{ + ctx: ctx, + db: gormDB, + tagID: "adads", + }, + want: []models.TagGroup{}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllTagGroupByTag(tt.args.ctx, tt.args.db, tt.args.tagID) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagGroupByTag() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagGroupByTag() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDeleteTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagGroupName models.AnthroveTagGroupName + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveTagGroupName", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupes[0], + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveTagGroupName", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: "asdad", + }, + wantErr: false, + }, + { + name: "Test 3: No AnthroveTagGroupName", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := DeleteTagGroup(tt.args.ctx, tt.args.db, tt.args.tagGroupName); (err != nil) != tt.wantErr { + t.Errorf("DeleteTagAlias() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 1eb22de..39c7a54 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -181,24 +181,20 @@ func (p *postgresqlConnection) DeleteTagAlias(ctx context.Context, tagAliasName return postgres.DeleteTagAlias(ctx, p.db, tagAliasName) } -func (p *postgresqlConnection) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) { - //TODO implement me - panic("implement me") +func (p *postgresqlConnection) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error { + return postgres.CreateTagGroup(ctx, p.db, tagGroupName, tagID) } func (p *postgresqlConnection) GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) { - //TODO implement me - panic("implement me") + return postgres.GetAllTagGroup(ctx, p.db) } func (p *postgresqlConnection) GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) { - //TODO implement me - panic("implement me") + return postgres.GetAllTagGroupByTag(ctx, p.db, tagID) } func (p *postgresqlConnection) DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error { - //TODO implement me - panic("implement me") + return postgres.DeleteTagGroup(ctx, p.db, tagGroupName) } // HELPER diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index acd0b0e..d53f9e2 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -2367,3 +2367,352 @@ func Test_postgresqlConnection_DeleteTagAlias(t *testing.T) { }) } } + +//-------------------------- + +func Test_postgresqlConnection_CreateTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validTagGroupName01 := models.AnthroveTagGroupName("httyd") + validTagGroupName02 := models.AnthroveTagGroupName("dragon") + + validTagID := models.AnthroveTagID("toothless") + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + tagGroupName models.AnthroveTagGroupName + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupName01, + tagID: validTagID, + }, + wantErr: false, + }, + { + name: "Test 2: No TagGroupName", + args: args{ + ctx: ctx, + tagGroupName: "", + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 4: No tagID", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupName01, + tagID: "", + }, + wantErr: true, + }, + { + name: "Test 5: Duplicate tagID", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupName01, + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 6: Invalide tagID", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupName02, + tagID: "aaa", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.CreateTagGroup(tt.args.ctx, tt.args.tagGroupName, tt.args.tagID); (err != nil) != tt.wantErr { + t.Errorf("CreateTagGroup() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_GetAllTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagGroup{ + { + Name: string(validTagGroupes[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[2]), + TagID: string(validTagID), + }, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = postgres.CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + } + tests := []struct { + name string + args args + want []models.TagGroup + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ctx: ctx}, + want: expectedResult, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllTagGroup(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagGroup() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagGroup() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetAllTagGroupByTag(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagGroup{ + { + Name: string(validTagGroupes[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[2]), + TagID: string(validTagID), + }, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = postgres.CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + want []models.TagGroup + wantErr bool + }{ + { + name: "Test 1: Valid TagID", + args: args{ + ctx: ctx, + tagID: validTagID, + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: No TagID", + args: args{ + ctx: ctx, + tagID: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: Invalid TagID", + args: args{ + ctx: ctx, + tagID: "adads", + }, + want: []models.TagGroup{}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllTagGroupByTag(tt.args.ctx, tt.args.tagID) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagGroupByTag() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagGroupByTag() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_DeleteTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = postgres.CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + tagGroupName models.AnthroveTagGroupName + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveTagGroupName", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupes[0], + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveTagGroupName", + args: args{ + ctx: ctx, + tagGroupName: "asdad", + }, + wantErr: false, + }, + { + name: "Test 3: No AnthroveTagGroupName", + args: args{ + ctx: ctx, + tagGroupName: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.DeleteTagGroup(tt.args.ctx, tt.args.tagGroupName); (err != nil) != tt.wantErr { + t.Errorf("DeleteTagAlias() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/database/taggroup.go b/pkg/database/taggroup.go index 594cd1e..f25bd68 100644 --- a/pkg/database/taggroup.go +++ b/pkg/database/taggroup.go @@ -7,7 +7,7 @@ import ( ) type TagGroup interface { - CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) + CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) From 6ccd593d8888cbb37e2fbdae64e94648e040eb0d Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 1 Jul 2024 11:36:21 +0200 Subject: [PATCH 117/124] refactor: changed code layout Signed-off-by: SoXX --- internal/postgres/user.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index c0a2543..042154f 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -11,6 +11,13 @@ import ( "gorm.io/gorm" ) +// Workaround, should be changed later maybe, but its not that bad right now +type selectFrequencyTag struct { + tagName string `gorm:"tag_name"` + count int64 `gorm:"count"` + tagType models.TagType `gorm:"tag_type"` +} + func CreateUser(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) error { if anthroveUserID == "" { @@ -267,13 +274,6 @@ func GetUserFavoriteWithPagination(ctx context.Context, db *gorm.DB, anthroveUse return &models.FavoriteList{Posts: favoritePosts}, nil } -// Workaround, should be changed later maybe, but its not that bad right now -type selectFrequencyTag struct { - tagName string `gorm:"tag_name"` - count int64 `gorm:"count"` - tagType models.TagType `gorm:"tag_type"` -} - func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID) ([]models.TagsWithFrequency, error) { var queryUserFavorites []selectFrequencyTag From 5f9ace9bd35077cf7eb55801e46f18f900bb6ba9 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 1 Jul 2024 13:42:53 +0200 Subject: [PATCH 118/124] feat: implemented all functions Signed-off-by: SoXX --- internal/postgres/user.go | 99 +++++++++ internal/postgres/user_test.go | 365 +++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 9 +- pkg/database/postgres_test.go | 357 ++++++++++++++++++++++++++++++++ pkg/error/validation.go | 6 +- pkg/models/const.go | 4 +- 6 files changed, 831 insertions(+), 9 deletions(-) diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 042154f..5037a17 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -3,6 +3,7 @@ package postgres import ( "context" "errors" + "time" otterError "git.dragse.it/anthrove/otter-space-sdk/pkg/error" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" @@ -320,3 +321,101 @@ func GetUserTagWitRelationToFavedPosts(ctx context.Context, db *gorm.DB, anthrov return userFavoritesFrequency, nil } + +func UpdateUserSourceScrapeTimeInterval(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error { + + if anthroveUserID == "" { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} + } + + if len(anthroveUserID) != 25 { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} + } + + if sourceID == "" { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDEmpty} + } + + if len(sourceID) != 25 { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDToShort} + } + + if scrapeTime == 0 { + return &otterError.EntityValidationFailed{Reason: "ScrapeTimeInterval cannot be empty"} + } + + userSource := &models.UserSource{ + UserID: string(anthroveUserID), + } + + result := db.WithContext(ctx).Model(&userSource).Update("scrape_time_interval", scrapeTime) + if result.Error != nil { + return result.Error + } + + return nil +} + +func UpdateUserSourceLastScrapeTime(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error { + + if anthroveUserID == "" { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} + } + + if len(anthroveUserID) != 25 { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} + } + + if sourceID == "" { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDEmpty} + } + + if len(sourceID) != 25 { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDToShort} + } + + if time.Time.IsZero(time.Time(lastScrapeTime)) { + return &otterError.EntityValidationFailed{Reason: "LastScrapeTime cannot be empty"} + } + + userSource := &models.UserSource{ + UserID: string(anthroveUserID), + } + + result := db.WithContext(ctx).Model(&userSource).Update("last_scrape_time", time.Time(lastScrapeTime)) + if result.Error != nil { + return result.Error + } + + return nil +} + +func UpdateUserSourceValidation(ctx context.Context, db *gorm.DB, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error { + + if anthroveUserID == "" { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} + } + + if len(anthroveUserID) != 25 { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDToShort} + } + + if sourceID == "" { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDEmpty} + } + + if len(sourceID) != 25 { + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveSourceIDToShort} + } + + userSource := &models.UserSource{ + UserID: string(anthroveUserID), + } + + result := db.WithContext(ctx).Model(&userSource).Update("account_validate", valid) + if result.Error != nil { + return result.Error + } + + return nil +} diff --git a/internal/postgres/user_test.go b/internal/postgres/user_test.go index 8dfa13a..c8be97a 100644 --- a/internal/postgres/user_test.go +++ b/internal/postgres/user_test.go @@ -5,6 +5,7 @@ import ( "fmt" "reflect" "testing" + "time" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" "git.dragse.it/anthrove/otter-space-sdk/test" @@ -986,3 +987,367 @@ func checkUserSource(got *models.UserSource, want *models.UserSource) bool { return true } + +func TestUpdateUserSourceScrapeTimeInterval(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: validSourceID, + }, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.icon", + } + + err = CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, "e66e6e6e6", "euser") + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + sourceID models.AnthroveSourceID + scrapeTime models.AnthroveScrapeTimeInterval + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: validSourceID, + scrapeTime: 10, + }, + wantErr: false, + }, + { + name: "Test 2: anthroveUserID to short", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: invalidUserID, + sourceID: validSourceID, + scrapeTime: 10, + }, + wantErr: true, + }, + { + name: "Test 3: anthroveUserID is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + sourceID: validSourceID, + scrapeTime: 10, + }, + wantErr: true, + }, + { + name: "Test 4: anthroveUserID to short", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: "111", + scrapeTime: 10, + }, + wantErr: true, + }, + { + name: "Test 5: anthroveUserID is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: "", + scrapeTime: 10, + }, + wantErr: true, + }, + { + name: "Test 5: scrapeTime is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: validSourceID, + scrapeTime: 0, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := UpdateUserSourceScrapeTimeInterval(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID, tt.args.scrapeTime); (err != nil) != tt.wantErr { + t.Errorf("UpdateUserSourceScrapeTimeInterval() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestUpdateUserSourceLastScrapeTime(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + + validScrapeTime := models.AnthroveUserLastScrapeTime(time.Now()) + inValidScrapeTime := models.AnthroveUserLastScrapeTime{} + + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: validSourceID, + }, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.icon", + } + + err = CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, "e66e6e6e6", "euser") + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + sourceID models.AnthroveSourceID + lastScrapeTime models.AnthroveUserLastScrapeTime + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: validSourceID, + lastScrapeTime: validScrapeTime, + }, + wantErr: false, + }, + { + name: "Test 2: anthroveUserID to short", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: invalidUserID, + sourceID: validSourceID, + lastScrapeTime: validScrapeTime, + }, + wantErr: true, + }, + { + name: "Test 3: anthroveUserID is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + sourceID: validSourceID, + lastScrapeTime: validScrapeTime, + }, + wantErr: true, + }, + { + name: "Test 4: anthroveUserID to short", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: "111", + lastScrapeTime: validScrapeTime, + }, + wantErr: true, + }, + { + name: "Test 5: anthroveUserID is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: "", + lastScrapeTime: validScrapeTime, + }, + wantErr: true, + }, + { + name: "Test 5: scrapeTime is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: validSourceID, + lastScrapeTime: inValidScrapeTime, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := UpdateUserSourceLastScrapeTime(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID, tt.args.lastScrapeTime); (err != nil) != tt.wantErr { + t.Errorf("UpdateUserSourceLastScrapeTime() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestUpdateUserSourceValidation(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: validSourceID, + }, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.icon", + } + + err = CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + err = CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, "e66e6e6e6", "euser") + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + anthroveUserID models.AnthroveUserID + sourceID models.AnthroveSourceID + valid bool + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: validSourceID, + valid: true, + }, + wantErr: false, + }, + { + name: "Test 2: anthroveUserID to short", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: invalidUserID, + sourceID: validSourceID, + valid: true, + }, + wantErr: true, + }, + { + name: "Test 3: anthroveUserID is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: "", + sourceID: validSourceID, + valid: true, + }, + wantErr: true, + }, + { + name: "Test 4: anthroveUserID to short", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: "111", + valid: true, + }, + wantErr: true, + }, + { + name: "Test 5: anthroveUserID is empty", + args: args{ + ctx: ctx, + db: gormDB, + anthroveUserID: validUserID, + sourceID: "", + valid: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := UpdateUserSourceValidation(tt.args.ctx, tt.args.db, tt.args.anthroveUserID, tt.args.sourceID, tt.args.valid); (err != nil) != tt.wantErr { + t.Errorf("UpdateUserSourceValidation() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 39c7a54..6d3dd07 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -151,18 +151,15 @@ func (p *postgresqlConnection) GetSourceByDomain(ctx context.Context, sourceDoma // NEW FUNCTIONS func (p *postgresqlConnection) UpdateUserSourceScrapeTimeInterval(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, scrapeTime models.AnthroveScrapeTimeInterval) error { - //TODO implement me - panic("implement me") + return postgres.UpdateUserSourceScrapeTimeInterval(ctx, p.db, anthroveUserID, sourceID, scrapeTime) } func (p *postgresqlConnection) UpdateUserSourceLastScrapeTime(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, lastScrapeTime models.AnthroveUserLastScrapeTime) error { - //TODO implement me - panic("implement me") + return postgres.UpdateUserSourceLastScrapeTime(ctx, p.db, anthroveUserID, sourceID, lastScrapeTime) } func (p *postgresqlConnection) UpdateUserSourceValidation(ctx context.Context, anthroveUserID models.AnthroveUserID, sourceID models.AnthroveSourceID, valid bool) error { - //TODO implement me - panic("implement me") + return postgres.UpdateUserSourceValidation(ctx, p.db, anthroveUserID, sourceID, valid) } func (p *postgresqlConnection) CreateTagAlias(ctx context.Context, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error { diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index d53f9e2..93534cc 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -5,6 +5,7 @@ import ( "fmt" "reflect" "testing" + "time" "git.dragse.it/anthrove/otter-space-sdk/internal/postgres" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" @@ -2716,3 +2717,359 @@ func Test_postgresqlConnection_DeleteTagGroup(t *testing.T) { }) } } + +func Test_postgresqlConnection_UpdateUserSourceScrapeTimeInterval(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: validSourceID, + }, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.icon", + } + + err = postgres.CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, "e66e6e6e6", "euser") + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + sourceID models.AnthroveSourceID + scrapeTime models.AnthroveScrapeTimeInterval + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: validSourceID, + scrapeTime: 10, + }, + wantErr: false, + }, + { + name: "Test 2: anthroveUserID to short", + args: args{ + ctx: ctx, + anthroveUserID: invalidUserID, + sourceID: validSourceID, + scrapeTime: 10, + }, + wantErr: true, + }, + { + name: "Test 3: anthroveUserID is empty", + args: args{ + ctx: ctx, + anthroveUserID: "", + sourceID: validSourceID, + scrapeTime: 10, + }, + wantErr: true, + }, + { + name: "Test 4: anthroveUserID to short", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: "111", + scrapeTime: 10, + }, + wantErr: true, + }, + { + name: "Test 5: anthroveUserID is empty", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: "", + scrapeTime: 10, + }, + wantErr: true, + }, + { + name: "Test 5: scrapeTime is empty", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: validSourceID, + scrapeTime: 0, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.UpdateUserSourceScrapeTimeInterval(tt.args.ctx, tt.args.anthroveUserID, tt.args.sourceID, tt.args.scrapeTime); (err != nil) != tt.wantErr { + t.Errorf("UpdateUserSourceScrapeTimeInterval() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_UpdateUserSourceLastScrapeTime(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + + validScrapeTime := models.AnthroveUserLastScrapeTime(time.Now()) + inValidScrapeTime := models.AnthroveUserLastScrapeTime{} + + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: validSourceID, + }, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.icon", + } + + err = postgres.CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, "e66e6e6e6", "euser") + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + sourceID models.AnthroveSourceID + lastScrapeTime models.AnthroveUserLastScrapeTime + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: validSourceID, + lastScrapeTime: validScrapeTime, + }, + wantErr: false, + }, + { + name: "Test 2: anthroveUserID to short", + args: args{ + ctx: ctx, + anthroveUserID: invalidUserID, + sourceID: validSourceID, + lastScrapeTime: validScrapeTime, + }, + wantErr: true, + }, + { + name: "Test 3: anthroveUserID is empty", + args: args{ + ctx: ctx, + anthroveUserID: "", + sourceID: validSourceID, + lastScrapeTime: validScrapeTime, + }, + wantErr: true, + }, + { + name: "Test 4: anthroveUserID to short", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: "111", + lastScrapeTime: validScrapeTime, + }, + wantErr: true, + }, + { + name: "Test 5: anthroveUserID is empty", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: "", + lastScrapeTime: validScrapeTime, + }, + wantErr: true, + }, + { + name: "Test 5: scrapeTime is empty", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: validSourceID, + lastScrapeTime: inValidScrapeTime, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.UpdateUserSourceLastScrapeTime(tt.args.ctx, tt.args.anthroveUserID, tt.args.sourceID, tt.args.lastScrapeTime); (err != nil) != tt.wantErr { + t.Errorf("UpdateUserSourceLastScrapeTime() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_UpdateUserSourceValidation(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validUserID := models.AnthroveUserID(fmt.Sprintf("%025s", "User1")) + invalidUserID := models.AnthroveUserID("XXX") + + validSourceID := models.AnthroveSourceID(fmt.Sprintf("%025s", "Source1")) + + source := &models.Source{ + BaseModel: models.BaseModel[models.AnthroveSourceID]{ + ID: validSourceID, + }, + DisplayName: "e621", + Domain: "e621.net", + Icon: "https://e621.icon", + } + + err = postgres.CreateSource(ctx, gormDB, source) + if err != nil { + t.Fatal(err) + } + + err = postgres.CreateUserWithRelationToSource(ctx, gormDB, validUserID, validSourceID, "e66e6e6e6", "euser") + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + anthroveUserID models.AnthroveUserID + sourceID models.AnthroveSourceID + valid bool + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: validSourceID, + valid: true, + }, + wantErr: false, + }, + { + name: "Test 2: anthroveUserID to short", + args: args{ + ctx: ctx, + anthroveUserID: invalidUserID, + sourceID: validSourceID, + valid: true, + }, + wantErr: true, + }, + { + name: "Test 3: anthroveUserID is empty", + args: args{ + ctx: ctx, + anthroveUserID: "", + sourceID: validSourceID, + valid: true, + }, + wantErr: true, + }, + { + name: "Test 4: anthroveUserID to short", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: "111", + valid: true, + }, + wantErr: true, + }, + { + name: "Test 5: anthroveUserID is empty", + args: args{ + ctx: ctx, + anthroveUserID: validUserID, + sourceID: "", + valid: true, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.UpdateUserSourceValidation(tt.args.ctx, tt.args.anthroveUserID, tt.args.sourceID, tt.args.valid); (err != nil) != tt.wantErr { + t.Errorf("UpdateUserSourceValidation() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/error/validation.go b/pkg/error/validation.go index 889ae13..48b8632 100644 --- a/pkg/error/validation.go +++ b/pkg/error/validation.go @@ -3,8 +3,10 @@ package error import "fmt" const ( - AnthroveUserIDIsEmpty = "anthrovePostID cannot be empty" - AnthroveUserIDToShort = "anthrovePostID needs to be 25 characters long" + AnthroveUserIDIsEmpty = "anthrovePostID cannot be empty" + AnthroveUserIDToShort = "anthrovePostID needs to be 25 characters long" + AnthroveSourceIDEmpty = "anthroveSourceID cannot be empty" + AnthroveSourceIDToShort = "anthroveSourceID needs to be 25 characters long" ) type EntityValidationFailed struct { diff --git a/pkg/models/const.go b/pkg/models/const.go index 0e24228..00fc13b 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -1,5 +1,7 @@ package models +import "time" + type AnthroveUserID string type AnthrovePostID string type AnthroveSourceID string @@ -9,7 +11,7 @@ type AnthroveTagGroupName string type AnthroveTagAliasName string type AnthroveTagID string type AnthroveScrapeTimeInterval int -type AnthroveUserLastScrapeTime int +type AnthroveUserLastScrapeTime time.Time type Rating string type TagType string From 3dfb345edc10bc28be6d6ba0fc16fa13804d4f01 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 1 Jul 2024 14:14:17 +0200 Subject: [PATCH 119/124] fix: make sonarqube happy Signed-off-by: SoXX --- internal/postgres/tag.go | 8 ++++---- pkg/error/validation.go | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 4e851e2..405b5a8 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -97,7 +97,7 @@ func CreateTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.Anthro return &otterError.EntityValidationFailed{Reason: "tagAliasName cannot be empty"} } if tagID == "" { - return &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty} } result := db.WithContext(ctx).Create(&models.TagAlias{ @@ -143,7 +143,7 @@ func GetAllTagAliasByTag(ctx context.Context, db *gorm.DB, tagID models.Anthrove var tagAliases []models.TagAlias if tagID == "" { - return nil, &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty} } result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagAliases) @@ -191,7 +191,7 @@ func CreateTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.Anthro return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"} } if tagID == "" { - return &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + return &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty} } result := db.WithContext(ctx).Create(&models.TagGroup{ @@ -237,7 +237,7 @@ func GetAllTagGroupByTag(ctx context.Context, db *gorm.DB, tagID models.Anthrove var tagGroups []models.TagGroup if tagID == "" { - return nil, &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty} } result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagGroups) diff --git a/pkg/error/validation.go b/pkg/error/validation.go index 48b8632..27ec3c4 100644 --- a/pkg/error/validation.go +++ b/pkg/error/validation.go @@ -7,6 +7,7 @@ const ( AnthroveUserIDToShort = "anthrovePostID needs to be 25 characters long" AnthroveSourceIDEmpty = "anthroveSourceID cannot be empty" AnthroveSourceIDToShort = "anthroveSourceID needs to be 25 characters long" + AnthroveTagIDEmpty = "tagID cannot be empty" ) type EntityValidationFailed struct { From 47fda2994ba528a420836de04d26d7b73e73e9a5 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 1 Jul 2024 21:38:09 +0200 Subject: [PATCH 120/124] fix: fixed issues in PR Signed-off-by: SoXX --- internal/postgres/post.go | 2 +- internal/postgres/post_test.go | 6 +++--- pkg/database/postgres.go | 16 ++++++++++++---- pkg/database/postgres_test.go | 4 ++-- pkg/models/api.go | 5 +++++ pkg/models/userFavorite.go | 4 ---- 6 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 pkg/models/api.go diff --git a/internal/postgres/post.go b/internal/postgres/post.go index 3679132..6c08cf3 100644 --- a/internal/postgres/post.go +++ b/internal/postgres/post.go @@ -59,7 +59,7 @@ func GetPostByAnthroveID(ctx context.Context, db *gorm.DB, anthrovePostID models return &post, nil } -func GetPostByURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.Post, error) { +func GetPostBySourceURL(ctx context.Context, db *gorm.DB, sourceURL string) (*models.Post, error) { if sourceURL == "" { return nil, &otterError.EntityValidationFailed{Reason: "sourceURL is not set"} diff --git a/internal/postgres/post_test.go b/internal/postgres/post_test.go index f679eaa..bb525c8 100644 --- a/internal/postgres/post_test.go +++ b/internal/postgres/post_test.go @@ -249,13 +249,13 @@ func TestGetPostBySourceURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GetPostByURL(tt.args.ctx, tt.args.db, tt.args.sourceURL) + got, err := GetPostBySourceURL(tt.args.ctx, tt.args.db, tt.args.sourceURL) if (err != nil) != tt.wantErr { - t.Errorf("GetPostByURL() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetPostBySourceURL() error = %v, wantErr %v", err, tt.wantErr) return } if !checkPost(got, tt.want) { - t.Errorf("GetPostByURL() got = %v, want %v", got, tt.want) + t.Errorf("GetPostBySourceURL() got = %v, want %v", got, tt.want) } }) } diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 6d3dd07..90080c0 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -15,7 +15,7 @@ import ( log "github.com/sirupsen/logrus" gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" - logger2 "gorm.io/gorm/logger" + gormLogger "gorm.io/gorm/logger" ) //go:embed migrations/*.sql @@ -34,6 +34,8 @@ func NewPostgresqlConnection() OtterSpace { func (p *postgresqlConnection) Connect(_ context.Context, config models.DatabaseConfig) error { var localSSL string + var logLevel gormLogger.LogLevel + if config.SSL { localSSL = "require" } else { @@ -45,9 +47,15 @@ func (p *postgresqlConnection) Connect(_ context.Context, config models.Database dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s", config.Endpoint, config.Username, config.Password, config.Database, config.Port, localSSL, config.Timezone) var err error - dbLogger := logger2.New(log2.New(os.Stdout, "\r\n", log2.LstdFlags), logger2.Config{ + if p.debug { + logLevel = gormLogger.Info + } else { + logLevel = gormLogger.Silent + } + + dbLogger := gormLogger.New(log2.New(os.Stdout, "\r\n", log2.LstdFlags), gormLogger.Config{ SlowThreshold: 200 * time.Millisecond, - LogLevel: logger2.Info, + LogLevel: logLevel, IgnoreRecordNotFoundError: true, Colorful: true, }) @@ -105,7 +113,7 @@ func (p *postgresqlConnection) GetPostByAnthroveID(ctx context.Context, anthrove } func (p *postgresqlConnection) GetPostByURL(ctx context.Context, sourceUrl string) (*models.Post, error) { - return postgres.GetPostByURL(ctx, p.db, sourceUrl) + return postgres.GetPostBySourceURL(ctx, p.db, sourceUrl) } func (p *postgresqlConnection) GetPostBySourceID(ctx context.Context, sourceID models.AnthroveSourceID) (*models.Post, error) { diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index 93534cc..41af09f 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -887,11 +887,11 @@ func Test_postgresqlConnection_GetPostByURL(t *testing.T) { } got, err := p.GetPostByURL(tt.args.ctx, tt.args.sourceUrl) if (err != nil) != tt.wantErr { - t.Errorf("GetPostByURL() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetPostBySourceURL() error = %v, wantErr %v", err, tt.wantErr) return } if !checkPost(got, tt.want) { - t.Errorf("GetPostByURL() got = %v, want %v", got, tt.want) + t.Errorf("GetPostBySourceURL() got = %v, want %v", got, tt.want) } }) } diff --git a/pkg/models/api.go b/pkg/models/api.go new file mode 100644 index 0000000..37adbd0 --- /dev/null +++ b/pkg/models/api.go @@ -0,0 +1,5 @@ +package models + +type FavoriteList struct { + Posts []Post `json:"posts,omitempty"` +} diff --git a/pkg/models/userFavorite.go b/pkg/models/userFavorite.go index 3bebe91..028b907 100644 --- a/pkg/models/userFavorite.go +++ b/pkg/models/userFavorite.go @@ -11,7 +11,3 @@ type UserFavorites struct { func (UserFavorites) TableName() string { return "UserFavorites" } - -type FavoriteList struct { - Posts []Post `json:"posts,omitempty"` -} From 1b40c6145a798deb39cd77f82ff41a5170fbea59 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 1 Jul 2024 22:06:36 +0200 Subject: [PATCH 121/124] refactor: changed CreateTag to align with other functions Signed-off-by: SoXX --- internal/postgres/tag.go | 16 +++++++----- internal/postgres/tag_test.go | 48 +++++++++++++++++++---------------- pkg/database/database.go | 3 +++ pkg/database/postgres.go | 14 ++++++++++ pkg/database/postgres_test.go | 18 ++++++------- pkg/database/tag.go | 6 +++++ pkg/models/const.go | 1 + 7 files changed, 69 insertions(+), 37 deletions(-) diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 405b5a8..bc5ccd0 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -10,13 +10,17 @@ import ( "gorm.io/gorm" ) -func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { +func CreateTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName, tagType models.TagType) error { - if tag == nil { - return &otterError.EntityValidationFailed{Reason: "Tag is nil"} + if tagName == "" { + return &otterError.EntityValidationFailed{Reason: "tagName is empty"} } - result := db.WithContext(ctx).Create(tag) + if tagType == "" { + return &otterError.EntityValidationFailed{Reason: "tagType is empty"} + } + + result := db.WithContext(ctx).Create(&models.Tag{Name: string(tagName), Type: tagType}) if result.Error != nil { if errors.Is(result.Error, gorm.ErrDuplicatedKey) { return &otterError.EntityAlreadyExists{} @@ -29,8 +33,8 @@ func CreateTag(ctx context.Context, db *gorm.DB, tag *models.Tag) error { } log.WithFields(log.Fields{ - "tag_name": tag.Name, - "tag_type": tag.Type, + "tag_name": tagName, + "tag_type": tagType, }).Trace("database: created tag node") return nil diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index adbc867..5a30658 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -128,7 +128,7 @@ func TestGetTags(t *testing.T) { } for _, tag := range tags { - err = CreateTag(ctx, gormDB, &tag) + err = CreateTag(ctx, gormDB, models.AnthroveTagName(tag.Name), tag.Type) if err != nil { t.Fatal(err) } @@ -202,9 +202,10 @@ func TestCreateTag(t *testing.T) { // Test type args struct { - ctx context.Context - db *gorm.DB - tag *models.Tag + ctx context.Context + db *gorm.DB + tagName models.AnthroveTagName + tagType models.TagType } tests := []struct { name string @@ -214,34 +215,37 @@ func TestCreateTag(t *testing.T) { { name: "Test 1: Valid Tag", args: args{ - ctx: ctx, - db: gormDB, - tag: &validTag, + ctx: ctx, + db: gormDB, + tagName: models.AnthroveTagName(validTag.Name), + tagType: validTag.Type, }, wantErr: false, }, { name: "Test 2: Duplicate Tag", args: args{ - ctx: ctx, - db: gormDB, - tag: &validTag, + ctx: ctx, + db: gormDB, + tagName: models.AnthroveTagName(validTag.Name), + tagType: validTag.Type, }, wantErr: true, }, { name: "Test 3: Invalid Tag", args: args{ - ctx: ctx, - db: gormDB, - tag: &invalidTag, + ctx: ctx, + db: gormDB, + tagName: models.AnthroveTagName(invalidTag.Name), + tagType: invalidTag.Type, }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CreateTag(tt.args.ctx, tt.args.db, tt.args.tag); (err != nil) != tt.wantErr { + if err := CreateTag(tt.args.ctx, tt.args.db, tt.args.tagName, tt.args.tagType); (err != nil) != tt.wantErr { t.Errorf("CreateTag() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -269,7 +273,7 @@ func TestCreateTagAlias(t *testing.T) { Type: models.Character, } - err = CreateTag(ctx, gormDB, validTag) + err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -379,7 +383,7 @@ func TestGetAllTagAlias(t *testing.T) { }, } - err = CreateTag(ctx, gormDB, validTag) + err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -456,7 +460,7 @@ func TestGetAllTagAliasByTag(t *testing.T) { }, } - err = CreateTag(ctx, gormDB, validTag) + err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -540,7 +544,7 @@ func TestDeleteTagAlias(t *testing.T) { Type: models.Character, } - err = CreateTag(ctx, gormDB, validTag) + err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -618,7 +622,7 @@ func TestCreateTagGroup(t *testing.T) { Type: models.Character, } - err = CreateTag(ctx, gormDB, validTag) + err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -728,7 +732,7 @@ func TestGetAllTagGroup(t *testing.T) { }, } - err = CreateTag(ctx, gormDB, validTag) + err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -805,7 +809,7 @@ func TestGetAllTagGroupByTag(t *testing.T) { }, } - err = CreateTag(ctx, gormDB, validTag) + err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -889,7 +893,7 @@ func TestDeleteTagGroup(t *testing.T) { Type: models.Character, } - err = CreateTag(ctx, gormDB, validTag) + err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } diff --git a/pkg/database/database.go b/pkg/database/database.go index 0bce2bf..bc19286 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -19,6 +19,9 @@ type OtterSpace interface { // Source contains all function that are needed to manage the Source Source + // Tag contains all functions that are used to manage Tag + Tag + // TagAlias contains all function that are needed to manage the TagAlias TagAlias diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 90080c0..4e1b02b 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -202,6 +202,20 @@ func (p *postgresqlConnection) DeleteTagGroup(ctx context.Context, tagGroupName return postgres.DeleteTagGroup(ctx, p.db, tagGroupName) } +func (p *postgresqlConnection) CreateTag(ctx context.Context, tagName models.AnthroveTagName, tagType models.TagType) error { + return postgres.CreateTag(ctx, p.db, tagName, tagType) +} + +func (p *postgresqlConnection) GetAllTagByTagType(ctx context.Context, tagType models.TagType) ([]models.Tag, error) { + //TODO implement me + panic("implement me") +} + +func (p *postgresqlConnection) DeleteTag(ctx context.Context, tagName models.AnthroveTagName) error { + //TODO implement me + panic("implement me") +} + // HELPER func (p *postgresqlConnection) migrateDatabase(dbPool *gorm.DB) error { diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index 41af09f..3a46606 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -1704,7 +1704,7 @@ func Test_postgresqlConnection_GetAllTags(t *testing.T) { } for _, tag := range tags { - err = postgres.CreateTag(ctx, gormDB, &tag) + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(tag.Name), tag.Type) if err != nil { t.Fatal(err) } @@ -2043,7 +2043,7 @@ func Test_postgresqlConnection_CreateTagAlias(t *testing.T) { Type: models.Character, } - err = postgres.CreateTag(ctx, gormDB, validTag) + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -2151,7 +2151,7 @@ func Test_postgresqlConnection_GetAllTagAlias(t *testing.T) { }, } - err = postgres.CreateTag(ctx, gormDB, validTag) + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -2228,7 +2228,7 @@ func Test_postgresqlConnection_GetAllTagAliasByTag(t *testing.T) { }, } - err = postgres.CreateTag(ctx, gormDB, validTag) + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -2312,7 +2312,7 @@ func Test_postgresqlConnection_DeleteTagAlias(t *testing.T) { Type: models.Character, } - err = postgres.CreateTag(ctx, gormDB, validTag) + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -2392,7 +2392,7 @@ func Test_postgresqlConnection_CreateTagGroup(t *testing.T) { Type: models.Character, } - err = postgres.CreateTag(ctx, gormDB, validTag) + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -2500,7 +2500,7 @@ func Test_postgresqlConnection_GetAllTagGroup(t *testing.T) { }, } - err = postgres.CreateTag(ctx, gormDB, validTag) + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -2577,7 +2577,7 @@ func Test_postgresqlConnection_GetAllTagGroupByTag(t *testing.T) { }, } - err = postgres.CreateTag(ctx, gormDB, validTag) + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } @@ -2661,7 +2661,7 @@ func Test_postgresqlConnection_DeleteTagGroup(t *testing.T) { Type: models.Character, } - err = postgres.CreateTag(ctx, gormDB, validTag) + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) if err != nil { t.Fatal(err) } diff --git a/pkg/database/tag.go b/pkg/database/tag.go index eb0f4a5..ecaf3d5 100644 --- a/pkg/database/tag.go +++ b/pkg/database/tag.go @@ -7,6 +7,12 @@ import ( ) type Tag interface { + CreateTag(ctx context.Context, tagName models.AnthroveTagName, tagType models.TagType) error + // GetAllTags retrieves all tags. GetAllTags(ctx context.Context) ([]models.Tag, error) + + GetAllTagByTagType(ctx context.Context, tagType models.TagType) ([]models.Tag, error) + + DeleteTag(ctx context.Context, tagName models.AnthroveTagName) error } diff --git a/pkg/models/const.go b/pkg/models/const.go index 00fc13b..7e84b0c 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -12,6 +12,7 @@ type AnthroveTagAliasName string type AnthroveTagID string type AnthroveScrapeTimeInterval int type AnthroveUserLastScrapeTime time.Time +type AnthroveTagName string type Rating string type TagType string From a842d64f1cb2f39529f64bc5fd6ffde0fabc1b8b Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 1 Jul 2024 22:15:43 +0200 Subject: [PATCH 122/124] refactor: added deletion of tags Signed-off-by: SoXX --- internal/postgres/tag.go | 26 ++++++++++++- internal/postgres/tag_test.go | 70 +++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 3 +- pkg/database/postgres_test.go | 70 +++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 4 deletions(-) diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index bc5ccd0..f810266 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -13,11 +13,11 @@ import ( func CreateTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName, tagType models.TagType) error { if tagName == "" { - return &otterError.EntityValidationFailed{Reason: "tagName is empty"} + return &otterError.EntityValidationFailed{Reason: "tagName cannot be empty"} } if tagType == "" { - return &otterError.EntityValidationFailed{Reason: "tagType is empty"} + return &otterError.EntityValidationFailed{Reason: "tagType cannot be empty"} } result := db.WithContext(ctx).Create(&models.Tag{Name: string(tagName), Type: tagType}) @@ -40,6 +40,28 @@ func CreateTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName, return nil } +func DeleteTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName) error { + + if tagName == "" { + return &otterError.EntityValidationFailed{Reason: "tagName cannot be empty"} + } + + result := db.WithContext(ctx).Delete(&models.Tag{Name: string(tagName)}) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return &otterError.NoDataFound{} + } + return result.Error + } + + log.WithFields(log.Fields{ + "tag_name": tagName, + }).Trace("database: deleted tag") + + return nil +} + func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, tag *models.Tag) error { if anthrovePostID == "" { diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index 5a30658..88eabcd 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -949,3 +949,73 @@ func TestDeleteTagGroup(t *testing.T) { }) } } + +func TestDeleteTag(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagName models.AnthroveTagName + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid TagName", + args: args{ + ctx: ctx, + db: gormDB, + tagName: models.AnthroveTagName(validTagID), + }, + wantErr: false, + }, + { + name: "Test 2: Invalid TagName", + args: args{ + ctx: ctx, + db: gormDB, + tagName: models.AnthroveTagName("aaa"), + }, + wantErr: false, + }, + { + name: "Test 3: No TagName", + args: args{ + ctx: ctx, + db: gormDB, + tagName: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := DeleteTag(tt.args.ctx, tt.args.db, tt.args.tagName); (err != nil) != tt.wantErr { + t.Errorf("DeleteTag() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 4e1b02b..0acb71e 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -212,8 +212,7 @@ func (p *postgresqlConnection) GetAllTagByTagType(ctx context.Context, tagType m } func (p *postgresqlConnection) DeleteTag(ctx context.Context, tagName models.AnthroveTagName) error { - //TODO implement me - panic("implement me") + return postgres.DeleteTag(ctx, p.db, tagName) } // HELPER diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index 3a46606..88b10ba 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -3073,3 +3073,73 @@ func Test_postgresqlConnection_UpdateUserSourceValidation(t *testing.T) { }) } } + +func Test_postgresqlConnection_DeleteTag(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(validTag.Name), validTag.Type) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + tagName models.AnthroveTagName + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid TagName", + args: args{ + ctx: ctx, + tagName: models.AnthroveTagName(validTagID), + }, + wantErr: false, + }, + { + name: "Test 2: Invalid TagName", + args: args{ + ctx: ctx, + tagName: models.AnthroveTagName("aaa"), + }, + wantErr: false, + }, + { + name: "Test 3: No TagName", + args: args{ + ctx: ctx, + tagName: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.DeleteTag(tt.args.ctx, tt.args.tagName); (err != nil) != tt.wantErr { + t.Errorf("DeleteTag() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 2d4102be6ab0e5599bfdaf113406d39cba21c704 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 1 Jul 2024 22:29:37 +0200 Subject: [PATCH 123/124] refactor: added getting of tag by specific type Signed-off-by: SoXX --- internal/postgres/tag.go | 23 +++++++++ internal/postgres/tag_test.go | 94 +++++++++++++++++++++++++++++++++++ pkg/database/postgres.go | 5 +- pkg/database/postgres_test.go | 94 +++++++++++++++++++++++++++++++++++ pkg/database/tag.go | 2 +- 5 files changed, 214 insertions(+), 4 deletions(-) diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index f810266..6b963f7 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -62,6 +62,29 @@ func DeleteTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName) return nil } +func GetAllTagByTagsType(ctx context.Context, db *gorm.DB, tagType models.TagType) ([]models.Tag, error) { + var tags []models.Tag + + if tagType == "" { + return nil, &otterError.EntityValidationFailed{Reason: "tagType cannot be empty"} + } + + result := db.WithContext(ctx).Find(&tags).Where("tag_type = ?", tagType) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &otterError.NoDataFound{} + } + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tags_length": len(tags), + }).Trace("database: got tag") + + return tags, nil +} + func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, tag *models.Tag) error { if anthrovePostID == "" { diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index 88eabcd..a976bd4 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -1019,3 +1019,97 @@ func TestDeleteTag(t *testing.T) { }) } } + +func TestGetAllTagByTagType(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validTags := []models.Tag{ + { + Name: "JayTheFerret", + Type: models.Character, + }, + { + Name: "SoXX", + Type: models.Character, + }, + { + Name: "Alphyron", + Type: models.Character, + }, + { + Name: "Dragon", + Type: models.Species, + }, + } + + for _, tag := range validTags { + err = CreateTag(ctx, gormDB, models.AnthroveTagName(tag.Name), tag.Type) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagType models.TagType + } + tests := []struct { + name string + args args + want []models.Tag + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + db: gormDB, + tagType: models.Character, + }, + want: validTags, + wantErr: false, + }, + { + name: "Test 2: invalid Tag Type", + args: args{ + ctx: ctx, + db: gormDB, + tagType: "aa", + }, + want: validTags, + wantErr: false, + }, + { + name: "Test 3: No Tag Type", + args: args{ + ctx: ctx, + db: gormDB, + tagType: "", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllTagByTagsType(tt.args.ctx, tt.args.db, tt.args.tagType) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagByTagsType() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !checkTag(got, tt.want) { + t.Errorf("GetAllTagByTagsType() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 0acb71e..2692907 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -206,9 +206,8 @@ func (p *postgresqlConnection) CreateTag(ctx context.Context, tagName models.Ant return postgres.CreateTag(ctx, p.db, tagName, tagType) } -func (p *postgresqlConnection) GetAllTagByTagType(ctx context.Context, tagType models.TagType) ([]models.Tag, error) { - //TODO implement me - panic("implement me") +func (p *postgresqlConnection) GetAllTagsByTagType(ctx context.Context, tagType models.TagType) ([]models.Tag, error) { + return postgres.GetAllTagByTagsType(ctx, p.db, tagType) } func (p *postgresqlConnection) DeleteTag(ctx context.Context, tagName models.AnthroveTagName) error { diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index 88b10ba..f00602e 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -3143,3 +3143,97 @@ func Test_postgresqlConnection_DeleteTag(t *testing.T) { }) } } + +func Test_postgresqlConnection_GetAllTagsByTagType(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validTags := []models.Tag{ + { + Name: "JayTheFerret", + Type: models.Character, + }, + { + Name: "SoXX", + Type: models.Character, + }, + { + Name: "Alphyron", + Type: models.Character, + }, + { + Name: "Dragon", + Type: models.Species, + }, + } + + for _, tag := range validTags { + err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(tag.Name), tag.Type) + if err != nil { + t.Fatal(err) + } + } + + // Test + type args struct { + ctx context.Context + tagType models.TagType + } + tests := []struct { + name string + args args + want []models.Tag + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + tagType: models.Character, + }, + want: validTags, + wantErr: false, + }, + { + name: "Test 2: invalid Tag Type", + args: args{ + ctx: ctx, + tagType: "aa", + }, + want: validTags, + wantErr: false, + }, + { + name: "Test 3: No Tag Type", + args: args{ + ctx: ctx, + tagType: "", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllTagsByTagType(tt.args.ctx, tt.args.tagType) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagsByTagType() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagsByTagType() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/database/tag.go b/pkg/database/tag.go index ecaf3d5..44fa553 100644 --- a/pkg/database/tag.go +++ b/pkg/database/tag.go @@ -12,7 +12,7 @@ type Tag interface { // GetAllTags retrieves all tags. GetAllTags(ctx context.Context) ([]models.Tag, error) - GetAllTagByTagType(ctx context.Context, tagType models.TagType) ([]models.Tag, error) + GetAllTagsByTagType(ctx context.Context, tagType models.TagType) ([]models.Tag, error) DeleteTag(ctx context.Context, tagName models.AnthroveTagName) error } From 768203ebd7ec5ab7c3b89676c2a2c5dd2c460bd0 Mon Sep 17 00:00:00 2001 From: SoXX Date: Mon, 1 Jul 2024 22:40:53 +0200 Subject: [PATCH 124/124] fix: fixed function to work properly Signed-off-by: SoXX --- internal/postgres/tag.go | 2 +- internal/postgres/tag_test.go | 17 ++++++++++++++++- pkg/database/postgres_test.go | 17 ++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 6b963f7..7ca240c 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -69,7 +69,7 @@ func GetAllTagByTagsType(ctx context.Context, db *gorm.DB, tagType models.TagTyp return nil, &otterError.EntityValidationFailed{Reason: "tagType cannot be empty"} } - result := db.WithContext(ctx).Find(&tags).Where("tag_type = ?", tagType) + result := db.WithContext(ctx).Model(&models.Tag{}).Where("tag_type = ?", tagType).Scan(&tags) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index a976bd4..ab15604 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -1050,6 +1050,21 @@ func TestGetAllTagByTagType(t *testing.T) { }, } + expectetResult := []models.Tag{ + { + Name: "JayTheFerret", + Type: models.Character, + }, + { + Name: "SoXX", + Type: models.Character, + }, + { + Name: "Alphyron", + Type: models.Character, + }, + } + for _, tag := range validTags { err = CreateTag(ctx, gormDB, models.AnthroveTagName(tag.Name), tag.Type) if err != nil { @@ -1076,7 +1091,7 @@ func TestGetAllTagByTagType(t *testing.T) { db: gormDB, tagType: models.Character, }, - want: validTags, + want: expectetResult, wantErr: false, }, { diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index f00602e..56e2036 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -3174,6 +3174,21 @@ func Test_postgresqlConnection_GetAllTagsByTagType(t *testing.T) { }, } + expectetResult := []models.Tag{ + { + Name: "JayTheFerret", + Type: models.Character, + }, + { + Name: "SoXX", + Type: models.Character, + }, + { + Name: "Alphyron", + Type: models.Character, + }, + } + for _, tag := range validTags { err = postgres.CreateTag(ctx, gormDB, models.AnthroveTagName(tag.Name), tag.Type) if err != nil { @@ -3198,7 +3213,7 @@ func Test_postgresqlConnection_GetAllTagsByTagType(t *testing.T) { ctx: ctx, tagType: models.Character, }, - want: validTags, + want: expectetResult, wantErr: false, }, {