diff --git a/apps/db-adapter/internal/api/person_and_relationship.go b/apps/db-adapter/internal/api/person_and_relationship.go index 88ddaf8..a42c602 100644 --- a/apps/db-adapter/internal/api/person_and_relationship.go +++ b/apps/db-adapter/internal/api/person_and_relationship.go @@ -18,50 +18,90 @@ func (srv *server) CreatePersonAndRelationship(c *gin.Context, id int, params ap return } - ctx, cancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout) - defer cancel() - - session := srv.db.NewSession(ctx, neo4j.SessionConfig{}) + session := srv.db.NewSession(c.Request.Context(), neo4j.SessionConfig{}) defer closeSession(c.Request.Context(), session, srv.dbOpTimeout) - qctx, qCancel := context.WithTimeout(ctx, srv.dbOpTimeout) - defer qCancel() - - res, err := session.ExecuteWrite(qctx, memgraph.CreatePerson(qctx, &api.PersonProperties{ - FirstName: &requestBody.Person.FirstName, - LastName: &requestBody.Person.LastName, - Born: &requestBody.Person.Born, - MothersFirstName: &requestBody.Person.MothersFirstName, - MothersLastName: &requestBody.Person.MothersLastName, - Limit: &requestBody.Person.Limit, - })) + trs, err := session.BeginTransaction(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + + return + } + defer func() { + trs.Commit(c.Request.Context()) + trs.Close(c.Request.Context()) + }() + + qctx, qCancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) + defer qCancel() + res, err := trs.Run(qctx, memgraph.CreatePersonCypherQuery, map[string]any{ + "Person": requestBody.Person, + }) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + return } - resMap, ok := res.(map[string]any) + singleRes, err := res.Single(qctx) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + + return + } + personID, ok := singleRes.Get("id") if !ok { - c.JSON(http.StatusInternalServerError, gin.H{"msg": "unexpected result type"}) + c.JSON(http.StatusInternalServerError, gin.H{"msg": "Person ID not found in response"}) return } - relCtx, relCCancel := context.WithTimeout(ctx, srv.dbOpTimeout) + actx, acancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout) + defer acancel() + _, aErr := trs.Run(actx, memgraph.CreateAdminRelationshipCypherQuery, map[string]any{ + "id2": personID.(int), + "id1": params.XUserID, + }) + if aErr != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": aErr.Error()}) + + return + } + + relCtx, relCCancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout) defer relCCancel() - personID := resMap["id"].(int) var relationShipResultRaw any var relationshipError error switch *requestBody.Type { case api.CreatePersonAndRelationshipJSONBodyTypeChild: - relationShipResultRaw, relationshipError = session.ExecuteRead(relCtx, memgraph.CreateChildParentRelationship(qctx, personID, id)) + relationShipResultRaw, relationshipError = trs.Run(relCtx, memgraph.CreateChildParentRelationshipCypherQuery, map[string]any{ + "childId": personID.(int), + "parentId": id, + "childRelationship": requestBody.Relationship, + "parentRelationship": requestBody.Relationship, + }) case api.CreatePersonAndRelationshipJSONBodyTypeParent: - relationShipResultRaw, relationshipError = session.ExecuteRead(relCtx, memgraph.CreateChildParentRelationship(qctx, id, personID)) + relationShipResultRaw, relationshipError = trs.Run(relCtx, memgraph.CreateChildParentRelationshipCypherQuery, map[string]any{ + "childId": id, + "parentId": personID.(int), + "childRelationship": requestBody.Relationship, + "parentRelationship": requestBody.Relationship, + }) case api.CreatePersonAndRelationshipJSONBodyTypeSibling: - relationShipResultRaw, relationshipError = session.ExecuteRead(relCtx, memgraph.CreateSiblingRelationship(qctx, personID, id)) + relationShipResultRaw, relationshipError = trs.Run(relCtx, memgraph.CreateSiblingRelationshipCypherQuery, map[string]any{ + "id1": id, + "id2": personID.(int), + "Relationship1": requestBody.Relationship, + "Relationship2": requestBody.Relationship, + }) case api.CreatePersonAndRelationshipJSONBodyTypeSpouse: - relationShipResultRaw, relationshipError = session.ExecuteRead(relCtx, memgraph.CreateSpouseRelationship(qctx, personID, id)) + relationShipResultRaw, relationshipError = trs.Run(relCtx, memgraph.CreateSpouseRelationshipCypherQuery, map[string]any{ + "id1": personID.(int), + "id2": id, + "Relationship1": requestBody.Relationship, + "Relationship2": requestBody.Relationship, + }) default: c.JSON(http.StatusBadRequest, gin.H{"msg": "invalid relationship type"}) } @@ -74,5 +114,5 @@ func (srv *server) CreatePersonAndRelationship(c *gin.Context, id int, params ap c.JSON(http.StatusOK, struct { Person any `json:"person"` Rel any `json:"relationship"` - }{Person: resMap, Rel: relationShipResultRaw}) + }{Person: singleRes, Rel: relationShipResultRaw}) } diff --git a/apps/db-adapter/internal/api/person_family_tree.go b/apps/db-adapter/internal/api/person_family_tree.go index 4a0f130..12b2bd5 100644 --- a/apps/db-adapter/internal/api/person_family_tree.go +++ b/apps/db-adapter/internal/api/person_family_tree.go @@ -1,5 +1,43 @@ package api -import "github.com/gin-gonic/gin" +import ( + "context" + "net/http" -func (srv *server) GetFamilyTreeById(c *gin.Context, id int) {} + "github.com/gin-gonic/gin" + "github.com/neo4j/neo4j-go-driver/v5/neo4j" + "github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/internal/memgraph" + "github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api" +) + +func (srv *server) GetFamilyTreeById(c *gin.Context, params api.GetFamilyTreeByIdParams) { + ctx, cancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) + defer cancel() + session := srv.db.NewSession(ctx, neo4j.SessionConfig{}) + + qctx, qCancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) + defer qCancel() + res, err := session.ExecuteRead(qctx, memgraph.GetFamilyTreeById(qctx, params.XUserID)) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + return + } + + c.JSON(http.StatusOK, res) +} + +func (srv *server) GetFamilyTreeWithSpousesById(c *gin.Context, params api.GetFamilyTreeWithSpousesByIdParams) { + ctx, cancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) + defer cancel() + session := srv.db.NewSession(ctx, neo4j.SessionConfig{}) + + qctx, qCancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) + defer qCancel() + res, err := session.ExecuteRead(qctx, memgraph.GetFamilyTreeWithSpousesById(qctx, params.XUserID)) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + return + } + + c.JSON(http.StatusOK, res) +} diff --git a/apps/db-adapter/internal/api/person_recipes.go b/apps/db-adapter/internal/api/person_recipes.go index b3faa11..94dd6fb 100644 --- a/apps/db-adapter/internal/api/person_recipes.go +++ b/apps/db-adapter/internal/api/person_recipes.go @@ -1,9 +1,12 @@ package api import ( + "net/http" + "github.com/gin-gonic/gin" "github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api" ) func (srv *server) GetRecipesByPersonId(c *gin.Context, id int, params api.GetRecipesByPersonIdParams) { + c.JSON(http.StatusServiceUnavailable, gin.H{"msg": "not implemented"}) } diff --git a/apps/db-adapter/internal/api/recipe_relationship.go b/apps/db-adapter/internal/api/recipe_relationship.go index efa9623..5399f69 100644 --- a/apps/db-adapter/internal/api/recipe_relationship.go +++ b/apps/db-adapter/internal/api/recipe_relationship.go @@ -1,12 +1,16 @@ package api import ( + "net/http" + "github.com/gin-gonic/gin" "github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api" ) func (srv *server) DeleteRecipeRelationship(c *gin.Context, recipeId int, params api.DeleteRecipeRelationshipParams) { + c.JSON(http.StatusServiceUnavailable, gin.H{"msg": "not implemented"}) } func (srv *server) CreateRecipeRelationship(c *gin.Context, recipeId int, params api.CreateRecipeRelationshipParams) { + c.JSON(http.StatusServiceUnavailable, gin.H{"msg": "not implemented"}) } diff --git a/apps/db-adapter/internal/api/recipes.go b/apps/db-adapter/internal/api/recipes.go index a771877..0481774 100644 --- a/apps/db-adapter/internal/api/recipes.go +++ b/apps/db-adapter/internal/api/recipes.go @@ -1,12 +1,20 @@ package api import ( + "net/http" + "github.com/gin-gonic/gin" "github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api" ) -func (srv *server) SoftDeleteRecipe(c *gin.Context, id int, params api.SoftDeleteRecipeParams) {} +func (srv *server) SoftDeleteRecipe(c *gin.Context, id int, params api.SoftDeleteRecipeParams) { + c.JSON(http.StatusServiceUnavailable, gin.H{"msg": "not implemented"}) +} -func (srv *server) UpdateRecipe(c *gin.Context, id int, params api.UpdateRecipeParams) {} +func (srv *server) UpdateRecipe(c *gin.Context, id int, params api.UpdateRecipeParams) { + c.JSON(http.StatusServiceUnavailable, gin.H{"msg": "not implemented"}) +} -func (srv *server) HardDeleteRecipe(c *gin.Context, id int, params api.HardDeleteRecipeParams) {} +func (srv *server) HardDeleteRecipe(c *gin.Context, id int, params api.HardDeleteRecipeParams) { + c.JSON(http.StatusServiceUnavailable, gin.H{"msg": "not implemented"}) +} diff --git a/apps/db-adapter/internal/api/relationship.go b/apps/db-adapter/internal/api/relationship.go index b743b5e..7dad592 100644 --- a/apps/db-adapter/internal/api/relationship.go +++ b/apps/db-adapter/internal/api/relationship.go @@ -41,13 +41,13 @@ func (srv *server) CreateRelationship(c *gin.Context, params api.CreateRelations var relationshipError error switch *relationship.Type { case api.CreateRelationshipJSONBodyTypeChild: - relationShipResultRaw, relationshipError = session.ExecuteWrite(qctx, memgraph.CreateChildParentRelationship(qctx, *relationship.Id1, *relationship.Id2)) + relationShipResultRaw, relationshipError = session.ExecuteWrite(qctx, memgraph.CreateChildParentRelationship(qctx, *relationship.Id1, *relationship.Id2, *relationship.Relationship)) case api.CreateRelationshipJSONBodyTypeParent: - relationShipResultRaw, relationshipError = session.ExecuteWrite(qctx, memgraph.CreateChildParentRelationship(qctx, *relationship.Id1, *relationship.Id2)) + relationShipResultRaw, relationshipError = session.ExecuteWrite(qctx, memgraph.CreateChildParentRelationship(qctx, *relationship.Id1, *relationship.Id2, *relationship.Relationship)) case api.CreateRelationshipJSONBodyTypeSibling: - relationShipResultRaw, relationshipError = session.ExecuteWrite(qctx, memgraph.CreateSiblingRelationship(qctx, *relationship.Id1, *relationship.Id2)) + relationShipResultRaw, relationshipError = session.ExecuteWrite(qctx, memgraph.CreateSiblingRelationship(qctx, *relationship.Id1, *relationship.Id2, *relationship.Relationship)) case api.CreateRelationshipJSONBodyTypeSpouse: - relationShipResultRaw, relationshipError = session.ExecuteWrite(qctx, memgraph.CreateSpouseRelationship(qctx, *relationship.Id1, *relationship.Id2)) + relationShipResultRaw, relationshipError = session.ExecuteWrite(qctx, memgraph.CreateSpouseRelationship(qctx, *relationship.Id1, *relationship.Id2, *relationship.Relationship)) default: c.JSON(http.StatusBadRequest, gin.H{"msg": "invalid relationship type"}) } @@ -60,6 +60,40 @@ func (srv *server) CreateRelationship(c *gin.Context, params api.CreateRelations c.JSON(http.StatusOK, relationShipResultRaw) } +func (srv *server) UpdateRelationship(c *gin.Context, id1, id2 int, params api.UpdateRelationshipParams) { + var relationship *api.UpdateRelationshipJSONBody + if err := c.ShouldBindJSON(&relationship); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"msg": err.Error()}) + + return + } + + session := srv.db.NewSession(c.Request.Context(), neo4j.SessionConfig{}) + defer closeSession(c.Request.Context(), session, srv.dbOpTimeout) + + actx, aCancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout) + defer aCancel() + + if err := auth.CouldManagePersonUnknownAdmin(actx, session, *relationship.Id1, params.XUserID); err != nil { + if err := auth.CouldManagePersonUnknownAdmin(actx, session, *relationship.Id1, params.XUserID); err != nil { + c.JSON(http.StatusUnauthorized, gin.H{"msg": fmt.Sprint("User does not have access to this person", err.Error())}) + + return + } + } + + qctx, qCancel := context.WithTimeout(c.Request.Context(), srv.dbOpTimeout) + defer qCancel() + res, err := session.ExecuteWrite(qctx, memgraph.UpdateRelationship(qctx, id1, id2, *relationship.Relationship)) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + + return + } + + c.JSON(http.StatusOK, res) +} + func (srv *server) GetRelationship(c *gin.Context, id1 int, id2 int, params api.GetRelationshipParams) { session := srv.db.NewSession(c.Request.Context(), neo4j.SessionConfig{}) defer closeSession(c.Request.Context(), session, srv.dbOpTimeout)