diff --git a/Dockerfile b/Dockerfile index 06ffd30..e09212c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,13 @@ # Dockerfile References: https://docs.docker.com/engine/reference/builder/ # Start from golang v1.11 base image -FROM golang:1.12-alpine +FROM golang:1.14-alpine # Add Maintainer Info LABEL maintainer="The OpenSentry Team" RUN apk add --update --no-cache ca-certificates cmake make g++ openssl-dev git curl pkgconfig openssh -# RUN apt install -y libssl1.0.0 -RUN git clone -b v1.7.4 https://github.com/neo4j-drivers/seabolt.git /seabolt - -# invoke cmake build and install artifacts - default location is /usr/local -WORKDIR /seabolt/build - -# CMAKE_INSTALL_LIBDIR=lib is a hack where we override default lib64 to lib to workaround a defect -# in our generated pkg-config file -RUN cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_LIBDIR=lib .. && cmake --build . --target install - # Set the Current Working Directory inside the container WORKDIR $GOPATH/src/github.com/opensentry/idp diff --git a/Dockerfile.alpine b/Dockerfile.alpine index 8eb88e2..1f5731a 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -1,6 +1,6 @@ # Build with: DOCKER_BUILDKIT=1 docker build -t opensentry/idp:`cat ./VERSION` -f Dockerfile.alpine . -ARG GO_VERSION=1.12 +ARG GO_VERSION=1.14 ARG ALPINE_VERSION=3.10.3 FROM golang:${GO_VERSION}-alpine AS builder @@ -9,7 +9,6 @@ ARG APP=idp ARG SEABOLT_VERSION="v1.7.4" RUN apk add --update --no-cache ca-certificates cmake make g++ openssl-dev git curl pkgconfig libcap -RUN git clone -b "$SEABOLT_VERSION" https://github.com/neo4j-drivers/seabolt.git /seabolt RUN update-ca-certificates 2>/dev/null || true WORKDIR /seabolt/build @@ -25,9 +24,7 @@ RUN rm -f application-build* RUN go get -d -v ./... -RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh -RUN dep init && dep ensure -add github.com/neo4j/neo4j-go-driver/neo4j -RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -tags seabolt_static -o /app +RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o /app RUN cp -r ./model /model # /views is static data, which isnt built within the binary RUN cp -r ./emails /emails # default email templates, mount others to change RUN cp -r ./ban /ban # default ban lists (empty), mount others to change diff --git a/Dockerfile.dev b/Dockerfile.dev index 0fb07a0..28efef9 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,11 +1,6 @@ -FROM golang:1.12-alpine +FROM golang:1.14-alpine RUN apk add --update --no-cache ca-certificates cmake make g++ openssl-dev git curl pkgconfig -RUN git clone -b v1.7.4 https://github.com/neo4j-drivers/seabolt.git /seabolt - -WORKDIR /seabolt/build - -RUN cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_LIBDIR=lib .. && cmake --build . --target install WORKDIR $GOPATH/src/github.com/opensentry/idp @@ -15,11 +10,10 @@ COPY . . #go get: warning: modules disabled by GO111MODULE=auto in GOPATH/src; # ignoring go.mod; # see 'go help modules' -RUN rm go.mod go.sum +# RUN rm go.mod go.sum RUN go get -d -v ./... -#RUN go get github.com/pilu/fresh RUN go get github.com/ivpusic/rerun EXPOSE 443 @@ -29,5 +23,4 @@ COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] -#CMD ["fresh"] CMD ["rerun", "-a--serve"] diff --git a/app/environment.go b/app/environment.go index 24cfacf..b7f2ac0 100644 --- a/app/environment.go +++ b/app/environment.go @@ -3,7 +3,7 @@ package app import ( "crypto/rsa" "github.com/sirupsen/logrus" - "github.com/neo4j/neo4j-go-driver/neo4j" + "database/sql" nats "github.com/nats-io/nats.go" "golang.org/x/oauth2/clientcredentials" oidc "github.com/coreos/go-oidc" @@ -37,7 +37,7 @@ type Environment struct { HydraConfig *clientcredentials.Config AapConfig *clientcredentials.Config - Driver neo4j.Driver + Driver *sql.DB BannedUsernames map[string]bool IssuerSignKey *rsa.PrivateKey IssuerVerifyKey *rsa.PublicKey @@ -49,4 +49,4 @@ type EmailTemplate struct { Sender idp.SMTPSender File string Subject string -} \ No newline at end of file +} diff --git a/endpoints/challenges/challenges.go b/endpoints/challenges/challenges.go index 87e1ac8..721c111 100644 --- a/endpoints/challenges/challenges.go +++ b/endpoints/challenges/challenges.go @@ -3,6 +3,7 @@ package challenges import ( "errors" "time" + "context" "net/http" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -31,6 +32,9 @@ type ConfirmTemplateData struct { func GetChallenges(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + + ctx := context.TODO() // FIXME + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "GetChallenges", @@ -45,19 +49,17 @@ func GetChallenges(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginReadTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() // requestor := c.MustGet("sub").(string) // var requestedBy *idp.Identity // if requestor != "" { - // identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) + // identities, err := idp.FetchIdentities(ctx, tx, []idp.Identity{ {Id:requestor} }) // if err != nil { // bulky.FailAllRequestsWithInternalErrorResponse(iRequests) // log.Debug(err.Error()) @@ -75,11 +77,11 @@ func GetChallenges(env *app.Environment) gin.HandlerFunc { var ok client.ReadChallengesResponse if request.Input == nil { - dbChallenges, err = idp.FetchChallenges(tx, nil) + dbChallenges, err = idp.FetchChallenges(ctx, tx, nil) } else { r := request.Input.(client.ReadChallengesRequest) log = log.WithFields(logrus.Fields{"otp_challenge": r.OtpChallenge}) - dbChallenges, err = idp.FetchChallenges(tx, []idp.Challenge{ {Id: r.OtpChallenge} }) + dbChallenges, err = idp.FetchChallenges(ctx, tx, []idp.Challenge{ {Id: r.OtpChallenge} }) } if err != nil { e := tx.Rollback() @@ -133,6 +135,9 @@ func GetChallenges(env *app.Environment) gin.HandlerFunc { func PostChallenges(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + + ctx := context.TODO() // FIXME + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostChallenges", @@ -155,19 +160,17 @@ func PostChallenges(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() // requestor := c.MustGet("sub").(string) // var requestedBy *idp.Identity // if requestor != "" { - // identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) + // identities, err := idp.FetchIdentities(ctx, tx, []idp.Identity{ {Id:requestor} }) // if err != nil { // bulky.FailAllRequestsWithInternalErrorResponse(iRequests) // log.Debug(err.Error()) @@ -237,9 +240,9 @@ func PostChallenges(env *app.Environment) gin.HandlerFunc { var otpCode idp.ChallengeCode var challenge idp.Challenge if client.OTPType(newChallenge.CodeType) == client.TOTP { - challenge, err = idp.CreateChallengeUsingTotp(tx, ct, newChallenge) + challenge, err = idp.CreateChallengeUsingTotp(ctx, tx, ct, newChallenge) } else { - challenge, otpCode, err = idp.CreateChallengeUsingOtp(tx, ct, newChallenge) + challenge, otpCode, err = idp.CreateChallengeUsingOtp(ctx, tx, ct, newChallenge) } if err == nil && challenge.Id != "" { @@ -441,4 +444,3 @@ func translateChallengeTypeToConfirmationType(challengeType idp.ChallengeType) ( return client.ConfirmationType(0) } } - diff --git a/endpoints/challenges/verify.go b/endpoints/challenges/verify.go index 87d19d8..493a4ed 100644 --- a/endpoints/challenges/verify.go +++ b/endpoints/challenges/verify.go @@ -2,6 +2,7 @@ package challenges import ( "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -16,6 +17,9 @@ import ( func PutVerify(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PutVerify", @@ -38,14 +42,12 @@ func PutVerify(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() // requestor := c.MustGet("sub").(string) // var requestedBy *idp.Identity @@ -69,7 +71,7 @@ func PutVerify(env *app.Environment) gin.HandlerFunc { // Sanity check. Challenge must exists var aChallenge []idp.Challenge aChallenge = append(aChallenge, idp.Challenge{Id: r.OtpChallenge}) - dbChallenges, err := idp.FetchChallenges(tx, aChallenge) + dbChallenges, err := idp.FetchChallenges(ctx, tx, aChallenge) if err != nil { e := tx.Rollback() if e != nil { @@ -99,7 +101,7 @@ func PutVerify(env *app.Environment) gin.HandlerFunc { if client.OTPType(challenge.CodeType) == client.TOTP { - humans, err := idp.FetchHumans(tx, []idp.Human{ {Identity:idp.Identity{Id:challenge.Subject}} }) + humans, err := idp.FetchHumans(ctx, tx, []idp.Human{ {Identity:idp.Identity{Id:challenge.Subject}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -155,7 +157,7 @@ func PutVerify(env *app.Environment) gin.HandlerFunc { if valid == true { - verifiedChallenge, err := idp.VerifyChallenge(tx, challenge) + verifiedChallenge, err := idp.VerifyChallenge(ctx, tx, challenge) if err != nil { e := tx.Rollback() if e != nil { diff --git a/endpoints/clients/clients.go b/endpoints/clients/clients.go index 57dcf8e..fd6a2a0 100644 --- a/endpoints/clients/clients.go +++ b/endpoints/clients/clients.go @@ -2,6 +2,7 @@ package clients import ( "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -19,6 +20,9 @@ import ( func GetClients(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + + ctx := context.TODO() // FIXME + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "GetClients", @@ -41,28 +45,12 @@ func GetClients(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginReadTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - requestor := c.MustGet("sub").(string) - var requestedBy *idp.Identity - if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - if err != nil { - bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - log.Debug(err.Error()) - return - } - if len(identities) > 0 { - requestedBy = &identities[0] - } - } for _, request := range iRequests { @@ -71,10 +59,10 @@ func GetClients(env *app.Environment) gin.HandlerFunc { var ok client.ReadClientsResponse if request.Input == nil { - dbClients, err = idp.FetchClients(tx, requestedBy, nil) + dbClients, err = idp.FetchClients(ctx, tx, nil) } else { r := request.Input.(client.ReadClientsRequest) - dbClients, err = idp.FetchClients(tx, requestedBy, []idp.Client{ {Identity:idp.Identity{Id: r.Id}} }) + dbClients, err = idp.FetchClients(ctx, tx, []idp.Client{ {Identity:idp.Identity{Id: r.Id}} }) } if err != nil { e := tx.Rollback() @@ -139,6 +127,8 @@ func GetClients(env *app.Environment) gin.HandlerFunc { func PostClients(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() // FIXME + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostClients", @@ -161,19 +151,17 @@ func PostClients(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.WithFields(logrus.Fields{ "error": err.Error() }).Debug("Failed to begin transaction") return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() requestor := c.MustGet("sub").(string) var requestedBy *idp.Identity if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) + identities, err := idp.FetchIdentities(ctx, tx, []idp.Identity{ {Id:requestor} }) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.WithFields(logrus.Fields{ "error": err.Error(), "id": requestor }).Debug("Failed to fetch identity") @@ -207,7 +195,7 @@ func PostClients(env *app.Environment) gin.HandlerFunc { if r.IsPublic == false { if r.Secret == "" { - + // BCrypt used by hydra to store passwords securely limits password to 55 chars not counting the terminating zero secret, err = sec.CreateClientSecret(sec.RECOMMENDED_CLIENT_SECRET_ENTROPY_IN_BYTES) if err != nil { @@ -241,7 +229,7 @@ func PostClients(env *app.Environment) gin.HandlerFunc { newClient.Secret = encryptedClientSecret } - objClient, err := idp.CreateClient(tx, requestedBy, newClient) + objClient, err := idp.CreateClient(ctx, tx, newClient) if err != nil { log.WithFields(logrus.Fields{ "error": err.Error() }).Debug("Failed to create client") @@ -404,6 +392,8 @@ func PostClients(env *app.Environment) gin.HandlerFunc { func DeleteClients(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() // FIXME + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "DeleteClients", @@ -418,28 +408,12 @@ func DeleteClients(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - requestor := c.MustGet("sub").(string) - var requestedBy *idp.Identity - if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - if err != nil { - bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - log.Debug(err.Error()) - return - } - if len(identities) > 0 { - requestedBy = &identities[0] - } - } var deleteHydraClients []string @@ -448,7 +422,7 @@ func DeleteClients(env *app.Environment) gin.HandlerFunc { log = log.WithFields(logrus.Fields{"id": r.Id}) - dbClients, err := idp.FetchClients(tx, requestedBy, []idp.Client{ {Identity:idp.Identity{Id:r.Id}} }) + dbClients, err := idp.FetchClients(ctx, tx, []idp.Client{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -471,7 +445,7 @@ func DeleteClients(env *app.Environment) gin.HandlerFunc { deleteHydraClients = append(deleteHydraClients, clientToDelete.Id) - deletedClient, err := idp.DeleteClient(tx, requestedBy, clientToDelete) + deletedClient, err := idp.DeleteClient(ctx, tx, clientToDelete) if err != nil { e := tx.Rollback() if e != nil { diff --git a/endpoints/humans/authenticate.go b/endpoints/humans/authenticate.go index d1b360d..ed3b4ac 100644 --- a/endpoints/humans/authenticate.go +++ b/endpoints/humans/authenticate.go @@ -4,6 +4,7 @@ import ( "net/url" "net/http" "time" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -28,6 +29,8 @@ type ConfirmTemplateData struct { func PostAuthenticate(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostAuthenticate", @@ -84,28 +87,12 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - // requestor := c.MustGet("sub").(string) - // var requestedBy *idp.Identity - // if requestor != "" { - // identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - // if err != nil { - // bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - // log.Debug(err.Error()) - // return - // } - // if len(identities) > 0 { - // requestedBy = &identities[0] - // } - // } for _, request := range iRequests { r := request.Input.(client.CreateHumansAuthenticateRequest) @@ -135,7 +122,7 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { // Lookup subject if subject != "" { - humans, err := idp.FetchHumans(tx, []idp.Human{ {Identity: idp.Identity{Id:subject}} }) + humans, err := idp.FetchHumans(ctx, tx, []idp.Human{ {Identity: idp.Identity{Id:subject}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -154,7 +141,7 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { deny.IdentityExists = false // Hydra told us subject has active session, but our identity provider told us that the subject no longer exists. - // This happens if we delete identity from neo4j, but fail to revoke sessions from hydra. + // This happens if we delete identity from our db, but fail to revoke sessions from hydra. hydraLoginRejectResponse, err := hydra.RejectLogin(config.GetString("hydra.private.url") + config.GetString("hydra.private.endpoints.loginReject"), hydraClient, r.Challenge, hydra.LoginRejectRequest{ Error: "Identity deleted", @@ -190,7 +177,7 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { // Lookup client if clientId != "" { - clients, err := idp.FetchClients(tx, nil, []idp.Client{ {Identity: idp.Identity{Id:clientId}} }) + clients, err := idp.FetchClients(ctx, tx, []idp.Client{ {Identity: idp.Identity{Id:clientId}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -262,7 +249,7 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { acr := "otp.email" - dbChallenges, err := idp.FetchChallenges(tx, []idp.Challenge{ {Id: r.EmailChallenge} }) + dbChallenges, err := idp.FetchChallenges(ctx, tx, []idp.Challenge{ {Id: r.EmailChallenge} }) if err != nil { e := tx.Rollback() if e != nil { @@ -287,7 +274,7 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { challenge := dbChallenges[0] if challenge.VerifiedAt > 0 { - _, err := idp.ConfirmEmail(tx, idp.Human{ Identity: idp.Identity{Id: challenge.Subject} }) + _, err := idp.ConfirmEmail(ctx, tx, idp.Human{ Identity: idp.Identity{Id: challenge.Subject} }) if err != nil { e := tx.Rollback() if e != nil { @@ -347,7 +334,7 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { log = log.WithFields(logrus.Fields{ "otp_challenge": r.OtpChallenge }) acr := "otp" - dbChallenges, err := idp.FetchChallenges(tx, []idp.Challenge{ {Id: r.OtpChallenge} }) + dbChallenges, err := idp.FetchChallenges(ctx, tx, []idp.Challenge{ {Id: r.OtpChallenge} }) if err != nil { e := tx.Rollback() if e != nil { @@ -433,7 +420,7 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { log = log.WithFields(logrus.Fields{"id": r.Id}) - dbHumans, err := idp.FetchHumans(tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) + dbHumans, err := idp.FetchHumans(ctx, tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -495,7 +482,7 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { CodeType: int64(client.OTP), Data: human.Email, } - challenge, otpCode, err := idp.CreateChallengeUsingOtp(tx, idp.ChallengeAuthenticate, newChallenge) + challenge, otpCode, err := idp.CreateChallengeUsingOtp(ctx, tx, idp.ChallengeAuthenticate, newChallenge) if err != nil { e := tx.Rollback() if e != nil { @@ -553,7 +540,7 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { RedirectTo: redirectToUrlWhenVerified.String(), CodeType: int64(client.TOTP), } - challenge, err := idp.CreateChallengeUsingTotp(tx, idp.ChallengeAuthenticate, newChallenge) + challenge, err := idp.CreateChallengeUsingTotp(ctx, tx, idp.ChallengeAuthenticate, newChallenge) if err != nil { e := tx.Rollback() if e != nil { @@ -638,4 +625,3 @@ func PostAuthenticate(env *app.Environment) gin.HandlerFunc { } return gin.HandlerFunc(fn) } - diff --git a/endpoints/humans/deleteverification.go b/endpoints/humans/deleteverification.go index 8f90d03..281a84b 100644 --- a/endpoints/humans/deleteverification.go +++ b/endpoints/humans/deleteverification.go @@ -2,6 +2,7 @@ package humans import ( "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -16,6 +17,8 @@ import ( func PutDeleteVerification(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PutDeleteVerification", @@ -30,14 +33,12 @@ func PutDeleteVerification(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() // requestor := c.MustGet("sub").(string) // var requestedBy *idp.Identity @@ -58,7 +59,7 @@ func PutDeleteVerification(env *app.Environment) gin.HandlerFunc { log = log.WithFields(logrus.Fields{"delete_challenge": r.DeleteChallenge}) - dbChallenges, err := idp.FetchChallenges(tx, []idp.Challenge{ {Id: r.DeleteChallenge} }) + dbChallenges, err := idp.FetchChallenges(ctx, tx, []idp.Challenge{ {Id: r.DeleteChallenge} }) if err != nil { e := tx.Rollback() if e != nil { @@ -92,7 +93,7 @@ func PutDeleteVerification(env *app.Environment) gin.HandlerFunc { log.WithFields(logrus.Fields{"fixme":1}).Debug("Revoke all consents in hydra for identity - this is probably aap?") log.WithFields(logrus.Fields{"fixme":1}).Debug("Revoke all sessions in hydra for identity - this is probably aap?") - deletedHuman, err := idp.DeleteHuman(tx, idp.Human{Identity: idp.Identity{ Id: challenge.Subject }}) + deletedHuman, err := idp.DeleteHuman(ctx, tx, idp.Human{Identity: idp.Identity{ Id: challenge.Subject }}) if err != nil { e := tx.Rollback() if e != nil { diff --git a/endpoints/humans/email.go b/endpoints/humans/email.go index a44f957..8a6bd85 100644 --- a/endpoints/humans/email.go +++ b/endpoints/humans/email.go @@ -2,6 +2,7 @@ package humans import ( "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -16,6 +17,8 @@ import ( func PutEmail(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PutEmail", @@ -30,19 +33,17 @@ func PutEmail(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() requestor := c.MustGet("sub").(string) var requestedBy *idp.Identity if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) + identities, err := idp.FetchIdentities(ctx, tx, []idp.Identity{ {Id:requestor} }) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) @@ -69,7 +70,7 @@ func PutEmail(env *app.Environment) gin.HandlerFunc { return } - dbHumans, err := idp.FetchHumans(tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) + dbHumans, err := idp.FetchHumans(ctx, tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -92,7 +93,7 @@ func PutEmail(env *app.Environment) gin.HandlerFunc { } human := dbHumans[0] - updatedHuman, err := idp.UpdateEmail(tx, idp.Human{ Identity: idp.Identity{ Id: human.Id }, Email: r.Email }) + updatedHuman, err := idp.UpdateEmail(ctx, tx, idp.Human{ Identity: idp.Identity{ Id: human.Id }, Email: r.Email }) if err != nil { e := tx.Rollback() if e != nil { @@ -143,4 +144,4 @@ func PutEmail(env *app.Environment) gin.HandlerFunc { c.JSON(http.StatusOK, responses) } return gin.HandlerFunc(fn) -} \ No newline at end of file +} diff --git a/endpoints/humans/emailchange.go b/endpoints/humans/emailchange.go index 462612d..86ada9c 100644 --- a/endpoints/humans/emailchange.go +++ b/endpoints/humans/emailchange.go @@ -4,6 +4,7 @@ import ( "time" "net/http" "net/url" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -25,6 +26,8 @@ type EmailChangeTemplateData struct { func PostEmailChange(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostEmailChange", @@ -59,14 +62,12 @@ func PostEmailChange(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() // requestor := c.MustGet("sub").(string) // var requestedBy *idp.Identity @@ -98,7 +99,7 @@ func PostEmailChange(env *app.Environment) gin.HandlerFunc { // return // } - dbHumans, err := idp.FetchHumans(tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) + dbHumans, err := idp.FetchHumans(ctx, tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -136,7 +137,7 @@ func PostEmailChange(env *app.Environment) gin.HandlerFunc { CodeType: int64(client.OTP), Data: r.Email, } - challenge, otpCode, err := idp.CreateChallengeUsingOtp(tx, idp.ChallengeEmailChange, newChallenge) + challenge, otpCode, err := idp.CreateChallengeUsingOtp(ctx, tx, idp.ChallengeEmailChange, newChallenge) if err != nil { e := tx.Rollback() if e != nil { @@ -216,6 +217,8 @@ func PostEmailChange(env *app.Environment) gin.HandlerFunc { func PutEmailChange(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PutEmailChange", @@ -230,14 +233,12 @@ func PutEmailChange(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() // requestor := c.MustGet("sub").(string) // var requestedBy *idp.Identity @@ -258,7 +259,7 @@ func PutEmailChange(env *app.Environment) gin.HandlerFunc { log = log.WithFields(logrus.Fields{"email_challenge": r.EmailChallenge}) - dbChallenges, err := idp.FetchChallenges(tx, []idp.Challenge{ {Id: r.EmailChallenge} }) + dbChallenges, err := idp.FetchChallenges(ctx, tx, []idp.Challenge{ {Id: r.EmailChallenge} }) if err != nil { e := tx.Rollback() if e != nil { @@ -284,7 +285,7 @@ func PutEmailChange(env *app.Environment) gin.HandlerFunc { if challenge.VerifiedAt > 0 { - updatedHuman, err := idp.UpdateEmail(tx, idp.Human{ Identity: idp.Identity{ Id: challenge.Subject }, Email: r.Email }) + updatedHuman, err := idp.UpdateEmail(ctx, tx, idp.Human{ Identity: idp.Identity{ Id: challenge.Subject }, Email: r.Email }) if err != nil { e := tx.Rollback() if e != nil { @@ -330,4 +331,4 @@ func PutEmailChange(env *app.Environment) gin.HandlerFunc { c.JSON(http.StatusOK, responses) } return gin.HandlerFunc(fn) -} \ No newline at end of file +} diff --git a/endpoints/humans/humans.go b/endpoints/humans/humans.go index 3e717f2..c45f850 100644 --- a/endpoints/humans/humans.go +++ b/endpoints/humans/humans.go @@ -4,6 +4,7 @@ import ( "time" "net/http" "net/url" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -27,6 +28,8 @@ type DeleteTemplateData struct { func GetHumans(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "GetHumans", @@ -44,28 +47,12 @@ func GetHumans(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginReadTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - // requestor := c.MustGet("sub").(string) - // var requestedBy *idp.Identity - // if requestor != "" { - // identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - // if err != nil { - // bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - // log.Debug(err.Error()) - // return - // } - // if len(identities) > 0 { - // requestedBy = &identities[0] - // } - // } for _, request := range iRequests { @@ -74,17 +61,17 @@ func GetHumans(env *app.Environment) gin.HandlerFunc { var ok client.ReadHumansResponse if request.Input == nil { - dbHumans, err = idp.FetchHumans(tx, nil) + dbHumans, err = idp.FetchHumans(ctx, tx, nil) } else { r := request.Input.(client.ReadHumansRequest) if r.Id != "" { log = log.WithFields(logrus.Fields{"id": r.Id}) - dbHumans, err = idp.FetchHumans(tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) + dbHumans, err = idp.FetchHumans(ctx, tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) } else if r.Email != "" { - dbHumans, err = idp.FetchHumansByEmail(tx, []idp.Human{ {Email:r.Email} }) + dbHumans, err = idp.FetchHumansByEmail(ctx, tx, []idp.Human{ {Email:r.Email} }) } else if r.Username != "" { - dbHumans, err = idp.FetchHumansByUsername(tx, []idp.Human{ {Username:r.Username} }) + dbHumans, err = idp.FetchHumansByUsername(ctx, tx, []idp.Human{ {Username:r.Username} }) } } @@ -140,6 +127,8 @@ func GetHumans(env *app.Environment) gin.HandlerFunc { func PostHumans(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostHumans", @@ -154,28 +143,12 @@ func PostHumans(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - // requestor := c.MustGet("sub").(string) - // var requestedBy *idp.Identity - // if requestor != "" { - // identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - // if err != nil { - // bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - // log.Debug(err.Error()) - // return - // } - // if len(identities) > 0 { - // requestedBy = &identities[0] - // } - // } var ids []string @@ -194,7 +167,7 @@ func PostHumans(env *app.Environment) gin.HandlerFunc { // Sanity check. Username must be unique if r.Username != "" { - humansFoundByUsername, err := idp.FetchHumansByUsername(tx, []idp.Human{ {Username:r.Username} }) + humansFoundByUsername, err := idp.FetchHumansByUsername(ctx, tx, []idp.Human{ {Username:r.Username} }) if err != nil { e := tx.Rollback() if e != nil { @@ -236,7 +209,7 @@ func PostHumans(env *app.Environment) gin.HandlerFunc { AllowLogin: true, EmailConfirmedAt: r.EmailConfirmedAt, } - human, err := idp.CreateHumanFromInvite(tx, newHuman) + human, err := idp.CreateHumanFromInvite(ctx, tx, newHuman) if err != nil { e := tx.Rollback() if e != nil { @@ -374,6 +347,8 @@ func PostHumans(env *app.Environment) gin.HandlerFunc { func PutHumans(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PutHumans", @@ -388,28 +363,12 @@ func PutHumans(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - // requestor := c.MustGet("sub").(string) - // var requestedBy *idp.Identity - // if requestor != "" { - // identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - // if err != nil { - // bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - // log.Debug(err.Error()) - // return - // } - // if len(identities) > 0 { - // requestedBy = &identities[0] - // } - // } for _, request := range iRequests { r := request.Input.(client.UpdateHumansRequest) @@ -422,7 +381,7 @@ func PutHumans(env *app.Environment) gin.HandlerFunc { }, Name: r.Name, } - human, err := idp.UpdateHuman(tx, updateHuman) + human, err := idp.UpdateHuman(ctx, tx, updateHuman) if err != nil { e := tx.Rollback() if e != nil { @@ -482,6 +441,8 @@ func PutHumans(env *app.Environment) gin.HandlerFunc { func DeleteHumans(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "DeleteHumans", @@ -516,19 +477,17 @@ func DeleteHumans(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() requestor := c.MustGet("sub").(string) var requestedBy *idp.Identity if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) + identities, err := idp.FetchIdentities(ctx, tx, []idp.Identity{ {Id:requestor} }) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) @@ -555,7 +514,7 @@ func DeleteHumans(env *app.Environment) gin.HandlerFunc { return } - dbHumans, err := idp.FetchHumans(tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) + dbHumans, err := idp.FetchHumans(ctx, tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -592,7 +551,7 @@ func DeleteHumans(env *app.Environment) gin.HandlerFunc { RedirectTo: r.RedirectTo, // Requested success url redirect. CodeType: int64(client.OTP), } - challenge, otpCode, err := idp.CreateChallengeUsingOtp(tx, idp.ChallengeEmailConfirm, newChallenge) + challenge, otpCode, err := idp.CreateChallengeUsingOtp(ctx, tx, idp.ChallengeEmailConfirm, newChallenge) if err != nil { e := tx.Rollback() if e != nil { diff --git a/endpoints/humans/password.go b/endpoints/humans/password.go index e698192..a9847ab 100644 --- a/endpoints/humans/password.go +++ b/endpoints/humans/password.go @@ -2,6 +2,7 @@ package humans import ( "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -16,6 +17,8 @@ import ( func PutPassword(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PutPassword", @@ -30,19 +33,17 @@ func PutPassword(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() requestor := c.MustGet("sub").(string) var requestedBy *idp.Identity if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) + identities, err := idp.FetchIdentities(ctx, tx, []idp.Identity{ {Id:requestor} }) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) @@ -69,7 +70,7 @@ func PutPassword(env *app.Environment) gin.HandlerFunc { return } - dbHumans, err := idp.FetchHumans(tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) + dbHumans, err := idp.FetchHumans(ctx, tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -120,7 +121,7 @@ func PutPassword(env *app.Environment) gin.HandlerFunc { return } - updatedHuman, err := idp.UpdatePassword(tx, idp.Human{ + updatedHuman, err := idp.UpdatePassword(ctx, tx, idp.Human{ Identity: idp.Identity{ Id: human.Id, }, diff --git a/endpoints/humans/recover.go b/endpoints/humans/recover.go index 2791bce..4cf1f82 100644 --- a/endpoints/humans/recover.go +++ b/endpoints/humans/recover.go @@ -4,6 +4,7 @@ import ( "time" "net/http" "net/url" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -25,6 +26,8 @@ type RecoverTemplateData struct { func PostRecover(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostRecover", @@ -59,14 +62,12 @@ func PostRecover(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() // requestor := c.MustGet("sub").(string) // var requestedBy *idp.Identity @@ -98,7 +99,7 @@ func PostRecover(env *app.Environment) gin.HandlerFunc { // return // } - dbHumans, err := idp.FetchHumans(tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) + dbHumans, err := idp.FetchHumans(ctx, tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -135,7 +136,7 @@ func PostRecover(env *app.Environment) gin.HandlerFunc { RedirectTo: r.RedirectTo, // Requested success url redirect. CodeType: int64(client.OTP), } - challenge, otpCode, err := idp.CreateChallengeUsingOtp(tx, idp.ChallengeRecover, newChallenge) + challenge, otpCode, err := idp.CreateChallengeUsingOtp(ctx, tx, idp.ChallengeRecover, newChallenge) if err != nil { e := tx.Rollback() if e != nil { @@ -210,4 +211,4 @@ func PostRecover(env *app.Environment) gin.HandlerFunc { c.JSON(http.StatusOK, responses) } return gin.HandlerFunc(fn) -} \ No newline at end of file +} diff --git a/endpoints/humans/recoververification.go b/endpoints/humans/recoververification.go index d51e4f9..e6522ca 100644 --- a/endpoints/humans/recoververification.go +++ b/endpoints/humans/recoververification.go @@ -2,6 +2,7 @@ package humans import ( "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -16,6 +17,8 @@ import ( func PutRecoverVerification(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PutRecoverVerification", @@ -30,14 +33,12 @@ func PutRecoverVerification(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() // requestor := c.MustGet("sub").(string) // var requestedBy *idp.Identity @@ -58,7 +59,7 @@ func PutRecoverVerification(env *app.Environment) gin.HandlerFunc { log = log.WithFields(logrus.Fields{"recover_challenge": r.RecoverChallenge}) - dbChallenges, err := idp.FetchChallenges(tx, []idp.Challenge{ {Id: r.RecoverChallenge} }) + dbChallenges, err := idp.FetchChallenges(ctx, tx, []idp.Challenge{ {Id: r.RecoverChallenge} }) if err != nil { e := tx.Rollback() if e != nil { @@ -105,7 +106,7 @@ func PutRecoverVerification(env *app.Environment) gin.HandlerFunc { return } - updatedHuman, err := idp.UpdatePassword(tx, idp.Human{ Identity: idp.Identity{ Id: challenge.Subject }, Password: hashedPassword }) + updatedHuman, err := idp.UpdatePassword(ctx, tx, idp.Human{ Identity: idp.Identity{ Id: challenge.Subject }, Password: hashedPassword }) if err != nil { e := tx.Rollback() if e != nil { diff --git a/endpoints/humans/totp.go b/endpoints/humans/totp.go index 1610a2f..2cce46a 100644 --- a/endpoints/humans/totp.go +++ b/endpoints/humans/totp.go @@ -2,6 +2,7 @@ package humans import ( "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -17,6 +18,8 @@ import ( func PutTotp(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PutTotp", @@ -39,19 +42,17 @@ func PutTotp(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() requestor := c.MustGet("sub").(string) var requestedBy *idp.Identity if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) + identities, err := idp.FetchIdentities(ctx, tx, []idp.Identity{ {Id:requestor} }) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) @@ -78,7 +79,7 @@ func PutTotp(env *app.Environment) gin.HandlerFunc { return } - dbHumans, err := idp.FetchHumans(tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) + dbHumans, err := idp.FetchHumans(ctx, tx, []idp.Human{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -113,7 +114,7 @@ func PutTotp(env *app.Environment) gin.HandlerFunc { return } - updatedHuman, err := idp.UpdateTotp(tx, idp.Human{ + updatedHuman, err := idp.UpdateTotp(ctx, tx, idp.Human{ Identity: idp.Identity{ Id: human.Id, }, diff --git a/endpoints/identities/identities.go b/endpoints/identities/identities.go index a099fc5..1d79765 100644 --- a/endpoints/identities/identities.go +++ b/endpoints/identities/identities.go @@ -3,6 +3,7 @@ package identities import ( "net/http" "strings" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -16,6 +17,8 @@ import ( func GetIdentities(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() // FIXME + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "GetIdentities", @@ -31,28 +34,12 @@ func GetIdentities(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginReadTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - // requestor := c.MustGet("sub").(string) - // var requestedBy *idp.Identity - // if requestor != "" { - // identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - // if err != nil { - // bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - // log.Debug(err.Error()) - // return - // } - // if len(identities) > 0 { - // requestedBy = &identities[0] - // } - // } for _, request := range iRequests { @@ -61,13 +48,13 @@ func GetIdentities(env *app.Environment) gin.HandlerFunc { var ok client.ReadIdentitiesResponse if request.Input == nil { - dbIdentities, err = idp.FetchIdentities(tx, nil) + dbIdentities, err = idp.FetchIdentities(ctx, tx, nil) } else { r := request.Input.(client.ReadIdentitiesRequest) if r.Id != "" { - dbIdentities, err = idp.FetchIdentities(tx, []idp.Identity{ {Id: r.Id} }) + dbIdentities, err = idp.FetchIdentities(ctx, tx, []idp.Identity{ {Id: r.Id} }) } else { - dbIdentities, err = idp.SearchIdentities(tx, r.Search) + dbIdentities, err = idp.SearchIdentities(ctx, tx, r.Search) } } if err != nil { diff --git a/endpoints/invites/claim.go b/endpoints/invites/claim.go index 381a1bf..c56423c 100644 --- a/endpoints/invites/claim.go +++ b/endpoints/invites/claim.go @@ -4,6 +4,7 @@ import ( "net/http" "net/url" "time" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -27,6 +28,8 @@ type ConfirmTemplateData struct { func PostInvitesClaim(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostInvitesClaim", @@ -65,14 +68,12 @@ func PostInvitesClaim(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() // requestor := c.MustGet("sub").(string) // var requestedBy *idp.Identity @@ -107,7 +108,7 @@ func PostInvitesClaim(env *app.Environment) gin.HandlerFunc { } inv := idp.Invite{ Identity: idp.Identity{ Id: r.Id } } - dbInvites, err := idp.FetchInvites(tx, nil, []idp.Invite{ inv }) + dbInvites, err := idp.FetchInvites(ctx, tx, []idp.Invite{ inv }) if err != nil { e := tx.Rollback() if e != nil { @@ -141,7 +142,7 @@ func PostInvitesClaim(env *app.Environment) gin.HandlerFunc { RedirectTo: redirectToUrlWhenVerified.String(), CodeType: int64(client.OTP), } - challenge, otpCode, err := idp.CreateChallengeUsingOtp(tx, idp.ChallengeEmailConfirm, newChallenge) + challenge, otpCode, err := idp.CreateChallengeUsingOtp(ctx, tx, idp.ChallengeEmailConfirm, newChallenge) if err != nil { e := tx.Rollback() if e != nil { diff --git a/endpoints/invites/invites.go b/endpoints/invites/invites.go index f0ecc4c..11001ab 100644 --- a/endpoints/invites/invites.go +++ b/endpoints/invites/invites.go @@ -3,6 +3,7 @@ package invites import ( "time" "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -20,6 +21,8 @@ import ( func PostInvites(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostInvites", @@ -48,28 +51,12 @@ func PostInvites(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - requestor := c.MustGet("sub").(string) - var requestedBy *idp.Identity - if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - if err != nil { - bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - log.Debug(err.Error()) - return - } - if len(identities) > 0 { - requestedBy = &identities[0] - } - } var ids []string @@ -89,7 +76,7 @@ func PostInvites(env *app.Environment) gin.HandlerFunc { // Sanity check. Username must be unique if r.Username != "" { - humansFoundByUsername, err := idp.FetchHumansByUsername(tx, []idp.Human{ {Username:r.Username} }) + humansFoundByUsername, err := idp.FetchHumansByUsername(ctx, tx, []idp.Human{ {Username:r.Username} }) if err != nil { e := tx.Rollback() if e != nil { @@ -113,7 +100,7 @@ func PostInvites(env *app.Environment) gin.HandlerFunc { } // Sanity check. Email must be unique - dbHumans, err := idp.FetchHumansByEmail(tx, []idp.Human{ {Email: r.Email} }) + dbHumans, err := idp.FetchHumansByEmail(ctx, tx, []idp.Human{ {Email: r.Email} }) if err != nil { e := tx.Rollback() if e != nil { @@ -160,7 +147,7 @@ func PostInvites(env *app.Environment) gin.HandlerFunc { Username: r.Username, } log.Debug(newInvite) - invite, err := idp.CreateInvite(tx, requestedBy, newInvite) + invite, err := idp.CreateInvite(ctx, tx, newInvite) if err != nil { e := tx.Rollback() if e != nil { @@ -286,6 +273,8 @@ func PostInvites(env *app.Environment) gin.HandlerFunc { func GetInvites(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "GetInvites", @@ -300,28 +289,12 @@ func GetInvites(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginReadTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - requestor := c.MustGet("sub").(string) - var requestedBy *idp.Identity - if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - if err != nil { - bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - log.Debug(err.Error()) - return - } - if len(identities) > 0 { - requestedBy = &identities[0] - } - } for _, request := range iRequests { @@ -330,13 +303,13 @@ func GetInvites(env *app.Environment) gin.HandlerFunc { var ok client.ReadInvitesResponse if request.Input == nil { - dbInvites, err = idp.FetchInvites(tx, requestedBy, nil) + dbInvites, err = idp.FetchInvites(ctx, tx, nil) } else { r := request.Input.(client.ReadInvitesRequest) if r.Id != "" { - dbInvites, err = idp.FetchInvites(tx, requestedBy, []idp.Invite{ {Identity:idp.Identity{Id:r.Id}} }) + dbInvites, err = idp.FetchInvites(ctx, tx, []idp.Invite{ {Identity:idp.Identity{Id:r.Id}} }) } else if r.Email != "" { - dbInvites, err = idp.FetchInvitesByEmail(tx, requestedBy, []idp.Invite{ {Email:r.Email} }) + dbInvites, err = idp.FetchInvitesByEmail(ctx, tx, []idp.Invite{ {Email:r.Email} }) } //else if r.Username != "" { // dbInvites, err = idp.FetchInvitesByUsername(env.Driver, []string{r.Username}) diff --git a/endpoints/invites/send.go b/endpoints/invites/send.go index b241b36..34de240 100644 --- a/endpoints/invites/send.go +++ b/endpoints/invites/send.go @@ -3,6 +3,7 @@ package invites import ( "net/url" "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -25,6 +26,8 @@ type InviteTemplateData struct { func PostInvitesSend(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostInvitesSend", @@ -62,35 +65,19 @@ func PostInvitesSend(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(ctx, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - requestor := c.MustGet("sub").(string) - var requestedBy *idp.Identity - if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - if err != nil { - bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - log.Debug(err.Error()) - return - } - if len(identities) > 0 { - requestedBy = &identities[0] - } - } for _, request := range iRequests { r := request.Input.(client.CreateInvitesSendRequest) log = log.WithFields(logrus.Fields{"id": r.Id}) - dbInvites, err := idp.FetchInvites(tx, requestedBy, []idp.Invite{ {Identity:idp.Identity{Id:r.Id}} }) + dbInvites, err := idp.FetchInvites(ctx, tx, []idp.Invite{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -129,7 +116,7 @@ func PostInvitesSend(env *app.Environment) gin.HandlerFunc { return } - updatedInvite, err := idp.UpdateInviteSentAt(tx, requestedBy, invite) + updatedInvite, err := idp.UpdateInviteSentAt(ctx, tx, invite) if err != nil { e := tx.Rollback() if e != nil { diff --git a/endpoints/resourceservers/resourceservers.go b/endpoints/resourceservers/resourceservers.go index a8371b9..6f4aea1 100644 --- a/endpoints/resourceservers/resourceservers.go +++ b/endpoints/resourceservers/resourceservers.go @@ -2,6 +2,7 @@ package resourceservers import ( "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -18,6 +19,9 @@ import ( func GetResourceServers(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "GetResourceServers", @@ -32,28 +36,12 @@ func GetResourceServers(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginReadTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - requestor := c.MustGet("sub").(string) - var requestedBy *idp.Identity - if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - if err != nil { - bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - log.Debug(err.Error()) - return - } - if len(identities) > 0 { - requestedBy = &identities[0] - } - } for _, request := range iRequests { @@ -62,10 +50,10 @@ func GetResourceServers(env *app.Environment) gin.HandlerFunc { var ok client.ReadResourceServersResponse if request.Input == nil { - dbResourceServers, err = idp.FetchResourceServers(tx, requestedBy, nil) + dbResourceServers, err = idp.FetchResourceServers(ctx, tx, nil) } else { r := request.Input.(client.ReadResourceServersRequest) - dbResourceServers, err = idp.FetchResourceServers(tx, requestedBy, []idp.ResourceServer{ {Identity:idp.Identity{Id: r.Id}} }) + dbResourceServers, err = idp.FetchResourceServers(ctx, tx, []idp.ResourceServer{ {Identity:idp.Identity{Id: r.Id}} }) } if err != nil { e := tx.Rollback() @@ -115,6 +103,8 @@ func GetResourceServers(env *app.Environment) gin.HandlerFunc { func PostResourceServers(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostResourceServers", @@ -129,19 +119,17 @@ func PostResourceServers(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() requestor := c.MustGet("sub").(string) var requestedBy *idp.Identity if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) + identities, err := idp.FetchIdentities(ctx, tx, []idp.Identity{ {Id:requestor} }) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) @@ -166,7 +154,7 @@ func PostResourceServers(env *app.Environment) gin.HandlerFunc { Audience: r.Audience, } - resourceServer, err := idp.CreateResourceServer(tx, requestedBy, newResourceServer) + resourceServer, err := idp.CreateResourceServer(ctx, tx, newResourceServer) if err != nil { e := tx.Rollback() if e != nil { @@ -291,6 +279,8 @@ func PostResourceServers(env *app.Environment) gin.HandlerFunc { func DeleteResourceServers(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "DeleteResourceServers", @@ -305,35 +295,19 @@ func DeleteResourceServers(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - requestor := c.MustGet("sub").(string) - var requestedBy *idp.Identity - if requestor != "" { - identities, err := idp.FetchIdentities(tx, []idp.Identity{ {Id:requestor} }) - if err != nil { - bulky.FailAllRequestsWithInternalErrorResponse(iRequests) - log.Debug(err.Error()) - return - } - if len(identities) > 0 { - requestedBy = &identities[0] - } - } - - for _, request := range iRequests { + for _, request := range iRequests { r := request.Input.(client.DeleteResourceServersRequest) log = log.WithFields(logrus.Fields{"id": r.Id}) - dbResourceServers, err := idp.FetchResourceServers(tx, requestedBy, []idp.ResourceServer{ {Identity:idp.Identity{Id:r.Id}} }) + dbResourceServers, err := idp.FetchResourceServers(ctx, tx, []idp.ResourceServer{ {Identity:idp.Identity{Id:r.Id}} }) if err != nil { e := tx.Rollback() if e != nil { @@ -355,7 +329,7 @@ func DeleteResourceServers(env *app.Environment) gin.HandlerFunc { if resourceServerToDelete != (idp.ResourceServer{}) { - deletedResourceServer, err := idp.DeleteResourceServer(tx, requestedBy, resourceServerToDelete) + deletedResourceServer, err := idp.DeleteResourceServer(ctx, tx, resourceServerToDelete) if err != nil { e := tx.Rollback() if e != nil { diff --git a/endpoints/roles/roles.go b/endpoints/roles/roles.go index eae79cb..625ddcb 100644 --- a/endpoints/roles/roles.go +++ b/endpoints/roles/roles.go @@ -2,6 +2,7 @@ package roles import ( "net/http" + "context" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -18,6 +19,9 @@ import ( func GetRoles(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "GetRoles", @@ -32,16 +36,12 @@ func GetRoles(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginReadTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() - - requestor := c.MustGet("sub").(string) for _, request := range iRequests { var dbRoles []idp.Role @@ -49,10 +49,10 @@ func GetRoles(env *app.Environment) gin.HandlerFunc { var ok client.ReadRolesResponse if request.Input == nil { - dbRoles, err = idp.FetchRoles(tx, nil, idp.Identity{Id:requestor}) + dbRoles, err = idp.FetchRoles(ctx, tx, nil) } else { r := request.Input.(client.ReadRolesRequest) - dbRoles, err = idp.FetchRoles(tx, []idp.Role{ {Identity: idp.Identity{Id: r.Id}} }, idp.Identity{Id:requestor}) + dbRoles, err = idp.FetchRoles(ctx, tx, []idp.Role{ {Identity: idp.Identity{Id: r.Id}} }) } if err != nil { e := tx.Rollback() @@ -101,6 +101,8 @@ func GetRoles(env *app.Environment) gin.HandlerFunc { func PostRoles(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "PostRoles", @@ -115,14 +117,12 @@ func PostRoles(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() requestor := c.MustGet("sub").(string) @@ -139,7 +139,7 @@ func PostRoles(env *app.Environment) gin.HandlerFunc { Description: r.Description, } - dbRole, err := idp.CreateRole(tx, newRole, idp.Identity{Id:requestor}) + dbRole, err := idp.CreateRole(ctx, tx, newRole) if err != nil { e := tx.Rollback() if e != nil { @@ -263,6 +263,8 @@ func PostRoles(env *app.Environment) gin.HandlerFunc { func DeleteRoles(env *app.Environment) gin.HandlerFunc { fn := func(c *gin.Context) { + ctx := context.TODO() + log := c.MustGet(env.Constants.LogKey).(*logrus.Entry) log = log.WithFields(logrus.Fields{ "func": "DeleteRoles", @@ -277,14 +279,12 @@ func DeleteRoles(env *app.Environment) gin.HandlerFunc { var handleRequests = func(iRequests []*bulky.Request) { - session, tx, err := idp.BeginWriteTx(env.Driver) + tx, err := env.Driver.BeginTx(c, nil) if err != nil { bulky.FailAllRequestsWithInternalErrorResponse(iRequests) log.Debug(err.Error()) return } - defer tx.Close() // rolls back if not already committed/rolled back - defer session.Close() requestor := c.MustGet("sub").(string) @@ -293,7 +293,7 @@ func DeleteRoles(env *app.Environment) gin.HandlerFunc { log = log.WithFields(logrus.Fields{"id": requestor}) - dbRoles, err := idp.FetchRoles(tx, []idp.Role{ {Identity: idp.Identity{Id:r.Id}} }, idp.Identity{Id:requestor}) + dbRoles, err := idp.FetchRoles(ctx, tx, []idp.Role{ {Identity: idp.Identity{Id:r.Id}} }) if err != nil { request.Output = bulky.NewInternalErrorResponse(request.Index) log.Debug(err.Error()) @@ -310,7 +310,7 @@ func DeleteRoles(env *app.Environment) gin.HandlerFunc { if roleToDelete != (idp.Role{}) { - dbDeletedRole, err := idp.DeleteRole(tx, roleToDelete, idp.Identity{Id:requestor}) + dbDeletedRole, err := idp.DeleteRole(ctx, tx, roleToDelete) if err != nil { e := tx.Rollback() if e != nil { diff --git a/gateway/idp/challenges.go b/gateway/idp/challenges.go index 598caa0..10e477f 100644 --- a/gateway/idp/challenges.go +++ b/gateway/idp/challenges.go @@ -4,19 +4,21 @@ import ( "errors" "strings" "fmt" - "github.com/neo4j/neo4j-go-driver/neo4j" + "context" + "database/sql" + "github.com/google/uuid" ) -func CreateChallengeUsingTotp(tx neo4j.Transaction, challengeType ChallengeType, newChallenge Challenge) (challenge Challenge, err error) { +func CreateChallengeUsingTotp(ctx context.Context, tx *sql.Tx, challengeType ChallengeType, newChallenge Challenge) (challenge Challenge, err error) { newChallenge.Code = "" // Do not set this on TOTP requests - challenge, err = createChallenge(tx, newChallenge, ChallengeAuthenticate) + challenge, err = createChallenge(ctx, tx, newChallenge, ChallengeAuthenticate) if err != nil { return Challenge{}, err } return challenge, nil } -func CreateChallengeUsingOtp(tx neo4j.Transaction, challengeType ChallengeType, newChallenge Challenge) (challenge Challenge, otpCode ChallengeCode, err error) { +func CreateChallengeUsingOtp(ctx context.Context, tx *sql.Tx, challengeType ChallengeType, newChallenge Challenge) (challenge Challenge, otpCode ChallengeCode, err error) { otpCode, err = CreateChallengeCode() if err != nil { return Challenge{}, ChallengeCode{}, err @@ -28,15 +30,14 @@ func CreateChallengeUsingOtp(tx neo4j.Transaction, challengeType ChallengeType, } newChallenge.Code = hashedCode - challenge, err = createChallenge(tx, newChallenge, challengeType) + challenge, err = createChallenge(ctx, tx, newChallenge, challengeType) if err != nil { return Challenge{}, ChallengeCode{}, err } return challenge, otpCode, nil } -func createChallenge(tx neo4j.Transaction, newChallenge Challenge, challengeType ChallengeType) (challenge Challenge, err error) { - var result neo4j.Result +func createChallenge(ctx context.Context, tx *sql.Tx, newChallenge Challenge, challengeType ChallengeType) (challenge Challenge, err error) { var cypher string var params = make(map[string]interface{}) @@ -67,6 +68,11 @@ func createChallenge(tx neo4j.Transaction, newChallenge Challenge, challengeType params["data"] = newChallenge.Data } + uuid, err := uuid.NewRandom() + if err != nil { + return Challenge{}, err + } + cypChallengeType := "" switch (challengeType) { case ChallengeAuthenticate: @@ -83,6 +89,7 @@ func createChallenge(tx neo4j.Transaction, newChallenge Challenge, challengeType return Challenge{}, errors.New("Unsupported challenge type") } + // TODO SQL cypher = fmt.Sprintf(` MATCH (i:Identity {id:$sub}) MERGE (c:Challenge%s { @@ -100,33 +107,21 @@ func createChallenge(tx neo4j.Transaction, newChallenge Challenge, challengeType RETURN c `, cypChallengeType, cypData) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Challenge{}, err } - if result.Next() { - record := result.Record() - challengeNode := record.GetByIndex(0) - - if challengeNode != nil { - challenge = marshalNodeToChallenge(challengeNode.(neo4j.Node)) - } - } else { - return Challenge{}, errors.New("Unable to create Challenge") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + challenges, err := FetchChallenges(ctx, tx, []Challenge{{ Id: uuid.String() }} ) + if err != nil { return Challenge{}, err } - return challenge, nil + return challenges[0], nil } -func FetchChallenges(tx neo4j.Transaction, iChallenges []Challenge) (challenges []Challenge, err error) { - var result neo4j.Result +func FetchChallenges(ctx context.Context, tx *sql.Tx, iChallenges []Challenge) (challenges []Challenge, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) @@ -140,38 +135,26 @@ func FetchChallenges(tx neo4j.Transaction, iChallenges []Challenge) (challenges params["ids"] = strings.Join(ids, ",") } + // TODO SQL cypher = fmt.Sprintf(` MATCH (c:Challenge) WHERE c.exp > datetime().epochSeconds %s RETURN c `, cypfilterChallenges) - if result, err = tx.Run(cypher, params); err != nil { + rows, err = tx.QueryContext(ctx, cypher, params); + if err != nil { return nil, err } - for result.Next() { - record := result.Record() - challengeNode := record.GetByIndex(0) - - if challengeNode != nil { - i := marshalNodeToChallenge(challengeNode.(neo4j.Node)) - - challenges = append(challenges, i) - } - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + i := marshalRowToChallenge(rows) + challenges = append(challenges, i) } return challenges, nil } -func VerifyChallenge(tx neo4j.Transaction, challengeToUpdate Challenge) (updatedChallenge Challenge, err error) { - var result neo4j.Result +func VerifyChallenge(ctx context.Context, tx *sql.Tx, challengeToUpdate Challenge) (updatedChallenge Challenge, err error) { var cypher string var params = make(map[string]interface{}) @@ -186,27 +169,15 @@ func VerifyChallenge(tx neo4j.Transaction, challengeToUpdate Challenge) (updated RETURN c `) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Challenge{}, err } - if result.Next() { - record := result.Record() - challengeNode := record.GetByIndex(0) - - if challengeNode != nil { - updatedChallenge = marshalNodeToChallenge(challengeNode.(neo4j.Node)) - } - } else { - return Challenge{}, errors.New("Unable to set Challenge verified. Hint: Challenge might be expired or non existant.") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + challenges, err := FetchChallenges(ctx, tx, []Challenge{ challengeToUpdate } ) + if err != nil { return Challenge{}, err } - return updatedChallenge, nil + return challenges[0], nil } diff --git a/gateway/idp/clients.go b/gateway/idp/clients.go index 1ae9f5a..9f1cebc 100644 --- a/gateway/idp/clients.go +++ b/gateway/idp/clients.go @@ -4,11 +4,12 @@ import ( "errors" "strings" "fmt" - "github.com/neo4j/neo4j-go-driver/neo4j" + "context" + "database/sql" + "github.com/google/uuid" ) -func CreateClient(tx neo4j.Transaction, managedBy *Identity, newClient Client) (client Client, err error) { - var result neo4j.Result +func CreateClient(ctx context.Context, tx *sql.Tx, newClient Client) (client Client, err error) { var cypher string var params = make(map[string]interface{}) @@ -36,6 +37,11 @@ func CreateClient(tx neo4j.Transaction, managedBy *Identity, newClient Client) ( params["audiences"] = []string{} params["tokenEndpointAuthMethod"] = "" + uuid, err := uuid.NewRandom() + if err != nil { + return Client{}, err + } + if len(newClient.GrantTypes) > 0 { params["grantTypes"] = newClient.GrantTypes } @@ -61,12 +67,7 @@ func CreateClient(tx neo4j.Transaction, managedBy *Identity, newClient Client) ( cypClientSecret = `secret:$client_secret,` } - cypManages := "" - if managedBy != nil { - params["managed_by"] = managedBy.Id - cypManages = `MATCH (i:Identity {id:$managed_by}) MERGE (i)-[:MANAGES]->(c)` - } - + // TODO SQL cypher = fmt.Sprintf(` CREATE (c:Client:Identity { id:randomUUID(), @@ -86,48 +87,27 @@ func CreateClient(tx neo4j.Transaction, managedBy *Identity, newClient Client) ( WITH c - %s - RETURN c - `, cypClientSecret, cypManages) + `, cypClientSecret) - logCypher(cypher, params) - - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Client{}, err } - if result.Next() { - record := result.Record() - clientNode := record.GetByIndex(0) - - if clientNode != nil { - client = marshalNodeToClient(clientNode.(neo4j.Node)) - } - } else { - return Client{}, errors.New("Unable to create Client") - } - - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + clients, err := FetchClients(ctx, tx, []Client{ { Identity: Identity{Id: uuid.String()} } }) + if err != nil { return Client{}, err } - return client, nil + return clients[0], nil } -func FetchClients(tx neo4j.Transaction, managedBy *Identity, iClients []Client) (clients []Client, err error) { - var result neo4j.Result +func FetchClients(ctx context.Context, tx *sql.Tx, iClients []Client) (clients []Client, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) - var cypManages string - if managedBy != nil { - cypManages = `(i:Identity {id:$managed_by})-[:MANAGES]->` - params["managed_by"] = managedBy.Id - } - cypFilterClients := "" if len(iClients) > 0 { var ids []string @@ -138,37 +118,26 @@ func FetchClients(tx neo4j.Transaction, managedBy *Identity, iClients []Client) params["ids"] = strings.Join(ids, ",") } + // TODO SQL cypher = fmt.Sprintf(` - MATCH %s(c:Client:Identity) WHERE 1=1 %s + MATCH (c:Client:Identity) WHERE 1=1 %s RETURN c - `, cypManages, cypFilterClients) + `, cypFilterClients) - if result, err = tx.Run(cypher, params); err != nil { + rows, err = tx.QueryContext(ctx, cypher, params) + if err != nil { return nil, err } - for result.Next() { - record := result.Record() - clientNode := record.GetByIndex(0) - - if clientNode != nil { - client := marshalNodeToClient(clientNode.(neo4j.Node)) - clients = append(clients, client) - } - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + client := marshalRowToClient(rows) + clients = append(clients, client) } return clients, nil } -func DeleteClient(tx neo4j.Transaction, managedBy *Identity, clientToDelete Client) (client Client, err error) { - var result neo4j.Result +func DeleteClient(ctx context.Context, tx *sql.Tx, clientToDelete Client) (client Client, err error) { var cypher string var params = make(map[string]interface{}) @@ -177,30 +146,15 @@ func DeleteClient(tx neo4j.Transaction, managedBy *Identity, clientToDelete Clie } params["id"] = clientToDelete.Id - var cypManages string - if managedBy != nil { - cypManages = `(i:Identity {id:$managed_by})-[:MANAGES]->` - params["managed_by"] = managedBy.Id - } - - params["id"] = clientToDelete.Id - // Warning: Do not accidentally delete i! + // TODO SQL cypher = fmt.Sprintf(` - MATCH %s(c:Client:Identity {id:$id}) + MATCH (c:Client:Identity {id:$id}) DETACH DELETE c - `, cypManages) - - if result, err = tx.Run(cypher, params); err != nil { - return Client{}, err - } - - result.Next() - - logCypher(cypher, params) + `) - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Client{}, err } diff --git a/gateway/idp/humans.go b/gateway/idp/humans.go index b724e18..189ab4c 100644 --- a/gateway/idp/humans.go +++ b/gateway/idp/humans.go @@ -2,13 +2,14 @@ package idp import ( "errors" + "context" "strings" "fmt" - "github.com/neo4j/neo4j-go-driver/neo4j" + "database/sql" + "github.com/google/uuid" ) -func CreateHumanFromInvite(tx neo4j.Transaction, newHuman Human) (human Human, err error) { - var result neo4j.Result +func CreateHumanFromInvite(ctx context.Context, tx *sql.Tx, newHuman Human) (human Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -39,6 +40,7 @@ func CreateHumanFromInvite(tx neo4j.Transaction, newHuman Human) (human Human, e params["password"] = newHuman.Password params["email_confirmed_at"] = newHuman.EmailConfirmedAt + // TODO SQL cypher = fmt.Sprintf(` MATCH (i:Invite:Identity {id:$id}) SET i.email_confirmed_at=$email_confirmed_at, @@ -58,33 +60,20 @@ func CreateHumanFromInvite(tx neo4j.Transaction, newHuman Human) (human Human, e RETURN i `) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Human{}, err } - if result.Next() { - record := result.Record() - humanNode := record.GetByIndex(0) - - if humanNode != nil { - human = marshalNodeToHuman(humanNode.(neo4j.Node)) - } - } else { - return Human{}, errors.New("Unable to create Human") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + humans, err := FetchHumans(ctx, tx, []Human{ newHuman } ) + if err != nil { return Human{}, err } - return human, nil + return humans[0], nil } -func CreateHuman(tx neo4j.Transaction, newHuman Human) (human Human, err error) { - var result neo4j.Result +func CreateHuman(ctx context.Context, tx *sql.Tx, newHuman Human) (human Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -108,6 +97,11 @@ func CreateHuman(tx neo4j.Transaction, newHuman Human) (human Human, err error) return Human{}, errors.New("Missing Human.Password") } + uuid, err := uuid.NewRandom() + if err != nil { + return Human{}, err + } + params["iss"] = newHuman.Issuer params["exp"] = newHuman.ExpiresAt params["email"] = newHuman.Email @@ -116,6 +110,7 @@ func CreateHuman(tx neo4j.Transaction, newHuman Human) (human Human, err error) params["allow_login"] = newHuman.AllowLogin params["password"] = newHuman.Password + // TODO SQL cypher = fmt.Sprintf(` CREATE (i:Human:Identity { id: randomUUID(), @@ -140,32 +135,20 @@ func CreateHuman(tx neo4j.Transaction, newHuman Human) (human Human, err error) RETURN i `) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Human{}, err } - if result.Next() { - record := result.Record() - humanNode := record.GetByIndex(0) - - if humanNode != nil { - human = marshalNodeToHuman(humanNode.(neo4j.Node)) - } - } else { - return Human{}, errors.New("Unable to create Human") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + humans, err := FetchHumans(ctx, tx, []Human{{ Identity: Identity{Id:uuid.String()} }} ) + if err != nil { return Human{}, err } - return human, nil + return humans[0], nil } -func FetchHumans(tx neo4j.Transaction, iHumans []Human) (humans []Human, err error) { +func FetchHumans(ctx context.Context, tx *sql.Tx, iHumans []Human) (humans []Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -179,16 +162,17 @@ func FetchHumans(tx neo4j.Transaction, iHumans []Human) (humans []Human, err err params["ids"] = strings.Join(ids, ",") } + // TODO SQL cypher = fmt.Sprintf(` MATCH (h:Human:Identity) %s RETURN h `, cypfilterIds) - humans, err = fetchHumansByQuery(tx, cypher, params) + humans, err = fetchHumansByQuery(ctx, tx, cypher, params) return humans, err } -func FetchHumansByEmail(tx neo4j.Transaction, iHumans []Human) (humans []Human, err error) { +func FetchHumansByEmail(ctx context.Context, tx *sql.Tx, iHumans []Human) (humans []Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -202,16 +186,17 @@ func FetchHumansByEmail(tx neo4j.Transaction, iHumans []Human) (humans []Human, params["emails"] = strings.Join(emails, ",") } + // TODO SQL cypher = fmt.Sprintf(` MATCH (h:Human:Identity) %s RETURN h `, cypfilterEmails) - humans, err = fetchHumansByQuery(tx, cypher, params) + humans, err = fetchHumansByQuery(ctx, tx, cypher, params) return humans, err } -func FetchHumansByUsername(tx neo4j.Transaction, iHumans []Human) (humans []Human, err error) { +func FetchHumansByUsername(ctx context.Context, tx *sql.Tx, iHumans []Human) (humans []Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -225,37 +210,27 @@ func FetchHumansByUsername(tx neo4j.Transaction, iHumans []Human) (humans []Huma params["usernames"] = strings.Join(usernames, ",") } + // TODO SQL cypher = fmt.Sprintf(` MATCH (h:Human:Identity) %s RETURN h `, cypfilterUsernames) - humans, err = fetchHumansByQuery(tx, cypher, params) + humans, err = fetchHumansByQuery(ctx, tx, cypher, params) return humans, err } -func fetchHumansByQuery(tx neo4j.Transaction, cypher string, params map[string]interface{}) (humans []Human, err error) { - var result neo4j.Result +func fetchHumansByQuery(ctx context.Context, tx *sql.Tx, cypher string, params map[string]interface{}) (humans []Human, err error) { + var rows *sql.Rows - if result, err = tx.Run(cypher, params); err != nil { + rows, err = tx.QueryContext(ctx, cypher, params) + if err != nil { return nil, err } - for result.Next() { - record := result.Record() - humanNode := record.GetByIndex(0) - - if humanNode != nil { - human := marshalNodeToHuman(humanNode.(neo4j.Node)) - humans = append(humans, human) - } - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + human := marshalRowToHuman(rows) + humans = append(humans, human) } return humans, nil @@ -263,8 +238,8 @@ func fetchHumansByQuery(tx neo4j.Transaction, cypher string, params map[string]i // NOTE: This can update everything that is _NOT_ sensitive to the authentication process like Identity.Password // To change the password see recover for that or iff identified UpdatePassword -func UpdateHuman(tx neo4j.Transaction, newHuman Human) (human Human, err error) { - var result neo4j.Result +func UpdateHuman(ctx context.Context, tx *sql.Tx, newHuman Human) (human Human, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) @@ -279,39 +254,28 @@ func UpdateHuman(tx neo4j.Transaction, newHuman Human) (human Human, err error) params["id"] = newHuman.Id params["name"] = newHuman.Name + // TODO SQL cypher = fmt.Sprintf(` MATCH (i:Human:Identity {id:$id}) SET i.name=$name RETURN i `) - if result, err = tx.Run(cypher, params); err != nil { + rows, err = tx.QueryContext(ctx, cypher, params) + if err != nil { return Human{}, err } - if result.Next() { - record := result.Record() - humanNode := record.GetByIndex(0) - - if humanNode != nil { - human = marshalNodeToHuman(humanNode.(neo4j.Node)) - } + if rows.Next() { + human = marshalRowToHuman(rows) } else { return Human{}, errors.New("Unable to update Human") } - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return Human{}, err - } - return human, nil } -func ConfirmEmail(tx neo4j.Transaction, newHuman Human) (human Human, err error) { - var result neo4j.Result +func ConfirmEmail(ctx context.Context, tx *sql.Tx, newHuman Human) (human Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -321,39 +285,27 @@ func ConfirmEmail(tx neo4j.Transaction, newHuman Human) (human Human, err error) params["id"] = newHuman.Id + // TODO SQL cypher = fmt.Sprintf(` MATCH (i:Human:Identity {id:$id, email_confirmed_at:0}) SET i.email_confirmed_at=datetime().epochSeconds RETURN i `) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Human{}, err } - if result.Next() { - record := result.Record() - humanNode := record.GetByIndex(0) - - if humanNode != nil { - human = marshalNodeToHuman(humanNode.(neo4j.Node)) - } - } else { - return Human{}, errors.New("Unable to confirm email for human") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + humans, err := FetchHumans(ctx, tx, []Human{ newHuman }) + if err != nil { return Human{}, err } - return human, nil + return humans[0], nil } -func UpdatePassword(tx neo4j.Transaction, newHuman Human) (human Human, err error) { - var result neo4j.Result +func UpdatePassword(ctx context.Context, tx *sql.Tx, newHuman Human) (human Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -368,39 +320,27 @@ func UpdatePassword(tx neo4j.Transaction, newHuman Human) (human Human, err erro params["id"] = newHuman.Id params["password"] = newHuman.Password + // TODO SQL cypher = fmt.Sprintf(` MATCH (i:Human:Identity {id:$id}) SET i.password=$password RETURN i `) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Human{}, err } - if result.Next() { - record := result.Record() - humanNode := record.GetByIndex(0) - - if humanNode != nil { - human = marshalNodeToHuman(humanNode.(neo4j.Node)) - } - } else { - return Human{}, errors.New("Unable to update password for human") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + humans, err := FetchHumans(ctx, tx, []Human{ newHuman }) + if err != nil { return Human{}, err } - return human, nil + return humans[0], nil } -func UpdateEmail(tx neo4j.Transaction, newHuman Human) (human Human, err error) { - var result neo4j.Result +func UpdateEmail(ctx context.Context, tx *sql.Tx, newHuman Human) (human Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -415,39 +355,27 @@ func UpdateEmail(tx neo4j.Transaction, newHuman Human) (human Human, err error) params["id"] = newHuman.Id params["email"] = newHuman.Email + // TODO SQL cypher = fmt.Sprintf(` MATCH (i:Human:Identity {id:$id}) SET i.email=$email RETURN i `) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Human{}, err } - if result.Next() { - record := result.Record() - humanNode := record.GetByIndex(0) - - if humanNode != nil { - human = marshalNodeToHuman(humanNode.(neo4j.Node)) - } - } else { - return Human{}, errors.New("Unable to update email for human") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + humans, err := FetchHumans(ctx, tx, []Human{ newHuman }) + if err != nil { return Human{}, err } - return human, nil + return humans[0], nil } -func UpdateAllowLogin(tx neo4j.Transaction, newHuman Human) (human Human, err error) { - var result neo4j.Result +func UpdateAllowLogin(ctx context.Context, tx *sql.Tx, newHuman Human) (human Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -458,39 +386,27 @@ func UpdateAllowLogin(tx neo4j.Transaction, newHuman Human) (human Human, err er params["id"] = newHuman.Id params["allow_login"] = newHuman.AllowLogin + // TODO SQL cypher = fmt.Sprintf(` MATCH (i:Human:Identity {id:$id}) SET i.allow_login=$allow_login RETURN i `) - if result, err = tx.Run(cypher, params); err != nil { - return Human{}, err - } - - if result.Next() { - record := result.Record() - humanNode := record.GetByIndex(0) - - if humanNode != nil { - human = marshalNodeToHuman(humanNode.(neo4j.Node)) - } - } else { - return Human{}, errors.New("Unable to update allow login for human") + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { + return Human{}, err } - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + humans, err := FetchHumans(ctx, tx, []Human{ newHuman }) + if err != nil { return Human{}, err } - return human, nil + return humans[0], nil } -func UpdateTotp(tx neo4j.Transaction, newHuman Human) (human Human, err error) { - var result neo4j.Result +func UpdateTotp(ctx context.Context, tx *sql.Tx, newHuman Human) (human Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -506,6 +422,7 @@ func UpdateTotp(tx neo4j.Transaction, newHuman Human) (human Human, err error) { params["totp_required"] = newHuman.TotpRequired params["totp_secret"] = newHuman.TotpSecret + // TODO SQL cypher = fmt.Sprintf(` MATCH (i:Human:Identity {id:$id}) SET i.totp_required=$totp_required, @@ -513,33 +430,20 @@ func UpdateTotp(tx neo4j.Transaction, newHuman Human) (human Human, err error) { RETURN i `) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Human{}, err } - if result.Next() { - record := result.Record() - humanNode := record.GetByIndex(0) - - if humanNode != nil { - human = marshalNodeToHuman(humanNode.(neo4j.Node)) - } - } else { - return Human{}, errors.New("Unable to update TOTP for human") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + humans, err := FetchHumans(ctx, tx, []Human{ newHuman }) + if err != nil { return Human{}, err } - return human, nil + return humans[0], nil } -func DeleteHuman(tx neo4j.Transaction, newHuman Human) (human Human, err error) { - var result neo4j.Result +func DeleteHuman(ctx context.Context, tx *sql.Tx, newHuman Human) (human Human, err error) { var cypher string var params = make(map[string]interface{}) @@ -549,24 +453,17 @@ func DeleteHuman(tx neo4j.Transaction, newHuman Human) (human Human, err error) params["id"] = newHuman.Id + // TODO SQL cypher = fmt.Sprintf(` MATCH (i:Human:Identity {id:$id}) DETACH DELETE i `) - if result, err = tx.Run(cypher, params); err != nil { - return Human{}, err - } - - result.Next() - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Human{}, err } human.Id = newHuman.Id return human, nil -} \ No newline at end of file +} diff --git a/gateway/idp/identities.go b/gateway/idp/identities.go index db5d19e..59a84c1 100644 --- a/gateway/idp/identities.go +++ b/gateway/idp/identities.go @@ -3,14 +3,12 @@ package idp import ( "fmt" "strings" - "github.com/neo4j/neo4j-go-driver/neo4j" + "context" + "database/sql" ) -// You should never make these, please specialize with another label, see client.go or human.go -// func CreateIdentities(driver neo4j.Driver, identities []Identity) ([]Identity, error) - -func FetchIdentities(tx neo4j.Transaction, iIdentities []Identity) (identities []Identity, err error) { - var result neo4j.Result +func FetchIdentities(ctx context.Context, tx *sql.Tx, iIdentities []Identity) (identities []Identity, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) @@ -28,32 +26,20 @@ func FetchIdentities(tx neo4j.Transaction, iIdentities []Identity) (identities [ MATCH (i:Identity) WHERE 1=1 %s RETURN i `, cypFilterIdentities) - logCypher(cypher, params) - if result, err = tx.Run(cypher, params); err != nil { + if rows, err = tx.QueryContext(ctx, cypher, params); err != nil { return nil, err } - for result.Next() { - record := result.Record() - identityNode := record.GetByIndex(0) - - if identityNode != nil { - i := marshalNodeToIdentity(identityNode.(neo4j.Node)) - - identities = append(identities, i) - } - } - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + i := marshalRowToIdentity(rows) + identities = append(identities, i) } return identities, nil } -func SearchIdentities(tx neo4j.Transaction, iSearch string) (identities []Identity, err error) { - var result neo4j.Result +func SearchIdentities(ctx context.Context, tx *sql.Tx, iSearch string) (identities []Identity, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) @@ -67,25 +53,13 @@ func SearchIdentities(tx neo4j.Transaction, iSearch string) (identities []Identi MATCH (i:Identity) WHERE 1=1 %s RETURN i `, cypFilterIdentities) - if result, err = tx.Run(cypher, params); err != nil { + if rows, err = tx.QueryContext(ctx, cypher, params); err != nil { return nil, err } - logCypher(cypher, params) - for result.Next() { - record := result.Record() - identityNode := record.GetByIndex(0) - - if identityNode != nil { - i := marshalNodeToIdentity(identityNode.(neo4j.Node)) - - identities = append(identities, i) - } - } - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + i := marshalRowToIdentity(rows) + identities = append(identities, i) } return identities, nil diff --git a/gateway/idp/invites.go b/gateway/idp/invites.go index 6f5a8c1..6d55b42 100644 --- a/gateway/idp/invites.go +++ b/gateway/idp/invites.go @@ -4,11 +4,12 @@ import ( "errors" "fmt" "strings" - "github.com/neo4j/neo4j-go-driver/neo4j" + "context" + "database/sql" + "github.com/google/uuid" ) -func UpdateInviteSentAt(tx neo4j.Transaction, updatedBy *Identity, inviteToUpdate Invite) (invite Invite, err error) { - var result neo4j.Result +func UpdateInviteSentAt(ctx context.Context, tx *sql.Tx, inviteToUpdate Invite) (invite Invite, err error) { var cypher string var params = make(map[string]interface{}) @@ -28,33 +29,20 @@ func UpdateInviteSentAt(tx neo4j.Transaction, updatedBy *Identity, inviteToUpdat RETURN inv `) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Invite{}, err } - if result.Next() { - record := result.Record() - inviteNode := record.GetByIndex(0) + invites, err := FetchInvites(ctx, tx, []Invite{ inviteToUpdate }) + if err != nil { + return Invite{}, nil + } - if inviteNode != nil { - invite = marshalNodeToInvite(inviteNode.(neo4j.Node)) - } - } else { - return Invite{}, errors.New("Unable to update Invite") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return Invite{}, err - } - - return invite, nil + return invites[0], nil } -func CreateInvite(tx neo4j.Transaction, invitedBy *Identity, newInvite Invite) (invite Invite, err error) { - var result neo4j.Result +func CreateInvite(ctx context.Context, tx *sql.Tx, newInvite Invite) (invite Invite, err error) { var cypher string var params = make(map[string]interface{}) @@ -76,62 +64,39 @@ func CreateInvite(tx neo4j.Transaction, invitedBy *Identity, newInvite Invite) ( params["exp"] = newInvite.ExpiresAt - cypInvites := "" - if invitedBy != nil { - params["invited_by"] = invitedBy.Id - cypInvites = `MATCH (i:Identity {id:$invited_by}) MERGE (i)-[:INVITES]->(inv)` - } + uuid, err := uuid.NewRandom() + if err != nil { + return Invite{}, err + } + // TODO SQL cypher = fmt.Sprintf(` CREATE (inv:Invite:Identity {id:randomUUID(), email:$email, iat:datetime().epochSeconds, iss:$iss, exp:$exp, sent_at:0, email_confirmed_at:0 %s}) WITH inv - %s - - WITH inv - OPTIONAL MATCH (d:Invite:Identity) WHERE id(inv) <> id(d) AND d.exp < datetime().epochSeconds DETACH DELETE d RETURN inv - `, cypUsername, cypInvites) + `, cypUsername) - if result, err = tx.Run(cypher, params); err != nil { + if _, err = tx.ExecContext(ctx, cypher, params); err != nil { return Invite{}, err } - if result.Next() { - record := result.Record() - inviteNode := record.GetByIndex(0) + invites, err := FetchInvites(ctx, tx, []Invite{ {Identity: Identity{Id: uuid.String()}} }) + if err != nil { + return Invite{}, nil + } - if inviteNode != nil { - invite = marshalNodeToInvite(inviteNode.(neo4j.Node)) - } - } else { - return Invite{}, errors.New("Unable to create Invite") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return Invite{}, err - } - - return invite, nil + return invites[0], nil } -func FetchInvites(tx neo4j.Transaction, invitedBy *Identity, iInvites []Invite) (invites []Invite, err error) { - var result neo4j.Result +func FetchInvites(ctx context.Context, tx *sql.Tx, iInvites []Invite) (invites []Invite, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) - var cypInvites string - if invitedBy != nil { - cypInvites = `(i:Identity {id:$invited_by})-[:INVITES]->` - params["invited_by"] = invitedBy.Id - } - cypfilterInvites := "" if len(iInvites) > 0 { var ids []string @@ -142,46 +107,29 @@ func FetchInvites(tx neo4j.Transaction, invitedBy *Identity, iInvites []Invite) params["ids"] = strings.Join(ids, ",") } + // TODO SQL cypher = fmt.Sprintf(` - MATCH %s(inv:Invite:Identity) WHERE inv.exp > datetime().epochSeconds %s + MATCH (inv:Invite:Identity) WHERE inv.exp > datetime().epochSeconds %s RETURN inv - `, cypInvites, cypfilterInvites) + `, cypfilterInvites) - if result, err = tx.Run(cypher, params); err != nil { + if rows, err = tx.QueryContext(ctx, cypher, params); err != nil { return nil, err } - for result.Next() { - record := result.Record() - inviteNode := record.GetByIndex(0) - - if inviteNode != nil { - i := marshalNodeToInvite(inviteNode.(neo4j.Node)) - invites = append(invites, i) - } - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + i := marshalRowToInvite(rows) + invites = append(invites, i) } return invites, nil } -func FetchInvitesByEmail(tx neo4j.Transaction, invitedBy *Identity, iInvites []Invite) (invites []Invite, err error) { - var result neo4j.Result +func FetchInvitesByEmail(ctx context.Context, tx *sql.Tx, iInvites []Invite) (invites []Invite, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) - var cypInvites string - if invitedBy != nil { - cypInvites = `(i:Identity {id:$invited_by})-[:INVITES]->` - params["invited_by"] = invitedBy.Id - } - cypfilterInvites := "" if len(iInvites) > 0 { var emails []string @@ -193,45 +141,27 @@ func FetchInvitesByEmail(tx neo4j.Transaction, invitedBy *Identity, iInvites []I } cypher = fmt.Sprintf(` - MATCH %s(inv:Invite:Identity) WHERE inv.exp > datetime().epochSeconds %s + MATCH (inv:Invite:Identity) WHERE inv.exp > datetime().epochSeconds %s RETURN inv - `, cypInvites, cypfilterInvites) + `, cypfilterInvites) - if result, err = tx.Run(cypher, params); err != nil { + if rows, err = tx.QueryContext(ctx, cypher, params); err != nil { return nil, err } - for result.Next() { - record := result.Record() - inviteNode := record.GetByIndex(0) - - if inviteNode != nil { - i := marshalNodeToInvite(inviteNode.(neo4j.Node)) - invites = append(invites, i) - } - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + i := marshalRowToInvite(rows) + invites = append(invites, i) } return invites, nil } -func FetchInvitesByUsername(tx neo4j.Transaction, invitedBy *Identity, iInvites []Invite) (invites []Invite, err error) { - var result neo4j.Result +func FetchInvitesByUsername(ctx context.Context, tx *sql.Tx, iInvites []Invite) (invites []Invite, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) - var cypInvites string - if invitedBy != nil { - cypInvites = `(i:Identity {id:$invited_by})-[:INVITES]->` - params["invited_by"] = invitedBy.Id - } - cypfilterInvites := "" if len(iInvites) > 0 { var usernames []string @@ -243,29 +173,17 @@ func FetchInvitesByUsername(tx neo4j.Transaction, invitedBy *Identity, iInvites } cypher = fmt.Sprintf(` - MATCH %s(inv:Invite:Identity) WHERE inv.exp > datetime().epochSeconds %s + MATCH (inv:Invite:Identity) WHERE inv.exp > datetime().epochSeconds %s RETURN inv - `, cypInvites, cypfilterInvites) + `, cypfilterInvites) - if result, err = tx.Run(cypher, params); err != nil { + if rows, err = tx.QueryContext(ctx, cypher, params); err != nil { return nil, err } - for result.Next() { - record := result.Record() - inviteNode := record.GetByIndex(0) - - if inviteNode != nil { - i := marshalNodeToInvite(inviteNode.(neo4j.Node)) - invites = append(invites, i) - } - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + i := marshalRowToInvite(rows) + invites = append(invites, i) } return invites, nil diff --git a/gateway/idp/model.go b/gateway/idp/model.go index 7711a68..54aff03 100644 --- a/gateway/idp/model.go +++ b/gateway/idp/model.go @@ -1,8 +1,7 @@ package idp import ( - "strings" - "github.com/neo4j/neo4j-go-driver/neo4j" + "database/sql" ) type JwtRegisteredClaims struct { @@ -14,9 +13,7 @@ type JwtRegisteredClaims struct { IssuedAt int64 JwtId string } -func marshalNodeToJwtRegisteredClaims(node neo4j.Node) (JwtRegisteredClaims) { - p := node.Props() - +func marshalRowToJwtRegisteredClaims(rows *sql.Rows) (JwtRegisteredClaims) { var iss string var sub string var aud string @@ -25,13 +22,7 @@ func marshalNodeToJwtRegisteredClaims(node neo4j.Node) (JwtRegisteredClaims) { var iat int64 var jti string - if p["iss"] != nil { iss = p["iss"].(string) } - if p["sub"] != nil { sub = p["sub"].(string) } - if p["aud"] != nil { aud = p["aud"].(string) } - if p["exp"] != nil { exp = p["exp"].(int64) } - if p["nbf"] != nil { nbf = p["nbf"].(int64) } - if p["iat"] != nil { iat = p["iat"].(int64) } - if p["jti"] != nil { jti = p["jti"].(string) } + rows.Scan(&iss, &sub, &aud, &exp, &nbf, &iat, &jti) return JwtRegisteredClaims{ Issuer: iss, @@ -59,15 +50,22 @@ type Identity struct { CreatedBy *Identity } -func marshalNodeToIdentity(node neo4j.Node) (Identity) { - p := node.Props() +func marshalRowToIdentity(row *sql.Rows) (Identity) { + var ( + id string + labels string + issuer string + expiresAt int64 + issuedAt int64 + ) + return Identity{ - Id: p["id"].(string), - Labels: strings.Join(node.Labels(), ":"), - Issuer: p["iss"].(string), - ExpiresAt: p["exp"].(int64), - IssuedAt: p["iat"].(int64), + Id: id, + Labels: labels, + Issuer: issuer, + ExpiresAt: expiresAt, + IssuedAt: issuedAt, } } @@ -102,10 +100,8 @@ func (d ChallengeType) String() string { return [...]string{"ChallengeNotSupported", "ChallengeAuthenticate", "ChallengeRecover", "ChallengeDelete", "ChallengeEmailConfirm", "ChallengeEmailChange"}[d] } -func marshalNodeToChallenge(node neo4j.Node) (Challenge) { - p := node.Props() - - var verifiedAt int64 +func marshalRowToChallenge(rows *sql.Rows) (Challenge) { + /*var verifiedAt int64 if (p["verified_at"] != nil) { verifiedAt = p["verified_at"].(int64) } var ct ChallengeType = ChallengeNotSupported @@ -156,7 +152,9 @@ func marshalNodeToChallenge(node neo4j.Node) (Challenge) { VerifiedAt: verifiedAt, Data: data, - } + }*/ + + return Challenge{} // TODO figure this out with sql } type Invite struct { @@ -167,21 +165,18 @@ type Invite struct { SentAt int64 } -func marshalNodeToInvite(node neo4j.Node) (Invite) { - p := node.Props() - - var username string - usr := p["username"] - if usr != nil { - username = p["username"].(string) - } - +func marshalRowToInvite(row *sql.Rows) (Invite) { + var ( + id string + email string + username string + sentAt int64 + ) return Invite{ - Identity: marshalNodeToIdentity(node), - - Email: p["email"].(string), + Identity: Identity{Id: id}, + Email: email, Username: username, - SentAt: p["sent_at"].(int64), + SentAt: sentAt, } } @@ -191,14 +186,21 @@ type ResourceServer struct { Description string Audience string } -func marshalNodeToResourceServer(node neo4j.Node) (ResourceServer) { - p := node.Props() +func marshalRowToResourceServer(row *sql.Rows) (ResourceServer) { + var ( + id string + name string + description string + audience string + ) + + row.Scan(&id, &name, &description, &audience) return ResourceServer{ - Identity: marshalNodeToIdentity(node), - Name: p["name"].(string), - Description: p["description"].(string), - Audience: p["aud"].(string), + Identity: Identity{Id: id}, + Name: name, + Description: description, + Audience: audience, } } @@ -207,13 +209,19 @@ type Role struct { Name string Description string } -func marshalNodeToRole(node neo4j.Node) (Role) { - p := node.Props() +func marshalRowToRole(row *sql.Rows) (Role) { + var ( + id string + name string + description string + ) + + row.Scan(&id, &name, &description) return Role{ - Identity: marshalNodeToIdentity(node), - Name: p["name"].(string), - Description: p["description"].(string), + Identity: Identity{Id: id}, + Name: name, + Description: description, } } @@ -229,10 +237,8 @@ type Client struct { PostLogoutRedirectUris []string TokenEndpointAuthMethod string } -func marshalNodeToClient(node neo4j.Node) (Client) { - p := node.Props() - - var secret string +func marshalRowToClient(rows *sql.Rows) (Client) { + /*var secret string cs := p["secret"] if cs == nil { secret = "" @@ -278,7 +284,7 @@ func marshalNodeToClient(node neo4j.Node) (Client) { } return Client{ - Identity: marshalNodeToIdentity(node), // This is client_id + // Identity: marshalRowToIdentity(node), // This is client_id // TODO Secret: secret, Name: p["name"].(string), Description: p["description"].(string), @@ -288,7 +294,9 @@ func marshalNodeToClient(node neo4j.Node) (Client) { RedirectUris: redirectUris, PostLogoutRedirectUris: postLogoutRedirectUris, TokenEndpointAuthMethod: p["token_endpoint_auth_method"].(string), - } + }*/ + + return Client{} // TODO figure out how to do this with sql } type Human struct { @@ -308,24 +316,29 @@ type Human struct { TotpRequired bool TotpSecret string } -func marshalNodeToHuman(node neo4j.Node) (Human) { - p := node.Props() +func marshalRowToHuman(row *sql.Rows) (Human) { + var ( + email string + email_confirmed_at int64 + username string + name string + allow_login bool + password string + totp_required bool + totp_secret string + ) + + row.Scan(&email, &email_confirmed_at, &username, &allow_login, &password, &totp_required, &totp_secret) return Human{ - Identity: marshalNodeToIdentity(node), - - Email: p["email"].(string), - EmailConfirmedAt: p["email_confirmed_at"].(int64), - Username: p["username"].(string), - - Name: p["name"].(string), - - AllowLogin: p["allow_login"].(bool), - - Password: p["password"].(string), - - TotpRequired: p["totp_required"].(bool), - TotpSecret: p["totp_secret"].(string), - + // Identity: marshalNodeToIdentity(node), TODO + Email: email, + EmailConfirmedAt: email_confirmed_at, + Username: username, + Name: name, + AllowLogin: allow_login, + Password: password, + TotpRequired: totp_required, + TotpSecret: totp_secret, } } diff --git a/gateway/idp/neo.go b/gateway/idp/neo.go deleted file mode 100644 index c9f01d6..0000000 --- a/gateway/idp/neo.go +++ /dev/null @@ -1,63 +0,0 @@ -package idp - -import ( - "strings" - "fmt" - "strconv" - "github.com/neo4j/neo4j-go-driver/neo4j" -) - -func BeginReadTx(driver neo4j.Driver, configurers ...func(*neo4j.TransactionConfig)) (neo4j.Session, neo4j.Transaction, error) { - session, err := driver.Session(neo4j.AccessModeRead) - - if err != nil { - return nil, nil, err - } - - tx, err := session.BeginTransaction(configurers...) - - if err != nil { - session.Close() - } - - return session, tx, err -} - -func BeginWriteTx(driver neo4j.Driver, configurers ...func(*neo4j.TransactionConfig)) (neo4j.Session, neo4j.Transaction, error) { - session, err := driver.Session(neo4j.AccessModeWrite) - - if err != nil { - return nil, nil, err - } - - tx, err := session.BeginTransaction(configurers...) - - if err != nil { - session.Close() - } - - return session, tx, err -} - -func logCypher(query string, params map[string]interface{}) { - for i,e := range params { - - switch t := e.(type) { - case bool: - query = strings.Replace(query, "$"+i, "\""+strconv.FormatBool(e.(bool))+"\"", -1) - case int: - query = strings.Replace(query, "$"+i, "\""+strconv.Itoa(e.(int))+"\"", -1) - case int64: - query = strings.Replace(query, "$"+i, "\""+strconv.FormatInt(e.(int64), 10)+"\"", -1) - case string: - query = strings.Replace(query, "$"+i, "\""+e.(string)+"\"", -1) - case []string: - query = strings.Replace(query, "$"+i, "["+strings.Join(e.([]string), ",")+"]", -1) - default: - panic(fmt.Sprintf("Unsupported type %T", t)) - } - - } - - fmt.Printf("\n========== NEO4J DEBUGGING ==========\nCypher: %v", query) -} diff --git a/gateway/idp/resourceservers.go b/gateway/idp/resourceservers.go index aef31ab..ad3f76d 100644 --- a/gateway/idp/resourceservers.go +++ b/gateway/idp/resourceservers.go @@ -4,11 +4,12 @@ import ( "errors" "strings" "fmt" - "github.com/neo4j/neo4j-go-driver/neo4j" + "context" + "database/sql" + "github.com/google/uuid" ) -func CreateResourceServer(tx neo4j.Transaction, managedBy *Identity, newResourceServer ResourceServer) (resourceServer ResourceServer, err error) { - var result neo4j.Result +func CreateResourceServer(ctx context.Context, tx *sql.Tx, newResourceServer ResourceServer) (resourceServer ResourceServer, err error) { var cypher string var params = make(map[string]interface{}) @@ -34,12 +35,12 @@ func CreateResourceServer(tx neo4j.Transaction, managedBy *Identity, newResource } params["aud"] = newResourceServer.Audience - cypManages := "" - if managedBy != nil { - params["managed_by"] = managedBy.Id - cypManages = `MATCH (i:Identity {id:$managed_by}) MERGE (i)-[:MANAGES]->(rs)` - } + uuid, err := uuid.NewRandom() + if err != nil { + return ResourceServer{}, err + } + // TODO SQL cypher = fmt.Sprintf(` CREATE (rs:ResourceServer:Identity { id:randomUUID(), @@ -56,44 +57,26 @@ func CreateResourceServer(tx neo4j.Transaction, managedBy *Identity, newResource %s RETURN rs - `, cypManages) + `) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return ResourceServer{}, err } - if result.Next() { - record := result.Record() - resourceServerNode := record.GetByIndex(0) - - if resourceServerNode != nil { - resourceServer = marshalNodeToResourceServer(resourceServerNode.(neo4j.Node)) - } - } else { - return ResourceServer{}, errors.New("Unable to create ResourceServer") - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + resourceServers, err := FetchResourceServers(ctx, tx, []ResourceServer{ {Identity: Identity{Id: uuid.String()}} }) + if err != nil { return ResourceServer{}, err } - return resourceServer, nil + return resourceServers[0], nil } -func FetchResourceServers(tx neo4j.Transaction, managedBy *Identity, iResourceServers []ResourceServer) (resourceServers []ResourceServer, err error) { - var result neo4j.Result +func FetchResourceServers(ctx context.Context, tx *sql.Tx, iResourceServers []ResourceServer) (resourceServers []ResourceServer, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) - var cypManages string - if managedBy != nil { - cypManages = `(i:Identity {id:$managed_by})-[:MANAGES]->` - params["managed_by"] = managedBy.Id - } - cypFilterResourceServers := "" if len(iResourceServers) > 0 { var ids []string @@ -104,37 +87,26 @@ func FetchResourceServers(tx neo4j.Transaction, managedBy *Identity, iResourceSe params["ids"] = strings.Join(ids, ",") } + // TODO SQL cypher = fmt.Sprintf(` - MATCH %s(rs:ResourceServer:Identity) WHERE 1=1 %s + MATCH (rs:ResourceServer:Identity) WHERE 1=1 %s RETURN rs - `, cypManages, cypFilterResourceServers) + `, cypFilterResourceServers) - if result, err = tx.Run(cypher, params); err != nil { + rows, err = tx.QueryContext(ctx, cypher, params) + if err != nil { return nil, err } - for result.Next() { - record := result.Record() - resourceServerNode := record.GetByIndex(0) - - if resourceServerNode != nil { - rs := marshalNodeToResourceServer(resourceServerNode.(neo4j.Node)) - resourceServers = append(resourceServers, rs) - } - } - - logCypher(cypher, params) - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + rs := marshalRowToResourceServer(rows) + resourceServers = append(resourceServers, rs) } return resourceServers, nil } -func DeleteResourceServer(tx neo4j.Transaction, managedBy *Identity, resourceServerToDelete ResourceServer) (resourceServer ResourceServer, err error) { - var result neo4j.Result +func DeleteResourceServer(ctx context.Context, tx *sql.Tx, resourceServerToDelete ResourceServer) (resourceServer ResourceServer, err error) { var cypher string var params = make(map[string]interface{}) @@ -143,30 +115,14 @@ func DeleteResourceServer(tx neo4j.Transaction, managedBy *Identity, resourceSer } params["id"] = resourceServerToDelete.Id - var cypManages string - if managedBy != nil { - cypManages = `(i:Identity {id:$managed_by})-[:MANAGES]->` - params["managed_by"] = managedBy.Id - } - - params["id"] = resourceServerToDelete.Id - // Warning: Do not accidentally delete i! + // TODO SQL cypher = fmt.Sprintf(` MATCH %s(c:ResourceServer:Identity {id:$id}) DETACH DELETE c - `, cypManages) - - if result, err = tx.Run(cypher, params); err != nil { - return ResourceServer{}, err - } - - result.Next() - - logCypher(cypher, params) + `) - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + if _, err = tx.ExecContext(ctx, cypher, params); err != nil { return ResourceServer{}, err } diff --git a/gateway/idp/roles.go b/gateway/idp/roles.go index 75b4808..581bac4 100644 --- a/gateway/idp/roles.go +++ b/gateway/idp/roles.go @@ -4,11 +4,12 @@ import ( "strings" "errors" "fmt" - "github.com/neo4j/neo4j-go-driver/neo4j" + "context" + "database/sql" + "github.com/google/uuid" ) -func CreateRole(tx neo4j.Transaction, iRole Role, requestor Identity) (rRole Role, err error) { - var result neo4j.Result +func CreateRole(ctx context.Context, tx *sql.Tx, iRole Role) (rRole Role, err error) { var cypher string var params = make(map[string]interface{}) @@ -27,6 +28,12 @@ func CreateRole(tx neo4j.Transaction, iRole Role, requestor Identity) (rRole Rol } params["description"] = iRole.Description + uuid, err := uuid.NewRandom() + if err != nil { + return Role{}, err + } + + // TODO SQL cypher = fmt.Sprintf(` // Create Role @@ -42,32 +49,22 @@ func CreateRole(tx neo4j.Transaction, iRole Role, requestor Identity) (rRole Rol RETURN role `) - logCypher(cypher, params) - if result, err = tx.Run(cypher, params); err != nil { + _, err = tx.ExecContext(ctx, cypher, params) + if err != nil { return Role{}, err } - if result.Next() { - record := result.Record() - roleNode := record.GetByIndex(0) + rRoles, err := FetchRoles(ctx, tx, []Role{ {Identity: Identity{Id: uuid.String()}} }) - if roleNode != nil { - rRole = marshalNodeToRole(roleNode.(neo4j.Node)) - } - } else { - return Role{}, errors.New("Unable to create Role") - } - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { + if err != nil { return Role{}, err } - return rRole, nil + return rRoles[0], nil } -func FetchRoles(tx neo4j.Transaction, iFilterRoles []Role, iRequest Identity) (rRoles []Role, err error) { - var result neo4j.Result +func FetchRoles(ctx context.Context, tx *sql.Tx, iFilterRoles []Role) (rRoles []Role, err error) { + var rows *sql.Rows var cypher string var params = make(map[string]interface{}) @@ -82,6 +79,7 @@ func FetchRoles(tx neo4j.Transaction, iFilterRoles []Role, iRequest Identity) (r params["filterRoles"] = strings.Join(filterRoles, ",") } + // TODO SQL cypher = fmt.Sprintf(` // Fetch roles @@ -90,30 +88,21 @@ func FetchRoles(tx neo4j.Transaction, iFilterRoles []Role, iRequest Identity) (r RETURN role `, where1) - logCypher(cypher, params) - if result, err = tx.Run(cypher, params); err != nil { + rows, err = tx.QueryContext(ctx, cypher, params) + if err != nil { return nil, err } + defer rows.Close() - for result.Next() { - record := result.Record() - roleNode := record.GetByIndex(0) - - if roleNode != nil { - role := marshalNodeToRole(roleNode.(neo4j.Node)) - rRoles = append(rRoles, role) - } - } - - // Check if we encountered any error during record streaming - if err = result.Err(); err != nil { - return nil, err + for rows.Next() { + role := marshalRowToRole(rows) + rRoles = append(rRoles, role) } return rRoles, nil } -func DeleteRole(tx neo4j.Transaction, iRole Role, requestor Identity) (rRole Role, err error) { +func DeleteRole(ctx context.Context, tx *sql.Tx, iRole Role) (rRole Role, err error) { var cypher string var params = make(map[string]interface{}) @@ -123,6 +112,7 @@ func DeleteRole(tx neo4j.Transaction, iRole Role, requestor Identity) (rRole Rol params["id"] = iRole.Id // Warning: Do not accidentally delete i! + // TODO SQL cypher = fmt.Sprintf(` // Delete role @@ -130,8 +120,7 @@ func DeleteRole(tx neo4j.Transaction, iRole Role, requestor Identity) (rRole Rol DETACH DELETE role `) - logCypher(cypher, params) - if _, err = tx.Run(cypher, params); err != nil { + if _, err = tx.ExecContext(ctx, cypher, params); err != nil { return Role{}, err } diff --git a/go.mod b/go.mod deleted file mode 100644 index 05e2272..0000000 --- a/go.mod +++ /dev/null @@ -1,64 +0,0 @@ -module github.com/charmixer/idp - -go 1.12 - -require ( - cloud.google.com/go v0.46.3 // indirect - github.com/charmixer/aap v0.0.0-20191025081801-453cb590980a - github.com/charmixer/bulky v0.0.0-20191009122503-4027f55965f8 - github.com/charmixer/hydra v0.0.0-20190919102541-aa8327fe2d8d - github.com/coreos/go-oidc v2.1.0+incompatible - github.com/creack/pty v1.1.9 // indirect - github.com/dgrijalva/jwt-go v3.2.0+incompatible - github.com/gin-contrib/sse v0.1.0 // indirect - github.com/gin-gonic/gin v1.4.0 - github.com/go-playground/locales v0.12.1 // indirect - github.com/go-playground/universal-translator v0.16.0 // indirect - github.com/gofrs/uuid v3.2.0+incompatible - github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc // indirect - github.com/google/go-cmp v0.3.1 // indirect - github.com/google/pprof v0.0.0-20190930153522-6ce02741cba3 // indirect - github.com/hashicorp/golang-lru v0.5.3 // indirect - github.com/json-iterator/go v1.1.7 // indirect - github.com/jstemmer/go-junit-report v0.9.1 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect - github.com/kr/pty v1.1.8 // indirect - github.com/leodido/go-urn v1.1.0 // indirect - github.com/magiconair/properties v1.8.1 // indirect - github.com/mattn/go-isatty v0.0.9 // indirect - github.com/nats-io/nats.go v1.8.1 - github.com/neo4j-drivers/gobolt v1.7.4 // indirect - github.com/neo4j/neo4j-go-driver v1.7.4 - github.com/onsi/ginkgo v1.10.1 // indirect - github.com/onsi/gomega v1.7.0 // indirect - github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3 - github.com/pelletier/go-toml v1.4.0 // indirect - github.com/pkg/errors v0.8.1 // indirect - github.com/pquerna/otp v1.2.0 - github.com/rogpeppe/go-internal v1.5.0 // indirect - github.com/sirupsen/logrus v1.4.2 - github.com/spf13/afero v1.2.2 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/viper v1.4.0 - github.com/stretchr/objx v0.2.0 // indirect - github.com/ugorji/go v1.1.7 // indirect - go.opencensus.io v0.22.1 // indirect - golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc - golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3 // indirect - golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a // indirect - golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect - golang.org/x/mobile v0.0.0-20191002175909-6d0d39b2ca82 // indirect - golang.org/x/net v0.0.0-20191007182048-72f939374954 - golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 - golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect - golang.org/x/sys v0.0.0-20191008105621-543471e840be // indirect - golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 // indirect - golang.org/x/tools v0.0.0-20191007185444-6536af71d98a // indirect - google.golang.org/api v0.11.0 // indirect - google.golang.org/appengine v1.6.5 // indirect - google.golang.org/genproto v0.0.0-20191007204434-a023cd5227bd // indirect - google.golang.org/grpc v1.24.0 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/go-playground/validator.v9 v9.30.0 - gopkg.in/yaml.v2 v2.2.4 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 39690f0..0000000 --- a/go.sum +++ /dev/null @@ -1,369 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= -github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/charmixer/aap v0.0.0-20191025081801-453cb590980a h1:+9TKy8otSbNm/H6kf9IoCyR1LckZlH9CYDB3JnO9VnE= -github.com/charmixer/aap v0.0.0-20191025081801-453cb590980a/go.mod h1:PzEgDlyL65O3Gp9xrCAmK8ZJ9hHkCiYdxtxAuUuDZtU= -github.com/charmixer/bulky v0.0.0-20191009081602-fc0bf88ae021 h1:nsRe6Cu8RwS/T3dg+pWyske3jme2wSomeciBPSiNpWY= -github.com/charmixer/bulky v0.0.0-20191009081602-fc0bf88ae021/go.mod h1:UFx87rGfxT72uKbELFfrOqJoCJn2AksfanG5s8zkzRM= -github.com/charmixer/bulky v0.0.0-20191009101030-25ef207972a9 h1:iUpbNJ5I59EnWdekWI5DZa5/JV7W8XQl+hLhy74Mh5c= -github.com/charmixer/bulky v0.0.0-20191009101030-25ef207972a9/go.mod h1:UFx87rGfxT72uKbELFfrOqJoCJn2AksfanG5s8zkzRM= -github.com/charmixer/bulky v0.0.0-20191009115735-515b740de1e3 h1:Cbl0zgKKfRfL0uIFhWQvtkjHNRM40TeeLBv4vZjM4sQ= -github.com/charmixer/bulky v0.0.0-20191009115735-515b740de1e3/go.mod h1:UFx87rGfxT72uKbELFfrOqJoCJn2AksfanG5s8zkzRM= -github.com/charmixer/bulky v0.0.0-20191009122503-4027f55965f8 h1:7Fzk5miavXqCvfO/p5qFPMU68mHXvlzjbzo2kDk8V2I= -github.com/charmixer/bulky v0.0.0-20191009122503-4027f55965f8/go.mod h1:UFx87rGfxT72uKbELFfrOqJoCJn2AksfanG5s8zkzRM= -github.com/charmixer/hydra v0.0.0-20190904201757-b5aa25347016 h1:f5p6r1WKz8FPp0mJpoBHN2ox9kaFd/S49YSkdwJ0+4Y= -github.com/charmixer/hydra v0.0.0-20190904201757-b5aa25347016/go.mod h1:lyCzw2EYfY+pmAuPCwRn179KOoBUoA9EkV29FYJu3L0= -github.com/charmixer/hydra v0.0.0-20190919102541-aa8327fe2d8d h1:wwvUfuiLTe1rETsjMBrBt91WlDpvS4SF0UCQ+EHEPyw= -github.com/charmixer/hydra v0.0.0-20190919102541-aa8327fe2d8d/go.mod h1:qZlNyfdcXQsvU9PUaRfpYEShUk4xX8B2KSkjKyj4CZk= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ= -github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= -github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190930153522-6ce02741cba3/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= -github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ= -github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= -github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M= -github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/neo4j-drivers/gobolt v1.7.4 h1:80c7W+vtw39ES9Q85q9GZh4tJo+1MpQGpFTuo28CP+Y= -github.com/neo4j-drivers/gobolt v1.7.4/go.mod h1:O9AUbip4Dgre+CD3p40dnMD4a4r52QBIfblg5k7CTbE= -github.com/neo4j/neo4j-go-driver v1.7.4 h1:BgVVwYkG3DWcZGiOPUOkwkd54sSg+UHDaLYz3aiNCek= -github.com/neo4j/neo4j-go-driver v1.7.4/go.mod h1:aPO0vVr+WnhEJne+FgFjfsjzAnssPFLucHgGZ76Zb/U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3 h1:YtFkrqsMEj7YqpIhRteVxJxCeC3jJBieuLr0d4C4rSA= -github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg= -github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= -github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190909091759-094676da4a83 h1:mgAKeshyNqWKdENOnQsg+8dRTwZFIwFaO3HNl52sweA= -golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc h1:c0o/qxkaO2LF5t6fQrT4b5hzyggAkLLlCUjqfRxd8Q4= -golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mobile v0.0.0-20191002175909-6d0d39b2ca82/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190909003024-a7b16738d86b h1:XfVGCX+0T4WOStkaOsJRllbsiImhB2jgVBGc9L0lPGc= -golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191007182048-72f939374954 h1:JGZucVF/L/TotR719NbujzadOZ2AgnYlqphQGHDCKaU= -golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190909082730-f460065e899a h1:mIzbOulag9/gXacgxKlFVwpCOWSfBT3/pDyyCwGA9as= -golang.org/x/sys v0.0.0-20190909082730-f460065e899a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190909214602-067311248421/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191007185444-6536af71d98a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.11.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191007204434-a023cd5227bd/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= -gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= -gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss= -gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/main.go b/main.go index e92e3d8..ee617bc 100644 --- a/main.go +++ b/main.go @@ -12,7 +12,10 @@ import ( "github.com/sirupsen/logrus" oidc "github.com/coreos/go-oidc" "github.com/gin-gonic/gin" - "github.com/neo4j/neo4j-go-driver/neo4j" + + _ "github.com/lib/pq" + "database/sql" + "github.com/pborman/getopt" "github.com/dgrijalva/jwt-go" "fmt" @@ -22,16 +25,20 @@ import ( "github.com/opensentry/idp/app" "github.com/opensentry/idp/config" "github.com/opensentry/idp/gateway/idp" - "github.com/opensentry/idp/migration" + // "github.com/opensentry/idp/migration" "github.com/opensentry/idp/endpoints/identities" "github.com/opensentry/idp/endpoints/humans" "github.com/opensentry/idp/endpoints/clients" - "github.com/opensentry/idp/endpoints/challenges" + "github.com/opensentry/idp/endpoints/challenges" "github.com/opensentry/idp/endpoints/invites" "github.com/opensentry/idp/endpoints/resourceservers" "github.com/opensentry/idp/endpoints/roles" - E "github.com/opensentry/idp/client/errors" + + "github.com/golang-migrate/migrate" + _ "github.com/golang-migrate/migrate/database/postgres" + _ "github.com/golang-migrate/migrate/source/file" + ) const appName = "idp" @@ -156,8 +163,19 @@ func createBanList(file string) (map[string]bool, error) { return banList, nil } -func migrate(driver neo4j.Driver) { - migration.Migrate(driver) +func applyMigrate(driver *sql.DB) { + m, err := migrate.New( + "file://migrations/postgres", + config.GetString("db.dsn")) + + if err != nil { + fmt.Println(err) + } + if err := m.Down(); err != nil { + fmt.Println(err) + } + + // migration.Migrate(driver) } func main() { @@ -172,25 +190,20 @@ func main() { os.Exit(0) } - // https://medium.com/neo4j/neo4j-go-driver-is-out-fbb4ba5b3a30 - // Each driver instance is thread-safe and holds a pool of connections that can be re-used over time. If you don’t have a good reason to do otherwise, a typical application should have a single driver instance throughout its lifetime. - log.WithFields(appFields).Debug("Fixme Neo4j loggning should go trough logrus so it does not differ in output from rest of the app") - driver, err := neo4j.NewDriver(config.GetString("neo4j.uri"), neo4j.BasicAuth(config.GetString("neo4j.username"), config.GetString("neo4j.password"), ""), func(conf *neo4j.Config) { - debug := config.GetInt("neo4j.debug") - - if debug == 1 { - conf.Log = neo4j.ConsoleLogger(neo4j.DEBUG) - } - }); - if err != nil { - log.WithFields(appFields).Panic(err.Error()) - return - } - defer driver.Close() + // Create DB pool + driver, err := sql.Open("postgres", config.GetString("db.dsn")) + if err != nil { + fmt.Println(err) + panic("Failed to open a DB connection") + } + /*if debug == 1 { + // TODO postgres logging settings + }*/ + defer driver.Close() // migrate then exit application if *optMigrate { - migrate(driver) + applyMigrate(driver) os.Exit(0) return } diff --git a/migration/migrate.go b/migration/migrate.go index f5b62cb..30cfdc8 100644 --- a/migration/migrate.go +++ b/migration/migrate.go @@ -3,9 +3,9 @@ package migration import ( "io/ioutil" "strings" + "context" "fmt" - - "github.com/neo4j/neo4j-go-driver/neo4j" + "database/sql" "github.com/opensentry/idp/config" ) @@ -21,43 +21,39 @@ func loadMigrationsFromFile(path string) []string { return strings.Split(string(dat), ";") } -func applyMigrations(migrations []string, session neo4j.Session) (error) { - _, err := session.WriteTransaction(func(tx neo4j.Transaction) (interface{}, error) { +func applyMigrations(ctx context.Context, migrations []string, tx *sql.Tx) (error) { - for _, query := range migrations { - if len(strings.TrimSpace(query)) == 0 { - // nothing to run, caused by split on last ; - continue - } + for _, query := range migrations { + if len(strings.TrimSpace(query)) == 0 { + // nothing to run, caused by split on last ; + continue + } - fmt.Println("Applying query: " + query) + fmt.Println("Applying query: " + query) - if _, err := tx.Run(query, nil); err != nil { - fmt.Println(err) - return nil, err - } - } + if _, err := tx.ExecContext(ctx, query, nil); err != nil { + fmt.Println(err) + return err + } + } - return nil, nil - }) - - return err + return nil } -func Migrate(driver neo4j.Driver) { +func Migrate(driver *sql.DB) { var err error - var session neo4j.Session - session, err = driver.Session(neo4j.AccessModeWrite); + ctx := context.TODO() + + tx, err := driver.BeginTx(ctx, nil); if err != nil { fmt.Println(err) - panic("Unable to obtain neo4j write session") + panic("Unable to obtain transaction") } - defer session.Close() schemaMigrations := loadMigrationsFromFile(config.GetString("migration.schema.path")) - err = applyMigrations(schemaMigrations, session) + err = applyMigrations(ctx, schemaMigrations, tx) if err != nil { fmt.Println(err) panic("Errors occured while applying schema migrations") @@ -67,7 +63,7 @@ func Migrate(driver neo4j.Driver) { dataMigrations := loadMigrationsFromFile(config.GetString("migration.data.path")) - err = applyMigrations(dataMigrations, session) + err = applyMigrations(ctx, dataMigrations, tx) if err != nil { fmt.Println(err) panic("Errors occured while applying data migrations") diff --git a/migrations/postgres/1_initial_schema.down.sql b/migrations/postgres/1_initial_schema.down.sql new file mode 100644 index 0000000..8fb4f62 --- /dev/null +++ b/migrations/postgres/1_initial_schema.down.sql @@ -0,0 +1,17 @@ +begin; + + drop table identity; + + drop table human; + + drop table client; + + drop table resource_provider; + + drop table crediential; + + drop table provider; + + drop table secret; + +commit; diff --git a/migrations/postgres/1_initial_schema.up.sql b/migrations/postgres/1_initial_schema.up.sql new file mode 100644 index 0000000..3f5bbb4 --- /dev/null +++ b/migrations/postgres/1_initial_schema.up.sql @@ -0,0 +1,74 @@ +begin; + + create table identity ( + id uuid primary key not null + ); + + create table human ( + subject uuid references identity(id), + name varchar null, + given_name varchar null, + family_name varchar null, + last_name varchar null, + middle_name varchar null, + nickname varchar null, + preferred_username varchar null, + profile varchar null, + picture varchar null, + website varchar null, + email varchar not null, + email_verified boolean not null, + gender varchar null, + birthdate varchar null, + zoneinfo varchar null, + locale varchar null, + phone_number varchar null, + phone_number_verified boolean null, + updated_at timestamp not null, + primary key(subject) + ); + + create table client ( + client_id uuid references identity(id), + name varchar not null, + description text not null, + is_public boolean not null, + secret varchar null, + grant_types varchar[] null, + response_types varchar[] null, + redirect_uris varchar[] null, + token_endpoint_auth_method varchar null, + post_logout_redirect_uris varchar null, + primary key(client_id) + ); + + create table resource_provider ( + resource_provider_id uuid references identity(id), + name varchar not null, + description text not null, + audience varchar not null, + primary key(resource_provider_id) + ); + + create table provider ( + id serial, + name varchar, + password boolean, + primary key(id) + ); + + create table secret ( + id serial, + hash varchar, + recoverable boolean, + end_dtm timestamp null, + primary key(id) + ); + + create table crediential ( + identity_id uuid references identity(id), + provider_id integer references provider(id), + secret_id integer references secret(id) + ); + +commit;