mirror of
https://github.com/vcscsvcscs/GenerationsHeritage.git
synced 2025-08-14 14:59:07 +02:00
fix folder name for db adapter
This commit is contained in:
3
apps/db-adapter/.env.example
Normal file
3
apps/db-adapter/.env.example
Normal file
@@ -0,0 +1,3 @@
|
||||
MEMGRAPH_URI="bolt://localhost:7687"
|
||||
MEMGRAPH_USER="memgraph"
|
||||
MEMGRAPH_PASSWORD="memgraph"
|
146
apps/db-adapter/.golangci.yml
Normal file
146
apps/db-adapter/.golangci.yml
Normal file
@@ -0,0 +1,146 @@
|
||||
version: "2"
|
||||
|
||||
linters:
|
||||
default: none
|
||||
# This list of linters is not a recommendation (same thing for all this configuration file).
|
||||
# We intentionally use a limited set of linters.
|
||||
# See the comment on top of this file.
|
||||
enable:
|
||||
- bodyclose
|
||||
- copyloopvar
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupl
|
||||
- errcheck
|
||||
- errorlint
|
||||
- funlen
|
||||
- gocheckcompilerdirectives
|
||||
- gochecknoinits
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godox
|
||||
- mnd
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- govet
|
||||
- intrange
|
||||
- ineffassign
|
||||
- lll
|
||||
- misspell
|
||||
- nakedret
|
||||
- noctx
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
- testifylint
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- whitespace
|
||||
|
||||
settings:
|
||||
depguard:
|
||||
rules:
|
||||
logger:
|
||||
deny:
|
||||
# logging is allowed only by zap.Logger.,
|
||||
- pkg: "github.com/sirupsen/logrus"
|
||||
desc: logging is allowed only by zap.Logger.
|
||||
- pkg: "github.com/pkg/errors"
|
||||
desc: Should be replaced by standard lib errors package.
|
||||
- pkg: "github.com/instana/testify"
|
||||
desc: It's a fork of github.com/stretchr/testify.
|
||||
|
||||
dupl:
|
||||
threshold: 100
|
||||
funlen:
|
||||
lines: -1 # the number of lines (code + empty lines) is not a right metric and leads to code without empty line or one-liner.
|
||||
statements: 60
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 3
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- experimental
|
||||
- opinionated
|
||||
- performance
|
||||
- style
|
||||
disabled-checks:
|
||||
- dupImport # https://github.com/go-critic/go-critic/issues/845
|
||||
- ifElseChain
|
||||
- octalLiteral
|
||||
- whyNoLint
|
||||
gocyclo:
|
||||
min-complexity: 15
|
||||
godox:
|
||||
keywords:
|
||||
- FIXME
|
||||
mnd:
|
||||
# don't include the "operation" and "assign"
|
||||
checks:
|
||||
- argument
|
||||
- case
|
||||
- condition
|
||||
- return
|
||||
ignored-numbers:
|
||||
- '0'
|
||||
- '1'
|
||||
- '2'
|
||||
- '3'
|
||||
ignored-functions:
|
||||
- strings.SplitN
|
||||
govet:
|
||||
enable-all: true
|
||||
errorlint:
|
||||
asserts: false
|
||||
lll:
|
||||
line-length: 140
|
||||
misspell:
|
||||
locale: US
|
||||
ignore-rules:
|
||||
- "importas" # linter name
|
||||
nolintlint:
|
||||
allow-unused: false # report any unused nolint directives
|
||||
require-explanation: true # require an explanation for nolint directives
|
||||
require-specific: true # require nolint directives to be specific about which linter is being skipped
|
||||
revive:
|
||||
rules:
|
||||
- name: indent-error-flow
|
||||
- name: unexported-return
|
||||
disabled: true
|
||||
- name: unused-parameter
|
||||
- name: unused-receiver
|
||||
|
||||
exclusions:
|
||||
presets:
|
||||
- comments
|
||||
- std-error-handling
|
||||
- common-false-positives
|
||||
- legacy
|
||||
paths:
|
||||
- internal/api/api.gen.go # generated code
|
||||
|
||||
rules:
|
||||
- path: (.+)_test\.go
|
||||
linters:
|
||||
- dupl
|
||||
- mnd
|
||||
- lll
|
||||
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
settings:
|
||||
gofmt:
|
||||
rewrite-rules:
|
||||
- pattern: 'interface{}'
|
||||
replacement: 'any'
|
||||
goimports:
|
||||
local-prefixes:
|
||||
- github.com/golangci/golangci-lint/v2
|
||||
exclusions:
|
||||
paths:
|
||||
- internal/api/api.gen.go # generated code
|
20
apps/db-adapter/dockerfile
Normal file
20
apps/db-adapter/dockerfile
Normal file
@@ -0,0 +1,20 @@
|
||||
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN go get ./...
|
||||
|
||||
RUN go generate ./...
|
||||
|
||||
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o db-adapter
|
||||
|
||||
RUN apk update && apk add ca-certificates && update-ca-certificates
|
||||
|
||||
FROM --platform=$TARGETPLATFORM busybox:1.36.1
|
||||
|
||||
COPY --from=build /etc/ssl/certs /etc/ssl/certs
|
||||
COPY --from=build /app/db-adapter /app/
|
||||
|
||||
CMD [ "/app/db-adapter" ]
|
76
apps/db-adapter/go.mod
Normal file
76
apps/db-adapter/go.mod
Normal file
@@ -0,0 +1,76 @@
|
||||
module github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter
|
||||
|
||||
go 1.24
|
||||
|
||||
require (
|
||||
github.com/gin-contrib/cors v1.7.4
|
||||
github.com/gin-contrib/zap v1.1.4
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.28.0
|
||||
github.com/oapi-codegen/runtime v1.1.1
|
||||
github.com/spf13/viper v1.20.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/net v0.37.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||
github.com/bytedance/sonic v1.13.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/getkin/kin-openapi v0.127.0 // indirect
|
||||
github.com/gin-contrib/sse v1.0.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.25.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/invopop/yaml v0.3.1 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.8.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/speakeasy-api/openapi-overlay v0.9.0 // indirect
|
||||
github.com/spf13/afero v1.14.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.15.0 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
golang.org/x/tools v0.31.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
tool github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen
|
300
apps/db-adapter/go.sum
Normal file
300
apps/db-adapter/go.sum
Normal file
@@ -0,0 +1,300 @@
|
||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
||||
github.com/bytedance/sonic v1.12.6 h1:/isNmCUF2x3Sh8RAp/4mh4ZGkcFAX/hLrzrK3AvpRzk=
|
||||
github.com/bytedance/sonic v1.12.6/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
||||
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iCjjJv3+E=
|
||||
github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
||||
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
|
||||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58=
|
||||
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w=
|
||||
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA=
|
||||
github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY=
|
||||
github.com/getkin/kin-openapi v0.127.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM=
|
||||
github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw=
|
||||
github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E=
|
||||
github.com/gin-contrib/cors v1.7.4 h1:/fC6/wk7rCRtqKqki8lLr2Xq+hnV49aXDLIuSek9g4k=
|
||||
github.com/gin-contrib/cors v1.7.4/go.mod h1:vGc/APSgLMlQfEJV5NAzkrAHb0C8DetL3K6QZuvGii0=
|
||||
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-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
||||
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
||||
github.com/gin-contrib/zap v1.1.4 h1:xvxTybg6XBdNtcQLH3Tf0lFr4vhDkwzgLLrIGlNTqIo=
|
||||
github.com/gin-contrib/zap v1.1.4/go.mod h1:7lgEpe91kLbeJkwBTPgtVBy4zMa6oSBEcvj662diqKQ=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
|
||||
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
|
||||
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
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/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
|
||||
github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.28.0 h1:chDT68PHNa8JZRmjSkGzAbk1weLWo4rMtDvccvpobg0=
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.28.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1 h1:ykgG34472DWey7TSjd8vIfNykXgjOgYJZoQbKfEeY/Q=
|
||||
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1/go.mod h1:N5+lY1tiTDV3V1BeHtOxeWXHoPVeApvsvjJqegfoaz8=
|
||||
github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
|
||||
github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
|
||||
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
|
||||
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
|
||||
github.com/sagikazarmark/locafero v0.8.0 h1:mXaMVw7IqxNBxfv3LdWt9MDmcWDQ1fagDH918lOdVaQ=
|
||||
github.com/sagikazarmark/locafero v0.8.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/speakeasy-api/openapi-overlay v0.9.0 h1:Wrz6NO02cNlLzx1fB093lBlYxSI54VRhy1aSutx0PQg=
|
||||
github.com/speakeasy-api/openapi-overlay v0.9.0/go.mod h1:f5FloQrHA7MsxYg9djzMD5h6dxrHjVVByWKh7an8TRc=
|
||||
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
|
||||
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
|
||||
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
|
||||
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY=
|
||||
github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
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/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk=
|
||||
github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg=
|
||||
golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw=
|
||||
golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
1
apps/db-adapter/internal/api/authorization_by_id.go
Normal file
1
apps/db-adapter/internal/api/authorization_by_id.go
Normal file
@@ -0,0 +1 @@
|
||||
package api
|
3
apps/db-adapter/internal/api/generate.go
Normal file
3
apps/db-adapter/internal/api/generate.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package api
|
||||
|
||||
//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config oapi-codegen-cfg.yaml ../../../../api/openapi.json
|
6
apps/db-adapter/internal/api/oapi-codegen-cfg.yaml
Normal file
6
apps/db-adapter/internal/api/oapi-codegen-cfg.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/HEAD/configuration-schema.json
|
||||
package: api
|
||||
output: api.gen.go
|
||||
generate:
|
||||
models: true
|
||||
gin-server: true
|
11
apps/db-adapter/internal/api/person.go
Normal file
11
apps/db-adapter/internal/api/person.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package api
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func (srv *server) CreatePerson(c *gin.Context) {}
|
||||
|
||||
func (srv *server) SoftDeletePerson(c *gin.Context, id int, params SoftDeletePersonParams) {}
|
||||
|
||||
func (srv *server) UpdatePerson(c *gin.Context, id int, params UpdatePersonParams) {}
|
||||
|
||||
func (srv *server) HardDeletePerson(c *gin.Context, id int, params HardDeletePersonParams) {}
|
6
apps/db-adapter/internal/api/person_and_relationship.go
Normal file
6
apps/db-adapter/internal/api/person_and_relationship.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package api
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func (srv *server) CreatePersonAndRelationship(c *gin.Context, id int, params CreatePersonAndRelationshipParams) {
|
||||
}
|
5
apps/db-adapter/internal/api/person_family_tree.go
Normal file
5
apps/db-adapter/internal/api/person_family_tree.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package api
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func (srv *server) GetFamilyTreeById(c *gin.Context, id int) {}
|
9
apps/db-adapter/internal/api/person_google.go
Normal file
9
apps/db-adapter/internal/api/person_google.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package api
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func (srv *server) GetPersonByGoogleId(c *gin.Context, googleId string) {}
|
||||
|
||||
func (srv *server) CreatePersonByGoogleIdAndInviteCode(c *gin.Context, googleId string) {}
|
||||
|
||||
func (srv *server) CreatePersonByGoogleId(c *gin.Context, googleId string) {}
|
5
apps/db-adapter/internal/api/person_recipes.go
Normal file
5
apps/db-adapter/internal/api/person_recipes.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package api
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func (srv *server) GetRecipesByPersonId(c *gin.Context, id int, params GetRecipesByPersonIdParams) {}
|
9
apps/db-adapter/internal/api/recipe_relationship.go
Normal file
9
apps/db-adapter/internal/api/recipe_relationship.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package api
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func (srv *server) DeleteRecipeRelationship(c *gin.Context, recipeId int, params DeleteRecipeRelationshipParams) {
|
||||
}
|
||||
|
||||
func (srv *server) CreateRecipeRelationship(c *gin.Context, recipeId int, params CreateRecipeRelationshipParams) {
|
||||
}
|
9
apps/db-adapter/internal/api/recipes.go
Normal file
9
apps/db-adapter/internal/api/recipes.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package api
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func (srv *server) SoftDeleteRecipe(c *gin.Context, id int, params SoftDeleteRecipeParams) {}
|
||||
|
||||
func (srv *server) UpdateRecipe(c *gin.Context, id int, params UpdateRecipeParams) {}
|
||||
|
||||
func (srv *server) HardDeleteRecipe(c *gin.Context, id int, params HardDeleteRecipeParams) {}
|
7
apps/db-adapter/internal/api/relationship.go
Normal file
7
apps/db-adapter/internal/api/relationship.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package api
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func (srv *server) CreateRelationship(c *gin.Context, params CreateRelationshipParams) {}
|
||||
|
||||
func (srv *server) GetRelationship(c *gin.Context, id1 int, id2 int, params GetRelationshipParams) {}
|
34
apps/db-adapter/internal/api/server.go
Normal file
34
apps/db-adapter/internal/api/server.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/gin/healthcheck"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type server struct {
|
||||
db neo4j.DriverWithContext
|
||||
health healthcheck.HealthCheck
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, drv neo4j.DriverWithContext, healthcheck healthcheck.HealthCheck) ServerInterface {
|
||||
if logger == nil {
|
||||
panic("logger is required")
|
||||
}
|
||||
|
||||
if drv == nil {
|
||||
panic("neo4j driver is required")
|
||||
}
|
||||
|
||||
if healthcheck == nil {
|
||||
panic("healthcheck is required")
|
||||
}
|
||||
|
||||
return &server{db: drv, health: healthcheck, logger: logger}
|
||||
}
|
||||
|
||||
func (srv *server) HealthCheck(c *gin.Context) {
|
||||
srv.health.HealthCheckHandler(c)
|
||||
}
|
77
apps/db-adapter/internal/api/server_test.go
Normal file
77
apps/db-adapter/internal/api/server_test.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type mockHealthCheck struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *mockHealthCheck) HealthCheckHandler(c *gin.Context) {
|
||||
m.Called(c)
|
||||
}
|
||||
|
||||
func (m *mockHealthCheck) SetStatus(status string) {
|
||||
m.Called(status)
|
||||
}
|
||||
|
||||
func (m *mockHealthCheck) GetStatus() string {
|
||||
args := m.Called()
|
||||
|
||||
return args.String(0)
|
||||
}
|
||||
|
||||
func TestNewServer(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
mockDriver, err := neo4j.NewDriverWithContext("bolt+ssc://memgraph:7687", nil)
|
||||
assert.NoError(t, err)
|
||||
mockHealth := &mockHealthCheck{}
|
||||
|
||||
t.Run("should create a new server instance", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
srv := New(logger, mockDriver, mockHealth)
|
||||
assert.NotNil(t, srv)
|
||||
})
|
||||
|
||||
t.Run("should panic if logger is nil", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Panics(t, func() {
|
||||
New(nil, mockDriver, mockHealth)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("should panic if driver is nil", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Panics(t, func() {
|
||||
New(logger, nil, mockHealth)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("should panic if healthcheck is nil", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Panics(t, func() {
|
||||
New(logger, mockDriver, nil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestHealthCheck(t *testing.T) {
|
||||
mockHealth := &mockHealthCheck{}
|
||||
srv := &server{health: mockHealth}
|
||||
|
||||
t.Run("should call HealthCheckHandler", func(t *testing.T) {
|
||||
mockHealth.On("HealthCheckHandler", mock.Anything).Once()
|
||||
|
||||
c, _ := gin.CreateTestContext(nil)
|
||||
srv.HealthCheck(c)
|
||||
|
||||
mockHealth.AssertCalled(t, "HealthCheckHandler", c)
|
||||
})
|
||||
}
|
119
apps/db-adapter/main.go
Normal file
119
apps/db-adapter/main.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
ginzap "github.com/gin-contrib/zap"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/internal/api"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/gin/healthcheck"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/memgraph"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
httpPort string
|
||||
memgraphURI string
|
||||
memgraphUser string
|
||||
memgraphPass string
|
||||
production bool
|
||||
requestTimeout time.Duration
|
||||
)
|
||||
|
||||
func init() {
|
||||
viper.AutomaticEnv()
|
||||
|
||||
viper.SetDefault("HTTP_PORT", ":80")
|
||||
viper.SetDefault("MEMGRAPH_URI", "bolt+ssc://memgraph:7687")
|
||||
viper.SetDefault("MEMGRAPH_USER", "")
|
||||
viper.SetDefault("MEMGRAPH_PASS", "")
|
||||
viper.SetDefault("PRODUCTION", false)
|
||||
viper.SetDefault("REQUEST_TIMEOUT", 20)
|
||||
|
||||
httpPort = viper.GetString("HTTP_PORT")
|
||||
memgraphURI = viper.GetString("MEMGRAPH_URI")
|
||||
memgraphUser = viper.GetString("MEMGRAPH_USER")
|
||||
memgraphPass = viper.GetString("MEMGRAPH_PASS")
|
||||
production = viper.GetBool("PRODUCTION")
|
||||
requestTimeout = time.Duration(viper.GetInt("REQUEST_TIMEOUT")) * time.Second
|
||||
}
|
||||
|
||||
func main() {
|
||||
var logger *zap.Logger
|
||||
var err error
|
||||
if production {
|
||||
logger, err = zap.NewProduction()
|
||||
} else {
|
||||
logger, _ = zap.NewDevelopment()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hc := healthcheck.New()
|
||||
|
||||
memgraphDriver := memgraph.InitDatabase(memgraphURI, memgraphUser, memgraphPass)
|
||||
|
||||
router := gin.Default()
|
||||
router.Use(cors.New(cors.Config{
|
||||
AllowOrigins: []string{"http://localhost:5173", "http://localhost"},
|
||||
AllowCredentials: true,
|
||||
AllowHeaders: []string{"X-User-ID", "Content-Type"},
|
||||
MaxAge: 12 * time.Hour,
|
||||
}))
|
||||
|
||||
router.Use(ginzap.Ginzap(logger, time.RFC3339, true))
|
||||
router.Use(ginzap.RecoveryWithZap(logger, true))
|
||||
|
||||
sApi := api.New(logger, memgraphDriver, hc)
|
||||
api.RegisterHandlersWithOptions(router, sApi, api.GinServerOptions{})
|
||||
|
||||
server := &http.Server{
|
||||
Addr: httpPort,
|
||||
Handler: router,
|
||||
ReadTimeout: requestTimeout * time.Second,
|
||||
WriteTimeout: requestTimeout * time.Second,
|
||||
}
|
||||
go func() {
|
||||
logger.Info("Starting server", zap.String("port", httpPort))
|
||||
if err := server.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
|
||||
logger.Fatal(err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for interrupt signal to gracefully shutdown the server with some time to finish requests.
|
||||
quit := make(chan os.Signal, 1)
|
||||
// kill (no param) default send syscall.SIGTERM
|
||||
// kill -2 is syscall.SIGINT
|
||||
// kill -9 is syscall.SIGKILL but can't be caught, so don't need to add it
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
|
||||
<-quit
|
||||
logger.Info("Shutting down server...")
|
||||
|
||||
// The context is used to inform the server it has some seconds to finish
|
||||
// the request it is currently handling
|
||||
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout*time.Second)
|
||||
defer cancel()
|
||||
|
||||
go func() {
|
||||
if err := memgraphDriver.Close(context.WithoutCancel(ctx)); err != nil {
|
||||
logger.Error("Memgraph driver forced to shutdown", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
|
||||
if err := server.Shutdown(ctx); err != nil {
|
||||
logger.Error("Server forced to shutdown", zap.Error(err))
|
||||
}
|
||||
|
||||
logger.Info("Server exited")
|
||||
}
|
11
apps/db-adapter/pkg/file_exists.go
Normal file
11
apps/db-adapter/pkg/file_exists.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Checks if file on path exists or not
|
||||
func FileExists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return !os.IsNotExist(err)
|
||||
}
|
27
apps/db-adapter/pkg/file_exists_test.go
Normal file
27
apps/db-adapter/pkg/file_exists_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFileExists(t *testing.T) {
|
||||
// Create a temporary file for testing
|
||||
file, err := os.CreateTemp("", "testfile")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temporary file: %v", err)
|
||||
}
|
||||
defer os.Remove(file.Name())
|
||||
|
||||
// Test with an existing file
|
||||
exists := FileExists(file.Name())
|
||||
if !exists {
|
||||
t.Errorf("FileExists(%q) = false, want true", file.Name())
|
||||
}
|
||||
|
||||
// Test with a non-existing file
|
||||
exists = FileExists("non_existing_file.txt")
|
||||
if exists {
|
||||
t.Errorf("FileExists(%q) = true, want false", "non_existing_file.txt")
|
||||
}
|
||||
}
|
52
apps/db-adapter/pkg/gin/healthcheck/health_check.go
Normal file
52
apps/db-adapter/pkg/gin/healthcheck/health_check.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package healthcheck
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type HealthCheck interface {
|
||||
SetStatus(status string)
|
||||
GetStatus() string
|
||||
HealthCheckHandler(c *gin.Context)
|
||||
}
|
||||
|
||||
type healthCheck struct {
|
||||
status string
|
||||
sync sync.Mutex
|
||||
}
|
||||
|
||||
func New() HealthCheck {
|
||||
return &healthCheck{
|
||||
status: "ok",
|
||||
}
|
||||
}
|
||||
|
||||
func (hc *healthCheck) SetStatus(status string) {
|
||||
hc.sync.Lock()
|
||||
defer hc.sync.Unlock()
|
||||
|
||||
hc.status = status
|
||||
}
|
||||
|
||||
func (hc *healthCheck) GetStatus() string {
|
||||
hc.sync.Lock()
|
||||
defer hc.sync.Unlock()
|
||||
|
||||
return hc.status
|
||||
}
|
||||
|
||||
func (hc *healthCheck) HealthCheckHandler(c *gin.Context) {
|
||||
switch hc.GetStatus() {
|
||||
case "nok":
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||
"msg": hc.GetStatus(),
|
||||
})
|
||||
default:
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"msg": hc.GetStatus(),
|
||||
})
|
||||
}
|
||||
}
|
134
apps/db-adapter/pkg/gin/healthcheck/health_check_test.go
Normal file
134
apps/db-adapter/pkg/gin/healthcheck/health_check_test.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package healthcheck
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func TestHealthCheck_GetStatus(t *testing.T) {
|
||||
var hc HealthCheck
|
||||
|
||||
type fields struct {
|
||||
status string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "Test GetStatus with status ok",
|
||||
fields: fields{
|
||||
status: "ok",
|
||||
},
|
||||
want: "ok",
|
||||
},
|
||||
{
|
||||
name: "Test GetStatus with status nok",
|
||||
fields: fields{
|
||||
status: "nok",
|
||||
},
|
||||
want: "nok",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hc = &healthCheck{
|
||||
status: tt.fields.status,
|
||||
}
|
||||
if got := hc.GetStatus(); got != tt.want {
|
||||
t.Errorf("HealthCheck.GetStatus() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthCheck_SetStatus(t *testing.T) {
|
||||
hc := New()
|
||||
|
||||
type args struct {
|
||||
status string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "Test SetStatus with status ok",
|
||||
args: args{
|
||||
status: "ok",
|
||||
},
|
||||
want: "ok",
|
||||
},
|
||||
{
|
||||
name: "Test SetStatus with status nok",
|
||||
args: args{
|
||||
status: "nok",
|
||||
},
|
||||
want: "nok",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hc.SetStatus(tt.args.status)
|
||||
if got := hc.GetStatus(); got != tt.want {
|
||||
t.Errorf("HealthCheck.GetStatus() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthCheck_HealthCheckHandler(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
r := gin.Default()
|
||||
hc := New()
|
||||
r.GET("/health", hc.HealthCheckHandler)
|
||||
type args struct {
|
||||
status string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
statusCode int
|
||||
}{
|
||||
{
|
||||
name: "Test respond with status ok",
|
||||
args: args{
|
||||
status: "ok",
|
||||
},
|
||||
want: `{"msg":"ok"}`,
|
||||
statusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "Test respond with status nok",
|
||||
args: args{
|
||||
status: "nok",
|
||||
},
|
||||
want: `{"msg":"nok"}`,
|
||||
statusCode: http.StatusServiceUnavailable,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
hc.SetStatus(tt.args.status)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", "/health", nil)
|
||||
r.ServeHTTP(w, req)
|
||||
|
||||
if got := w.Code; got != tt.statusCode {
|
||||
t.Errorf("HealthCheck response status code = %v, want %v", got, tt.statusCode)
|
||||
}
|
||||
if got := w.Body.String(); got != tt.want {
|
||||
t.Errorf("HealthCheck response = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
30
apps/db-adapter/pkg/memgraph/create_person.go
Normal file
30
apps/db-adapter/pkg/memgraph/create_person.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (p *Person) CreatePerson(driver neo4j.DriverWithContext) (*neo4j.Record, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
|
||||
defer session.Close(ctx)
|
||||
|
||||
if err := p.Verify(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("CREATE (n:Person {%s}) RETURN n;", p.ToString())
|
||||
|
||||
result, err := session.Run(ctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Single(ctx)
|
||||
}
|
39
apps/db-adapter/pkg/memgraph/create_relationship.go
Normal file
39
apps/db-adapter/pkg/memgraph/create_relationship.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (r *Relationship) CreateRelationship(driver neo4j.DriverWithContext) (*neo4j.Record, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
|
||||
defer session.Close(ctx)
|
||||
|
||||
if err := r.Verify(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`MATCH (a:Person), (b:Person) WHERE a.id = '%s' AND b.id = '%s'`, r.FirstPersonID, r.SecondPersonID)
|
||||
|
||||
if r.Direction == "->" {
|
||||
query = fmt.Sprintf(`%s CREATE (a)-[r:%s {verified: false}]->(b) RETURN r;`, query, r.Relationship)
|
||||
} else if r.Direction == "<-" {
|
||||
query = fmt.Sprintf(`%s CREATE (a)<-[r:%s {verified: false}]-(b) RETURN r;`, query, r.Relationship)
|
||||
} else {
|
||||
query = fmt.Sprintf(`%s CREATE (a)<-[r1:%s {verified: True}]-(b) CREATE (a)-[r2:%s {verified: True}]->(b) RETURN r1, r2;`,
|
||||
query, r.Relationship, r.Relationship)
|
||||
}
|
||||
|
||||
result, err := session.Run(ctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Single(ctx)
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (rp *RelationshipAndPerson) CreateRelationshipAndPerson(driver neo4j.DriverWithContext) (*neo4j.Record, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
|
||||
defer session.Close(ctx)
|
||||
|
||||
if err := rp.Verify(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rp.Person.ID = strings.ReplaceAll(uuid.New().String(), "-", "")
|
||||
|
||||
query := fmt.Sprintf(`MATCH (a:Person) WHERE a.id = '%s'`, rp.Relationship.FirstPersonID)
|
||||
|
||||
query = fmt.Sprintf("%s CREATE (b:Person {%s})", query, rp.Person.ToString())
|
||||
|
||||
if rp.Relationship.Direction == "->" {
|
||||
query = fmt.Sprintf(`%s CREATE (a)-[r:%s {verified: True}]->(b) RETURN r;`, query, rp.Relationship.Relationship)
|
||||
} else if rp.Relationship.Direction == "<-" {
|
||||
query = fmt.Sprintf(`%s CREATE (a)<-[r:%s {verified: True}]-(b) RETURN r;`, query, rp.Relationship.Relationship)
|
||||
} else {
|
||||
query = fmt.Sprintf(`%s CREATE (a)<-[r1:%s {verified: True}]-(b) CREATE (a)-[r2:%s {verified: True}]->(b) RETURN r1, r2, b;`,
|
||||
query, rp.Relationship.Relationship, rp.Relationship.Relationship)
|
||||
}
|
||||
|
||||
result, err := session.Run(ctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Single(ctx)
|
||||
}
|
66
apps/db-adapter/pkg/memgraph/create_schema.go
Normal file
66
apps/db-adapter/pkg/memgraph/create_schema.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
const dbCreateSchemaTimeout = 10 * time.Second
|
||||
|
||||
func createIndexes(driver neo4j.DriverWithContext) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), dbCreateSchemaTimeout)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
|
||||
defer session.Close(ctx)
|
||||
|
||||
indexes := []string{
|
||||
`CREATE INDEX ON :Person(id);`,
|
||||
`CREATE INDEX ON :Person(last_name);`,
|
||||
`CREATE INDEX ON :Person(first_name);`,
|
||||
`CREATE INDEX ON :Person(born);`,
|
||||
`CREATE INDEX ON :Person(mothers_first_name);`,
|
||||
`CREATE INDEX ON :Person(mothers_last_name);`,
|
||||
}
|
||||
|
||||
// Run index queries via implicit auto-commit transaction
|
||||
for _, index := range indexes {
|
||||
_, err := session.Run(ctx, index, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createConstraints(driver neo4j.DriverWithContext) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), dbCreateSchemaTimeout)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
|
||||
defer session.Close(ctx)
|
||||
|
||||
constraints := []string{
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.id);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.last_name);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.first_name);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.born);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.mothers_first_name);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.mothers_last_name);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT n.id IS UNIQUE;`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT n.last_name, n.first_name, n.born, n.mothers_first_name, n.mothers_last_name IS UNIQUE;`,
|
||||
}
|
||||
|
||||
// Run index queries via implicit auto-commit transaction
|
||||
for _, constraint := range constraints {
|
||||
_, err := session.Run(ctx, constraint, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
124
apps/db-adapter/pkg/memgraph/cypher_verify_string.go
Normal file
124
apps/db-adapter/pkg/memgraph/cypher_verify_string.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var cypherKeywords = []string{
|
||||
"CREATE",
|
||||
"DELETE",
|
||||
"DETACH",
|
||||
"DETACH DELETE",
|
||||
"FOREACH",
|
||||
"LOAD CSV",
|
||||
"MERGE",
|
||||
"MATCH",
|
||||
"ON",
|
||||
"OPTIONAL MATCH",
|
||||
"REMOVE",
|
||||
"SET",
|
||||
"START",
|
||||
"UNION",
|
||||
"UNWIND",
|
||||
"WITH",
|
||||
"RETURN",
|
||||
"ORDER BY",
|
||||
"SKIP",
|
||||
"LIMIT",
|
||||
"ASC",
|
||||
"DESC",
|
||||
"EXISTS",
|
||||
"CALL",
|
||||
"USING",
|
||||
"CONSTRAINT",
|
||||
"DROP",
|
||||
"INDEX",
|
||||
"WHERE",
|
||||
}
|
||||
|
||||
var cypherOperators = []string{
|
||||
"+",
|
||||
"-",
|
||||
"*",
|
||||
"/",
|
||||
"%",
|
||||
"^",
|
||||
"=",
|
||||
"<",
|
||||
">",
|
||||
"<=",
|
||||
">=",
|
||||
"<>",
|
||||
"AND",
|
||||
"OR",
|
||||
"XOR",
|
||||
"NOT",
|
||||
"IN",
|
||||
"STARTS WITH",
|
||||
"ENDS WITH",
|
||||
"CONTAINS",
|
||||
"IS NULL",
|
||||
"IS NOT NULL",
|
||||
"IS UNIQUE",
|
||||
"IS NODE",
|
||||
"IS RELATIONSHIP",
|
||||
"IS PROPERTY KEY",
|
||||
"IS MAP",
|
||||
"IS LIST",
|
||||
"IS BOOLEAN",
|
||||
"IS STRING",
|
||||
"IS NUMBER",
|
||||
"IS INTEGER",
|
||||
"IS FLOAT",
|
||||
"IS NODE",
|
||||
"IS RELATIONSHIP",
|
||||
"IS PATH",
|
||||
"IS POINT",
|
||||
"IS DATE",
|
||||
"IS DURATION",
|
||||
}
|
||||
|
||||
// cypherDelimiters contains the delimiters that need to be escaped in a string to prevent cypher injection keys are the delimiters that need to be escaped and values are the escaped delimiters
|
||||
var cypherDelimiters = map[string]string{
|
||||
"'": `\'`,
|
||||
`"`: `\"`,
|
||||
`\u0027`: `\\u0027`,
|
||||
`\u0022`: "\\\\u0022",
|
||||
"`": "``",
|
||||
"\\u0060": "\\u0060\\u0060",
|
||||
}
|
||||
|
||||
// VerifyString verifies if a string is valid and does not contain cypher injection
|
||||
func VerifyString(s string) error {
|
||||
s = strings.ToUpper(s)
|
||||
for _, keyword := range cypherKeywords {
|
||||
if strings.Contains(s, keyword) {
|
||||
return fmt.Errorf("invalid string: %s contains cypher keyword: %s", s, keyword)
|
||||
}
|
||||
}
|
||||
|
||||
for _, operator := range cypherOperators {
|
||||
if strings.Contains(s, operator) {
|
||||
return fmt.Errorf("invalid string: %s contains cypher operator: %s", s, operator)
|
||||
}
|
||||
}
|
||||
|
||||
for key := range cypherDelimiters {
|
||||
if strings.Contains(s, key) {
|
||||
return fmt.Errorf("invalid string: %s contains cypher delimiter: %s", s, key)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EscapeString escapes delimiters in a string to prevent cypher injection
|
||||
func EscapeString(s string) string {
|
||||
result := s
|
||||
for k, v := range cypherDelimiters {
|
||||
result = strings.ReplaceAll(result, k, v)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
27
apps/db-adapter/pkg/memgraph/delete_person.go
Normal file
27
apps/db-adapter/pkg/memgraph/delete_person.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (p *Person) DeletePerson(driver neo4j.DriverWithContext) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
|
||||
defer session.Close(ctx)
|
||||
|
||||
if err := p.Verify(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("MATCH (n:Person {id: '%s'}) DELETE n;", p.ID)
|
||||
|
||||
_, err := session.Run(ctx, query, nil)
|
||||
|
||||
return err
|
||||
}
|
36
apps/db-adapter/pkg/memgraph/delete_relationship.go
Normal file
36
apps/db-adapter/pkg/memgraph/delete_relationship.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (r *Relationship) DeleteRelationship(driver neo4j.DriverWithContext) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
|
||||
defer session.Close(ctx)
|
||||
|
||||
if err := r.Verify(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query := ""
|
||||
if r.Direction == "->" {
|
||||
query = fmt.Sprintf(`MATCH (a)-[r:%s]->(b)`, r.Relationship)
|
||||
} else if r.Direction == "<-" {
|
||||
query = fmt.Sprintf(`MATCH (a)<-[r:%s]-(b)`, r.Relationship)
|
||||
} else {
|
||||
query = fmt.Sprintf(`MATCH (a)-[r:%s]-(b)`, r.Relationship)
|
||||
}
|
||||
|
||||
query = fmt.Sprintf(`%s WHERE a.id = '%s' AND b.id = '%s' DELETE r;`, query, r.FirstPersonID, r.SecondPersonID)
|
||||
|
||||
_, err := session.Run(ctx, query, nil)
|
||||
|
||||
return err
|
||||
}
|
32
apps/db-adapter/pkg/memgraph/init_database.go
Normal file
32
apps/db-adapter/pkg/memgraph/init_database.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
)
|
||||
|
||||
func InitDatabase(dbURI, dbUser, dbPassword string) neo4j.DriverWithContext {
|
||||
driver, err := neo4j.NewDriverWithContext(dbURI, neo4j.BasicAuth(dbUser, dbPassword, ""))
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
err = driver.VerifyConnectivity(ctx)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := createIndexes(driver); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := createConstraints(driver); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
return driver
|
||||
}
|
272
apps/db-adapter/pkg/memgraph/model.go
Normal file
272
apps/db-adapter/pkg/memgraph/model.go
Normal file
@@ -0,0 +1,272 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
var RelationshipTypes = []string{
|
||||
"Parent",
|
||||
"Child",
|
||||
"Spouse",
|
||||
"Sibling",
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
ID string `json:"id"`
|
||||
Firstname string `json:"first_name"`
|
||||
Middlename string `json:"middle_name"`
|
||||
Lastname string `json:"last_name"`
|
||||
Titles []string `json:"titles"` // e.g. Jr., Sr., III
|
||||
Suffixes []string `json:"suffixes"` // e.g. Ph.D., M.D.
|
||||
ExtraNames []string `json:"extra_names"`
|
||||
Aliases []string `json:"aliases"`
|
||||
MothersFirstname string `json:"mothers_first_name"`
|
||||
MothersLastname string `json:"mothers_last_name"`
|
||||
Born time.Time `json:"born"`
|
||||
Birthplace string `json:"birthplace"`
|
||||
Residence string `json:"residence"`
|
||||
Death time.Time `json:"death"`
|
||||
Deathplace string `json:"deathplace"`
|
||||
LifeEvents []map[string]string `json:"life_events"`
|
||||
Occupations []string `json:"occupation"`
|
||||
OccupationToDisplay string `json:"occupation_to_display"`
|
||||
OthersSaid map[string]string `json:"others_said"`
|
||||
Photos map[string]string `json:"photos"`
|
||||
ProfilePicture string `json:"profile_picture"`
|
||||
verified bool
|
||||
}
|
||||
|
||||
func (p *Person) ToString() string {
|
||||
result := fmt.Sprintf("id: '%s'", p.ID)
|
||||
if p.Firstname != "" {
|
||||
result = fmt.Sprintf("%s, first_name: '%s'", result, p.Firstname)
|
||||
}
|
||||
if p.Lastname != "" {
|
||||
result = fmt.Sprintf("%s, last_name: '%s'", result, p.Lastname)
|
||||
}
|
||||
if p.Middlename != "" {
|
||||
result = fmt.Sprintf("%s, middle_name: '%s'", result, p.Middlename)
|
||||
}
|
||||
if p.MothersFirstname != "" {
|
||||
result = fmt.Sprintf("%s, mothers_first_name: '%s'", result, p.MothersFirstname)
|
||||
}
|
||||
if p.MothersLastname != "" {
|
||||
result = fmt.Sprintf("%s, mothers_last_name: '%s'", result, p.MothersLastname)
|
||||
}
|
||||
if !p.Born.IsZero() {
|
||||
result = fmt.Sprintf("%s, born: date({year:%d, month:%d, day:%d})", result, p.Born.Year(), p.Born.Month(), p.Born.Day())
|
||||
}
|
||||
if !p.Death.IsZero() {
|
||||
result = fmt.Sprintf("%s, death: date({year:%d, month:%d, day:%d})", result, p.Death.Year(), p.Death.Month(), p.Death.Day())
|
||||
}
|
||||
if p.Birthplace != "" {
|
||||
result = fmt.Sprintf("%s, birthplace: '%s'", result, p.Birthplace)
|
||||
}
|
||||
if p.Residence != "" {
|
||||
result = fmt.Sprintf("%s, residence: '%s'", result, p.Residence)
|
||||
}
|
||||
if p.Deathplace != "" {
|
||||
result = fmt.Sprintf("%s, deathplace: '%s'", result, p.Deathplace)
|
||||
}
|
||||
if p.OccupationToDisplay != "" {
|
||||
result = fmt.Sprintf("%s, occupation_to_display: '%s'", result, p.OccupationToDisplay)
|
||||
}
|
||||
if p.ProfilePicture != "" {
|
||||
result = fmt.Sprintf("%s, profile_picture: '%s'", result, p.ProfilePicture)
|
||||
}
|
||||
|
||||
if p.Titles != nil && len(p.Titles) > 0 {
|
||||
result = fmt.Sprintf("%s, titles: [", result)
|
||||
for _, title := range p.Titles {
|
||||
result = fmt.Sprintf("%s'%s', ", result, title)
|
||||
}
|
||||
result = fmt.Sprintf("%s]", result[:len(result)-2])
|
||||
}
|
||||
|
||||
if p.Suffixes != nil && len(p.Suffixes) > 0 {
|
||||
result = fmt.Sprintf("%s, suffixes: [", result)
|
||||
for _, suffix := range p.Suffixes {
|
||||
result = fmt.Sprintf("%s'%s', ", result, suffix)
|
||||
}
|
||||
result = fmt.Sprintf("%s]", result[:len(result)-2])
|
||||
}
|
||||
|
||||
if p.ExtraNames != nil && len(p.ExtraNames) > 0 {
|
||||
result = fmt.Sprintf("%s, extra_names: [", result)
|
||||
for _, extraName := range p.ExtraNames {
|
||||
result = fmt.Sprintf("%s'%s', ", result, extraName)
|
||||
}
|
||||
result = fmt.Sprintf("%s]", result[:len(result)-2])
|
||||
}
|
||||
|
||||
if p.Aliases != nil && len(p.Aliases) > 0 {
|
||||
result = fmt.Sprintf("%s, aliases: [", result)
|
||||
for _, alias := range p.Aliases {
|
||||
result = fmt.Sprintf("%s'%s', ", result, alias)
|
||||
}
|
||||
result = fmt.Sprintf("%s]", result[:len(result)-2])
|
||||
}
|
||||
|
||||
if p.LifeEvents != nil && len(p.LifeEvents) > 0 {
|
||||
result = fmt.Sprintf("%s, life_events: [", result)
|
||||
for i := 0; i < len(p.LifeEvents); i++ {
|
||||
date, dok := p.LifeEvents[i]["date"]
|
||||
event, eok := p.LifeEvents[i]["event"]
|
||||
if dok && eok {
|
||||
result = fmt.Sprintf("%s{date: '%s', event: '%s'}, ", result, date, event)
|
||||
}
|
||||
}
|
||||
result = fmt.Sprintf("%s]", result[:len(result)-2])
|
||||
}
|
||||
|
||||
if p.Occupations != nil && len(p.Occupations) > 0 {
|
||||
result = fmt.Sprintf("%s, occupations: [", result)
|
||||
|
||||
for _, occupation := range p.Occupations {
|
||||
result = fmt.Sprintf("%s'%s', ", result, occupation)
|
||||
}
|
||||
|
||||
result = fmt.Sprintf("%s]", result[:len(result)-2])
|
||||
}
|
||||
|
||||
if p.OthersSaid != nil {
|
||||
result = fmt.Sprintf("%s, others_said: {", result)
|
||||
for key, value := range p.OthersSaid {
|
||||
result = fmt.Sprintf("%s%s: '%s', ", result, key, value)
|
||||
}
|
||||
result = fmt.Sprintf("%s}", result[:len(result)-2])
|
||||
}
|
||||
|
||||
if p.Photos != nil && len(p.Photos) > 0 {
|
||||
result = fmt.Sprintf("%s, photos: {", result)
|
||||
for key, value := range p.Photos {
|
||||
result = fmt.Sprintf("%s%s: '%s', ", result, key, value)
|
||||
}
|
||||
result = fmt.Sprintf("%s}", result[:len(result)-2])
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Verify checks if the person is valid and does not contain cypher injection it also escapes the delimiters contained in any of the strings
|
||||
func (p *Person) Verify() error {
|
||||
if p.verified {
|
||||
return nil
|
||||
}
|
||||
if err := VerifyString(p.ID); err != nil {
|
||||
return fmt.Errorf("invalid ID type %s", err)
|
||||
}
|
||||
|
||||
p.Firstname = EscapeString(p.Firstname)
|
||||
p.Middlename = EscapeString(p.Middlename)
|
||||
p.Lastname = EscapeString(p.Lastname)
|
||||
p.MothersFirstname = EscapeString(p.MothersFirstname)
|
||||
p.MothersLastname = EscapeString(p.MothersLastname)
|
||||
p.Birthplace = EscapeString(p.Birthplace)
|
||||
p.Residence = EscapeString(p.Residence)
|
||||
p.Deathplace = EscapeString(p.Deathplace)
|
||||
p.OccupationToDisplay = EscapeString(p.OccupationToDisplay)
|
||||
p.ProfilePicture = EscapeString(p.ProfilePicture)
|
||||
|
||||
for i, title := range p.Titles {
|
||||
p.Titles[i] = EscapeString(title)
|
||||
}
|
||||
|
||||
for i, suffix := range p.Suffixes {
|
||||
p.Suffixes[i] = EscapeString(suffix)
|
||||
}
|
||||
|
||||
for i, extraName := range p.ExtraNames {
|
||||
p.ExtraNames[i] = EscapeString(extraName)
|
||||
}
|
||||
|
||||
for i, alias := range p.Aliases {
|
||||
p.Aliases[i] = EscapeString(alias)
|
||||
}
|
||||
|
||||
for i, lifeEvent := range p.LifeEvents {
|
||||
for key, value := range lifeEvent {
|
||||
if key != "date" && key != "event" {
|
||||
return fmt.Errorf("invalid key in life event")
|
||||
}
|
||||
p.LifeEvents[i][key] = EscapeString(value)
|
||||
}
|
||||
}
|
||||
|
||||
for i, occupation := range p.Occupations {
|
||||
p.Occupations[i] = EscapeString(occupation)
|
||||
}
|
||||
|
||||
for key, value := range p.OthersSaid {
|
||||
if err := VerifyString(key); err != nil {
|
||||
return fmt.Errorf("invalid key in others said %s", err)
|
||||
}
|
||||
p.OthersSaid[key] = EscapeString(value)
|
||||
}
|
||||
|
||||
for key, value := range p.Photos {
|
||||
if err := VerifyString(key); err != nil {
|
||||
return fmt.Errorf("invalid key in photos %s", err)
|
||||
}
|
||||
p.Photos[key] = EscapeString(value)
|
||||
}
|
||||
|
||||
p.verified = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Relationship struct {
|
||||
FirstPersonID string `json:"first_person_id"`
|
||||
SecondPersonID string `json:"second_person_id"`
|
||||
Relationship string `json:"relationship"`
|
||||
Direction string `json:"direction"`
|
||||
}
|
||||
|
||||
// Verify checks if the relationship is valid and does not contain cypher injection
|
||||
func (r *Relationship) Verify() error {
|
||||
if r.Direction != "->" && r.Direction != "<-" && r.Direction != "-" {
|
||||
return fmt.Errorf("invalid direction for relationship")
|
||||
}
|
||||
|
||||
// Check if the relationship is in the list of valid relationships
|
||||
found := false
|
||||
for _, relationship := range RelationshipTypes {
|
||||
if r.Relationship == relationship {
|
||||
found = true
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("invalid relationship type")
|
||||
}
|
||||
|
||||
if err := VerifyString(r.FirstPersonID); err != nil {
|
||||
return fmt.Errorf("invalid FirstPersonID type %s", err)
|
||||
}
|
||||
|
||||
if err := VerifyString(r.SecondPersonID); err != nil {
|
||||
return fmt.Errorf("invalid SecondPersonID type %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type RelationshipAndPerson struct {
|
||||
Relationship Relationship `json:"relationship"`
|
||||
Person Person `json:"person"`
|
||||
}
|
||||
|
||||
func (r *RelationshipAndPerson) Verify() error {
|
||||
if err := r.Relationship.Verify(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.Person.Verify(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
77
apps/db-adapter/pkg/memgraph/model_test.go
Normal file
77
apps/db-adapter/pkg/memgraph/model_test.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPerson_ToString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
p *Person
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "Test with nil values",
|
||||
p: &Person{
|
||||
ID: "1",
|
||||
Firstname: "John",
|
||||
Lastname: "Doe",
|
||||
MothersFirstname: "Jane",
|
||||
MothersLastname: "Doe",
|
||||
Born: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
Birthplace: "New York",
|
||||
Residence: "New York",
|
||||
Death: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
Deathplace: "New York",
|
||||
},
|
||||
want: "ID: '1', Firstname: 'John', Lastname: 'Doe', MothersFirstname: 'Jane', MothersLastname: 'Doe', Born: date({year:2021, month:1, day:1}), Death: date({year:2021, month:1, day:1}), Birthplace: 'New York', Residence: 'New York', Deathplace: 'New York', OccupationToDisplay: '', ProfilePicture: ''",
|
||||
}, {
|
||||
name: "Test with All values",
|
||||
p: &Person{
|
||||
ID: "1",
|
||||
Firstname: "John",
|
||||
Lastname: "Doe",
|
||||
MothersFirstname: "Jane",
|
||||
MothersLastname: "Doe",
|
||||
Born: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
Birthplace: "New York",
|
||||
Residence: "New York",
|
||||
Death: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
Deathplace: "New York",
|
||||
LifeEvents: []map[string]string{
|
||||
{
|
||||
"date": "2021-01-01",
|
||||
"event": "Event 1",
|
||||
},
|
||||
{
|
||||
"date": "2021-01-02",
|
||||
"event": "Event 2",
|
||||
},
|
||||
},
|
||||
Occupations: []string{
|
||||
"Welder",
|
||||
"Plumber",
|
||||
},
|
||||
OccupationToDisplay: "Welder",
|
||||
OthersSaid: map[string]string{
|
||||
"Beni": "He is a good person",
|
||||
"Jani": "He is a bad person",
|
||||
},
|
||||
Photos: map[string]string{
|
||||
"Profile": "profile.jpg",
|
||||
"Family": "family.jpg",
|
||||
},
|
||||
ProfilePicture: "profile.jpg",
|
||||
},
|
||||
want: "ID: '1', Firstname: 'John', Lastname: 'Doe', MothersFirstname: 'Jane', MothersLastname: 'Doe', Born: date({year:2021, month:1, day:1}), Death: date({year:2021, month:1, day:1}), Birthplace: 'New York', Residence: 'New York', Deathplace: 'New York', OccupationToDisplay: 'Welder', ProfilePicture: 'profile.jpg', LifeEvents: [{date: '2021-01-01', event: 'Event 1'}, {date: '2021-01-02', event: 'Event 2'}], Occupations: ['Welder', 'Plumber'], OthersSaid: {Beni: 'He is a good person', Jani: 'He is a bad person'}, Photos: {Profile: 'profile.jpg', Family: 'family.jpg'}",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.p.ToString(); got != tt.want {
|
||||
t.Errorf("Person.ToString() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
MATCH (a:Person), (b:Person)
|
||||
WHERE id(a) = $id1 AND id(b) = $id2
|
||||
CREATE (a)-[r:Relationship $Relationship]->(b)
|
||||
RETURN r AS relationship
|
@@ -0,0 +1 @@
|
||||
CREATE (p:Person $Person) RETURN p as person
|
@@ -0,0 +1,4 @@
|
||||
MATCH (a:Person), (b:Person)
|
||||
WHERE id(a) = $id1 AND id(b) = $id2
|
||||
CREATE (a)-[r:Relationship $Relationship]-(b)
|
||||
RETURN r as relationship
|
@@ -0,0 +1,5 @@
|
||||
MATCH (a:Person), (b:Person)
|
||||
WHERE id(a) = $id1 AND id(b) = $id2
|
||||
CREATE (a)-[r1:Relationship $Relationship1]->(b)
|
||||
CREATE (b)-[r2:Relationship $Relationship2]->(a)
|
||||
RETURN r1 as relationship1, r2 as relationship2
|
@@ -0,0 +1,8 @@
|
||||
MATCH (n:Person)-[p:Parent*1..]->(family:Person)
|
||||
WHERE id(n) = $id
|
||||
OPTIONAL MATCH (family)-[c:Child]->(children:Person)
|
||||
WITH family, p, children, c, n
|
||||
OPTIONAL MATCH (children)<-[p2:Parent]-(OtherParents:Person)
|
||||
WITH family, p, children, c, OtherParents, p2, n
|
||||
OPTIONAL MATCH (family)-[s:Spouse]-(spouse:Person)
|
||||
RETURN family, p, children, c, OtherParents, p2, spouse, s, n;
|
@@ -0,0 +1 @@
|
||||
MATCH (n:Person) WHERE n.id = $id RETURN n AS people
|
@@ -0,0 +1 @@
|
||||
MATCH (n:Person) WHERE n.google_id = $google_id RETURN n as person
|
@@ -0,0 +1 @@
|
||||
MATCH (n:Person) WHERE id(n) = $id RETURN n as person
|
@@ -0,0 +1,3 @@
|
||||
MATCH (n)-[r]-(o)
|
||||
WHERE id(n) = $id1 AND id(o) = $id2
|
||||
RETURN r as relationship
|
@@ -0,0 +1,3 @@
|
||||
MATCH (n:DeletedPerson)
|
||||
WHERE id(n) = $id
|
||||
DETACH DELETE n;
|
14
apps/db-adapter/pkg/memgraph/queries/schema.cypher
Normal file
14
apps/db-adapter/pkg/memgraph/queries/schema.cypher
Normal file
@@ -0,0 +1,14 @@
|
||||
CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.last_name);
|
||||
CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.first_name);
|
||||
CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.born);
|
||||
CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.mothers_first_name);
|
||||
CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.mothers_last_name);
|
||||
CREATE CONSTRAINT ON (n:Person) ASSERT n.google_id IS UNIQUE;
|
||||
CREATE CONSTRAINT ON (n:Person) ASSERT n.last_name, n.first_name, n.born, n.mothers_first_name, n.mothers_last_name IS UNIQUE;
|
||||
|
||||
CREATE INDEX ON :Person(google_id);
|
||||
CREATE INDEX ON :Person(last_name);
|
||||
CREATE INDEX ON :Person(first_name);
|
||||
CREATE INDEX ON :Person(born);
|
||||
CREATE INDEX ON :Person(mothers_first_name);
|
||||
CREATE INDEX ON :Person(mothers_last_name);
|
@@ -0,0 +1,4 @@
|
||||
MATCH (n:Person {id: $id})
|
||||
SET n:DeletedPerson
|
||||
REMOVE n:Person
|
||||
RETURN labels(n) AS labels, n AS person
|
@@ -0,0 +1,4 @@
|
||||
MATCH (n:Person)
|
||||
WHERE id(n) = $id
|
||||
SET n += $props
|
||||
RETURN n AS person
|
30
apps/db-adapter/pkg/memgraph/update_person.go
Normal file
30
apps/db-adapter/pkg/memgraph/update_person.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (p *Person) UpdatePerson(driver neo4j.DriverWithContext) (*neo4j.Record, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
|
||||
defer session.Close(ctx)
|
||||
|
||||
if err := p.Verify(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("MATCH (n:Person {id: '%s'}) SET n += {%s} RETURN n;", p.ID, p.ToString())
|
||||
|
||||
result, err := session.Run(ctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Single(ctx)
|
||||
}
|
39
apps/db-adapter/pkg/memgraph/verify_relationship.go
Normal file
39
apps/db-adapter/pkg/memgraph/verify_relationship.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (r *Relationship) VerifyRelationship(driver neo4j.DriverWithContext) (*neo4j.Record, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
|
||||
defer session.Close(ctx)
|
||||
|
||||
if err := r.Verify(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := ""
|
||||
if r.Direction == "->" {
|
||||
query = fmt.Sprintf(`MATCH (a)-[r:%s]->(b)`, r.Relationship)
|
||||
} else if r.Direction == "<-" {
|
||||
query = fmt.Sprintf(`MATCH (a)<-[r:%s]-(b)`, r.Relationship)
|
||||
} else {
|
||||
query = fmt.Sprintf(`MATCH (a)-[r:%s]-(b)`, r.Relationship)
|
||||
}
|
||||
|
||||
query = fmt.Sprintf(`%s WHERE a.id = %s AND b.id = %s set r.verified = true return r;`, query, r.FirstPersonID, r.SecondPersonID)
|
||||
|
||||
result, err := session.Run(ctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Single(ctx)
|
||||
}
|
40
apps/db-adapter/pkg/setup_https_server.go
Normal file
40
apps/db-adapter/pkg/setup_https_server.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func SetupHttpsServer(router http.Handler, cert, key, httpsPort, httpPort string, requestTimeout time.Duration) (server *http.Server) {
|
||||
if FileExists(cert) && FileExists(key) {
|
||||
server = &http.Server{
|
||||
Addr: httpsPort,
|
||||
Handler: router,
|
||||
ReadTimeout: 5 * time.Second,
|
||||
WriteTimeout: 10 * time.Second,
|
||||
}
|
||||
go func() {
|
||||
log.Println("Server starts at port ", httpsPort)
|
||||
if err := server.ListenAndServeTLS(cert, key); err != nil && errors.Is(err, http.ErrServerClosed) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
server = &http.Server{
|
||||
Addr: httpPort,
|
||||
Handler: router,
|
||||
ReadTimeout: requestTimeout * time.Second,
|
||||
WriteTimeout: requestTimeout * time.Second,
|
||||
}
|
||||
go func() {
|
||||
log.Println("Server starts at port ", httpPort)
|
||||
if err := server.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
return server
|
||||
}
|
Reference in New Issue
Block a user