From 723c679ad0c0327bad05212ac0d239bb5d1bdfe4 Mon Sep 17 00:00:00 2001 From: Vargha Csongor Date: Fri, 28 Mar 2025 22:15:12 +0100 Subject: [PATCH] implement google queries --- apps/db-adapter/internal/api/person.go | 62 ++++++++++++++++- apps/db-adapter/internal/api/person_google.go | 69 ++++++++++++++++++- apps/db-adapter/internal/memgraph/person.go | 44 ++++++++++++ .../internal/memgraph/person_google.go | 45 ++++++++++++ apps/db-adapter/internal/memgraph/queries.go | 15 ++++ .../update_person_by_invite_code.cypher | 4 ++ 6 files changed, 235 insertions(+), 4 deletions(-) create mode 100644 apps/db-adapter/internal/memgraph/person.go create mode 100644 apps/db-adapter/internal/memgraph/person_google.go create mode 100644 apps/db-adapter/internal/memgraph/queries/update_person_by_invite_code.cypher diff --git a/apps/db-adapter/internal/api/person.go b/apps/db-adapter/internal/api/person.go index 5317576..cdcb17c 100644 --- a/apps/db-adapter/internal/api/person.go +++ b/apps/db-adapter/internal/api/person.go @@ -1,11 +1,71 @@ package api import ( + "context" + "net/http" + "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) CreatePerson(c *gin.Context) {} +func (srv *server) CreatePerson(c *gin.Context, params api.CreatePersonParams) { + var person *api.PersonProperties + if err := c.ShouldBindJSON(&person); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"msg": err.Error()}) + + return + } + + adminList := []struct { + Id *int "json:\"id,omitempty\"" + Name *string "json:\"name,omitempty\"" + }{ + {Id: ¶ms.XUserID, Name: ¶ms.XUserName}, + } + person.AllowAdminAccess = &adminList + + 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.CreatePerson(qctx, person)) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + + return + } + + c.JSON(http.StatusOK, res) +} + +func (srv *server) GetPersonById(c *gin.Context, id int, params api.GetPersonByIdParams) { + ctx, cancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) + defer cancel() + session := srv.db.NewSession(ctx, neo4j.SessionConfig{}) + + actx, acancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) + defer acancel() + if !userWithIdHasAccessToGivenPerson(actx, session, params.XUserID, id) { + c.JSON(http.StatusUnauthorized, gin.H{"msg": "User does not have access to this person"}) + + return + } + + qctx, qCancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) + defer qCancel() + res, err := session.ExecuteRead(qctx, memgraph.GetPersonById(qctx, id)) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + + return + } + + c.JSON(http.StatusOK, res) +} func (srv *server) SoftDeletePerson(c *gin.Context, id int, params api.SoftDeletePersonParams) {} diff --git a/apps/db-adapter/internal/api/person_google.go b/apps/db-adapter/internal/api/person_google.go index 2b028dd..2bbd5f3 100644 --- a/apps/db-adapter/internal/api/person_google.go +++ b/apps/db-adapter/internal/api/person_google.go @@ -2,18 +2,81 @@ package api import ( "context" + "net/http" "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) GetPersonByGoogleId(c *gin.Context, googleId string) { ctx, cancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) defer cancel() session := srv.db.NewSession(ctx, neo4j.SessionConfig{}) - session.ExecuteRead() + + qctx, qCancel := context.WithTimeout(context.Background(), srv.dbOpTimeout) + defer qCancel() + res, err := session.ExecuteRead(qctx, memgraph.GetPersonByGoogleId(qctx, googleId)) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + return + } + + c.JSON(http.StatusOK, res) } -func (srv *server) CreatePersonByGoogleIdAndInviteCode(c *gin.Context, googleId string) {} +func (srv *server) CreatePersonByGoogleIdAndInviteCode(c *gin.Context, googleId string) { + var person struct { + InviteCode string `json:"invite_code"` + Props *api.PersonProperties `json:"person"` + } + if err := c.ShouldBindJSON(&person); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"msg": err.Error()}) -func (srv *server) CreatePersonByGoogleId(c *gin.Context, googleId string) {} + return + } + + emptyString := "" + person.Props.InviteCode = &emptyString + + 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.UpdatePersonByInviteCode(qctx, person.InviteCode, person.Props)) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()}) + + return + } + + c.JSON(http.StatusOK, res) +} + +func (srv *server) CreatePersonByGoogleId(c *gin.Context, googleId string) { + var person *api.PersonProperties + if err := c.ShouldBindJSON(&person); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"msg": err.Error()}) + + return + } + person.GoogleId = &googleId // just making sure :) + + 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.CreatePerson(qctx, person)) + 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/memgraph/person.go b/apps/db-adapter/internal/memgraph/person.go new file mode 100644 index 0000000..c3c0f54 --- /dev/null +++ b/apps/db-adapter/internal/memgraph/person.go @@ -0,0 +1,44 @@ +package memgraph + +import ( + "context" + + "github.com/neo4j/neo4j-go-driver/v5/neo4j" + "github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api" +) + +func CreatePerson(ctx context.Context, Person *api.PersonProperties) neo4j.ManagedTransactionWork { + return func(tx neo4j.ManagedTransaction) (any, error) { + result, err := tx.Run(ctx, CreatePersonCypherQuery, map[string]any{ + "Person": *Person, + }) + if err != nil { + return nil, err + } + + record, err := result.Single(ctx) + if err != nil { + return nil, err + } + + return record.AsMap(), nil + } +} + +func GetPersonById(ctx context.Context, id int) neo4j.ManagedTransactionWork { + return func(tx neo4j.ManagedTransaction) (any, error) { + result, err := tx.Run(ctx, GetPersonCypherQuery, map[string]any{ + "id": id, + }) + if err != nil { + return nil, err + } + + record, err := result.Single(ctx) + if err != nil { + return nil, err + } + + return record.AsMap(), nil + } +} diff --git a/apps/db-adapter/internal/memgraph/person_google.go b/apps/db-adapter/internal/memgraph/person_google.go new file mode 100644 index 0000000..15941eb --- /dev/null +++ b/apps/db-adapter/internal/memgraph/person_google.go @@ -0,0 +1,45 @@ +package memgraph + +import ( + "context" + + "github.com/neo4j/neo4j-go-driver/v5/neo4j" + "github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api" +) + +func GetPersonByGoogleId(ctx context.Context, googleId string) neo4j.ManagedTransactionWork { + return func(tx neo4j.ManagedTransaction) (any, error) { + result, err := tx.Run(ctx, GetPersonByGoogleIdCypherQuery, map[string]any{ + "google_id": googleId, + }) + if err != nil { + return nil, err + } + + record, err := result.Single(ctx) + if err != nil { + return nil, err + } + + return record.AsMap(), nil + } +} + +func UpdatePersonByInviteCode(ctx context.Context, inviteCode string, Person *api.PersonProperties) neo4j.ManagedTransactionWork { + return func(tx neo4j.ManagedTransaction) (any, error) { + result, err := tx.Run(ctx, UpdatePersonByInviteCodeCypherQuery, map[string]any{ + "invite_code": inviteCode, + "props": *Person, + }) + if err != nil { + return nil, err + } + + record, err := result.Single(ctx) + if err != nil { + return nil, err + } + + return record.AsMap(), nil + } +} diff --git a/apps/db-adapter/internal/memgraph/queries.go b/apps/db-adapter/internal/memgraph/queries.go index 0f3ee74..9766072 100644 --- a/apps/db-adapter/internal/memgraph/queries.go +++ b/apps/db-adapter/internal/memgraph/queries.go @@ -16,45 +16,60 @@ var DropConstraintsCypherQuery string // Requires Person parameter. // Returns p as person +// //go:embed queries/create_person.cypher var CreatePersonCypherQuery string // Requires id parameter. // Returns n as person +// //go:embed queries/get_person_by_id.cypher var GetPersonCypherQuery string // Requires id, props parameter. // Returns n as person +// //go:embed queries/update_person.cypher var UpdatePersonCypherQuery string +// Requires invite_code, props parameter. +// +//go:embed queries/update_person_by_invite_code.cypher +var UpdatePersonByInviteCodeCypherQuery string + // Requires google_id parameter. // Returns n as person +// //go:embed queries/get_person_by_google_id.cypher var GetPersonByGoogleIdCypherQuery string // Requires id parameter. // Returns labels(n) AS labels, n AS person +// //go:embed queries/soft_delete_person_by_id.cypher var SoftDeletePersonCypherQuery string // Requires id parameter. +// //go:embed queries/hard_delete_person_by_id.cypher var HardDeletePersonCypherQuery string // Requires id1, id2 parameters. +// //go:embed queries/get_relationship.cypher var GetRelationshipCypherQuery string // Requires id1, id2, Relationship parameters. +// //go:embed queries/create_directed_relationship.cypher var CreateDirectedRelationshipCypherQuery string // Requires id1, id2, Relationship1, Relationship2 parameters. +// //go:embed queries/create_two_directed_relationships.cypher var CreateTwoDirectedRelationshipCypherQuery string // Requires id parameter. +// //go:embed queries/get_family_tree_by_id.cypher var GetFamilyTreeByIdCypherQuery string diff --git a/apps/db-adapter/internal/memgraph/queries/update_person_by_invite_code.cypher b/apps/db-adapter/internal/memgraph/queries/update_person_by_invite_code.cypher new file mode 100644 index 0000000..0a869dd --- /dev/null +++ b/apps/db-adapter/internal/memgraph/queries/update_person_by_invite_code.cypher @@ -0,0 +1,4 @@ +MATCH (n:Person) +WHERE n.invite_code = $invite_code +SET n += $props +RETURN n AS person \ No newline at end of file