mirror of
https://github.com/vcscsvcscs/GenerationsHeritage.git
synced 2025-08-13 14:29:05 +02:00
Compare commits
115 Commits
feature/cr
...
feature/ad
Author | SHA1 | Date | |
---|---|---|---|
5a7e62a183 | |||
5e871cb272 | |||
22ca38ad86 | |||
3ade387d7d | |||
77042ffdc5 | |||
5b9b6c53a6 | |||
0b0b138c16 | |||
304552c2a5 | |||
cf4b79c593 | |||
bc7cf7f1a6 | |||
e49aba7c58 | |||
01c6e4b0c9 | |||
564ef322e3 | |||
d85d37eb2d | |||
913042d441 | |||
56607b31e5 | |||
a5822913f6 | |||
5d03c51097 | |||
5e8cdecca7 | |||
40a70ecc93 | |||
12bb08d6ce | |||
eadfcd7afc | |||
5d19dad30f | |||
7358ef5db1 | |||
68bd7dec11 | |||
f10d8a87db | |||
72f81214be | |||
47b52d8a33 | |||
2e4cd879b2 | |||
ca67dead2b | |||
162fe47051 | |||
d49601b871 | |||
f5e95095c7 | |||
c54b142b70 | |||
65345e0e76 | |||
a34a934bf4 | |||
73627c7c59 | |||
33aa4945af | |||
3b12f4798c | |||
cb6628a83c | |||
a4c1bc56f8 | |||
79256f2f10 | |||
cdea69736d | |||
|
ffde94d457 | ||
423e5502a7 | |||
422e2f683a | |||
35f478e24c | |||
a6718b2487 | |||
|
317fc9067e | ||
4c1b5bcce4 | |||
|
30321ba5d7 | ||
f42d966183 | |||
94820faf8c | |||
8d1bb6dbfe | |||
150d3d7b33 | |||
d004a155d7 | |||
9996b79b46 | |||
504de2fc2e | |||
36b34a161f | |||
|
87b63e40ce | ||
3e40c09f18 | |||
ab007395bc | |||
a1e14f0a7b | |||
2ba61b0854 | |||
8bf6027e42 | |||
723c108ec4 | |||
2e718c06f6 | |||
26c227c062 | |||
2e720c326a | |||
608b0e3fb2 | |||
a88550f8cd | |||
b06cfcaf69 | |||
a78161d389 | |||
0aad11b1d6 | |||
4199d65d6c | |||
d533738a32 | |||
a0233fdc2d | |||
e89b1638d9 | |||
2492b94be8 | |||
518f86caa4 | |||
303c582217 | |||
cc9fbd42da | |||
16457111cd | |||
28395c2859 | |||
b7eaa44d26 | |||
ac514578f3 | |||
13f0eea33c | |||
91376d87de | |||
0226b93135 | |||
65f6200b81 | |||
6e7e767f54 | |||
30ae64e2f6 | |||
cda79c4428 | |||
db0b28ca79 | |||
befd578bf9 | |||
2e233abfd6 | |||
d3be181d77 | |||
a230886c40 | |||
4bc365c4a2 | |||
26b446ab54 | |||
a4a79a1136 | |||
4764be0c2e | |||
2cb55937c9 | |||
de64411eb0 | |||
1ee384813b | |||
bb7370ae33 | |||
3c47578809 | |||
23743a23b9 | |||
e2450247e7 | |||
3d9398e9c1 | |||
59b3b31b44 | |||
3a2dd1972a | |||
48e7e414dd | |||
494278875b | |||
d0915986a6 |
51
.github/workflows/auth-service-cd.yml
vendored
Normal file
51
.github/workflows/auth-service-cd.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Release Auth service to Docker Hub and Deploy to Kubernetes
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "auth-service/**"
|
||||
- "deployment/auth-service/**"
|
||||
- ".github/workflows/auth-service-cd.yml"
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
name: Build and Push Auth-service image to Docker Hub
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
id: create_image_tag
|
||||
with:
|
||||
script: |
|
||||
if(github.ref == 'refs/heads/main') {
|
||||
return 'latest';
|
||||
} else if(context.issue.number) {
|
||||
return "pr" + context.issue.number;
|
||||
} else {
|
||||
return "pr" + (
|
||||
await github.rest.repos.listPullRequestsAssociatedWithCommit({
|
||||
commit_sha: context.sha,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
).data[0].number;
|
||||
}
|
||||
result-encoding: string
|
||||
- name: Image tag
|
||||
run: echo '${{steps.create_image_tag.outputs.result}}'
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
context: "{{defaultContext}}:auth-service"
|
||||
tags: vcscsvcscs/gheritage-auth-service:${{steps.create_image_tag.outputs.result}}
|
||||
platforms: linux/arm64/v8
|
20
.github/workflows/auth-service-ci.yml
vendored
Normal file
20
.github/workflows/auth-service-ci.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Authentication service Continuous Integration
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "auth-service/**"
|
||||
jobs:
|
||||
lint:
|
||||
uses: ./.github/workflows/go_lint.yml
|
||||
with:
|
||||
working-directory: 'auth-service'
|
||||
build:
|
||||
needs: lint
|
||||
uses: ./.github/workflows/go_build.yml
|
||||
with:
|
||||
working-directory: 'auth-service'
|
||||
test:
|
||||
needs: build
|
||||
uses: ./.github/workflows/go_test.yml
|
||||
with:
|
||||
working-directory: 'auth-service'
|
51
.github/workflows/backend-cd.yml
vendored
Normal file
51
.github/workflows/backend-cd.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Release Backend service to Docker Hub and Deploy to Kubernetes
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "backend/**"
|
||||
- "deployment/backend/**"
|
||||
- ".github/workflows/backend-cd.yml"
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
name: Build and Push Backend image to Docker Hub
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
id: create_image_tag
|
||||
with:
|
||||
script: |
|
||||
if(github.ref == 'refs/heads/main') {
|
||||
return 'latest';
|
||||
} else if(context.issue.number) {
|
||||
return "pr" + context.issue.number;
|
||||
} else {
|
||||
return "pr" + (
|
||||
await github.rest.repos.listPullRequestsAssociatedWithCommit({
|
||||
commit_sha: context.sha,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
).data[0].number;
|
||||
}
|
||||
result-encoding: string
|
||||
- name: Image tag
|
||||
run: echo '${{steps.create_image_tag.outputs.result}}'
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
context: "{{defaultContext}}:backend"
|
||||
tags: vcscsvcscs/gheritage-backend-service:${{steps.create_image_tag.outputs.result}}
|
||||
platforms: linux/arm64/v8
|
20
.github/workflows/backend-ci.yml
vendored
Normal file
20
.github/workflows/backend-ci.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Backend Continuous Integration
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "backend/**"
|
||||
jobs:
|
||||
lint:
|
||||
uses: ./.github/workflows/go_lint.yml
|
||||
with:
|
||||
working-directory: 'backend'
|
||||
build:
|
||||
needs: lint
|
||||
uses: ./.github/workflows/go_build.yml
|
||||
with:
|
||||
working-directory: 'backend'
|
||||
test:
|
||||
needs: build
|
||||
uses: ./.github/workflows/go_test.yml
|
||||
with:
|
||||
working-directory: 'backend'
|
15
.github/workflows/frontend-ci.yml
vendored
Normal file
15
.github/workflows/frontend-ci.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
name: Frontend Continuous Integration
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "frontend/**"
|
||||
jobs:
|
||||
lint:
|
||||
uses: ./.github/workflows/svelte_lint.yml
|
||||
with:
|
||||
working-directory: 'frontend'
|
||||
build:
|
||||
needs: lint
|
||||
uses: ./.github/workflows/svelte_build.yml
|
||||
with:
|
||||
working-directory: 'frontend'
|
29
.github/workflows/go_build.yml
vendored
Normal file
29
.github/workflows/go_build.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
working-directory:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go 1.22.x'
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22.x'
|
||||
|
||||
- name: Display Go version
|
||||
run: go version
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd ${{ inputs.working-directory }}
|
||||
go get
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cd ${{ inputs.working-directory }}
|
||||
go build .
|
22
.github/workflows/go_lint.yml
vendored
Normal file
22
.github/workflows/go_lint.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
working-directory:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
cache: false
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v4
|
||||
with:
|
||||
version: latest
|
||||
working-directory: ${{ inputs.working-directory }}
|
29
.github/workflows/go_test.yml
vendored
Normal file
29
.github/workflows/go_test.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
working-directory:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go 1.22.x'
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22.x'
|
||||
|
||||
- name: Display Go version
|
||||
run: go version
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd ${{ inputs.working-directory }}
|
||||
go get
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd ${{ inputs.working-directory }}
|
||||
go test ./...
|
24
.github/workflows/svelte_build.yml
vendored
Normal file
24
.github/workflows/svelte_build.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
working-directory:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '21.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd ${{ inputs.working-directory }}
|
||||
npm ci
|
||||
- name: Build
|
||||
run: |
|
||||
cd ${{ inputs.working-directory }}
|
||||
npm run build
|
24
.github/workflows/svelte_lint.yml
vendored
Normal file
24
.github/workflows/svelte_lint.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
working-directory:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '21.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd ${{ inputs.working-directory }}
|
||||
npm ci
|
||||
- name: Lint
|
||||
run: |
|
||||
cd ${{ inputs.working-directory }}
|
||||
npm run lint
|
132
.golangci.yml
Normal file
132
.golangci.yml
Normal file
@@ -0,0 +1,132 @@
|
||||
linters-settings:
|
||||
depguard:
|
||||
rules:
|
||||
logger:
|
||||
deny:
|
||||
# logging is allowed only by logutils.Log,
|
||||
# logrus is allowed to use only in logutils package.
|
||||
- pkg: "github.com/sirupsen/logrus"
|
||||
desc: logging is allowed only by logutils.Log.
|
||||
- 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: 50
|
||||
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
|
||||
gofmt:
|
||||
rewrite-rules:
|
||||
- pattern: 'interface{}'
|
||||
replacement: 'any'
|
||||
gomnd:
|
||||
# don't include the "operation" and "assign"
|
||||
checks:
|
||||
- argument
|
||||
- case
|
||||
- condition
|
||||
- return
|
||||
ignored-numbers:
|
||||
- '0'
|
||||
- '1'
|
||||
- '2'
|
||||
- '3'
|
||||
ignored-functions:
|
||||
- strings.SplitN
|
||||
govet:
|
||||
settings:
|
||||
printf:
|
||||
funcs:
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
enable:
|
||||
- nilness
|
||||
- shadow
|
||||
errorlint:
|
||||
asserts: false
|
||||
lll:
|
||||
line-length: 140
|
||||
misspell:
|
||||
locale: US
|
||||
nolintlint:
|
||||
allow-unused: false # report any unused nolint directives
|
||||
require-explanation: false # don't require an explanation for nolint directives
|
||||
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
|
||||
revive:
|
||||
rules:
|
||||
- name: unexported-return
|
||||
disabled: true
|
||||
- name: unused-parameter
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- bodyclose
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupl
|
||||
- errcheck
|
||||
- errorlint
|
||||
- exportloopref
|
||||
- funlen
|
||||
- gocheckcompilerdirectives
|
||||
- gochecknoinits
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- gofmt
|
||||
- goimports
|
||||
- gomnd
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- lll
|
||||
- misspell
|
||||
- nakedret
|
||||
- noctx
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- whitespace
|
||||
|
||||
# don't enable:
|
||||
# - asciicheck
|
||||
# - gochecknoglobals
|
||||
# - gocognit
|
||||
# - godot
|
||||
# - godox
|
||||
# - goerr113
|
||||
# - nestif
|
||||
# - prealloc
|
||||
# - testpackage
|
||||
# - wsl
|
||||
|
||||
run:
|
||||
timeout: 5m
|
@@ -23,3 +23,10 @@ The purpose of the thesis is to develop a web application that enables the commu
|
||||
Users could register and the system would provide the ability to edit their own profiles, which are part of the family tree structure. The family tree would contain not only names and birth dates but also additional information such as schools, residences, workplaces, life wisdom, important knowledge, and photos. Furthermore, the application would employ protective measures, so that only those related by blood could access each other's data.
|
||||
|
||||
The task is highly complex, as it involves not only designing the user interface and the family tree structure but also properly implementing security layers. The development of the database system, the cloud-based server, and the CI/CD system present further challenges. The application must ensure optimal display on various devices and screen sizes, which requires additional development and design skills. The thesis details the extent to which specific challenges and solutions related to the project contribute to the success and functionality of the software.
|
||||
|
||||
## Deployment
|
||||
To deploy all micro services use:
|
||||
|
||||
```bash:
|
||||
kubectl apply --server-side -k .
|
||||
```
|
13
auth-service/dockerfile
Normal file
13
auth-service/dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM golang:1.22.2-alpine as build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN GOOS=linux GOARCH=arm64 go build -o auth-service
|
||||
|
||||
FROM arm64v8/busybox
|
||||
|
||||
COPY --from=build /app/auth-service /app/
|
||||
|
||||
CMD [ "/app/auth-service" ]
|
@@ -1,3 +1,32 @@
|
||||
module github.com/vcscsvcscs/GenerationsHeritage/auth-service
|
||||
|
||||
go 1.22.0
|
||||
go 1.22.2
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.9.1 // 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.14.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
github.com/vcscsvcscs/GenerationsHeritage/utilities v0.0.0-20240414091827-ffde94d457cb // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.9.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
80
auth-service/go.sum
Normal file
80
auth-service/go.sum
Normal file
@@ -0,0 +1,80 @@
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
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/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
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.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
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.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
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/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/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/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
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.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/vcscsvcscs/GenerationsHeritage/utilities v0.0.0-20240414091827-ffde94d457cb h1:fU736we2gQQRMOWP/su7sCiUFmrXTKBN0s8LG5k7bOE=
|
||||
github.com/vcscsvcscs/GenerationsHeritage/utilities v0.0.0-20240414091827-ffde94d457cb/go.mod h1:aQlmG6BiGFmOFxzAkWTJDzm1EzdCJ4OEETXTUkWJaLk=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
13
backend/dockerfile
Normal file
13
backend/dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM golang:1.22.2-alpine as build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN GOOS=linux GOARCH=arm64 go build -o backend
|
||||
|
||||
FROM busybox
|
||||
|
||||
COPY --from=build /app/backend /app/
|
||||
|
||||
CMD [ "/app/backend" ]
|
@@ -1,6 +1,14 @@
|
||||
module github.com/vcscsvcscs/GenerationsHeritage/backend
|
||||
|
||||
go 1.22.0
|
||||
go 1.22.2
|
||||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.19.0
|
||||
github.com/vcscsvcscs/GenerationsHeritage/utilities v0.0.0-20240414091827-ffde94d457cb
|
||||
golang.org/x/net v0.22.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.11.3 // indirect
|
||||
@@ -8,7 +16,6 @@ require (
|
||||
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.9.1 // 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.19.0 // indirect
|
||||
@@ -24,7 +31,6 @@ require (
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/net v0.22.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
|
@@ -10,6 +10,7 @@ github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLI
|
||||
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
|
||||
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
|
||||
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/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
@@ -17,6 +18,8 @@ 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.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
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=
|
||||
@@ -25,9 +28,11 @@ github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn
|
||||
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
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/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
@@ -43,8 +48,11 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
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/neo4j/neo4j-go-driver/v5 v5.19.0 h1:v2cB19fZQYz1xmj6EZXofFHD/+Tj16hH/OOp39uNN1I=
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.19.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k=
|
||||
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
|
||||
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
@@ -56,11 +64,16 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
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/vcscsvcscs/GenerationsHeritage/utilities v0.0.0-20240413225529-30321ba5d7e7 h1:6HOZdgsOt8KojDfNDOyHLwv+Chv90MECxMdP+cKKNv4=
|
||||
github.com/vcscsvcscs/GenerationsHeritage/utilities v0.0.0-20240413225529-30321ba5d7e7/go.mod h1:8byGXK+Csy5RCmHrvdMIzS8oVuvkr9Ech2PqLrad7os=
|
||||
github.com/vcscsvcscs/GenerationsHeritage/utilities v0.0.0-20240414091827-ffde94d457cb h1:fU736we2gQQRMOWP/su7sCiUFmrXTKBN0s8LG5k7bOE=
|
||||
github.com/vcscsvcscs/GenerationsHeritage/utilities v0.0.0-20240414091827-ffde94d457cb/go.mod h1:aQlmG6BiGFmOFxzAkWTJDzm1EzdCJ4OEETXTUkWJaLk=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
|
||||
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
@@ -74,9 +87,11 @@ golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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=
|
||||
|
48
backend/handlers/createPerson.go
Normal file
48
backend/handlers/createPerson.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/backend/memgraph"
|
||||
)
|
||||
|
||||
func CreatePerson(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if c.Request.Body == nil || c.ContentType() != "application/json" {
|
||||
log.Printf("ip: %s error: request body is empty or content type is not application/json", c.ClientIP())
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "content type must be application/json and request body must not be empty"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var person memgraph.Person
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&person)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err.Error())
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := person.Verify(); err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err.Error())
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "contains-forbidden-characters"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
rec, err := person.CreatePerson(driver)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err.Error())
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "already-exists"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{"person": rec.AsMap()})
|
||||
}
|
||||
}
|
32
backend/handlers/createRelationship.go
Normal file
32
backend/handlers/createRelationship.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/backend/memgraph"
|
||||
)
|
||||
|
||||
func CreateRelationship(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var relationship memgraph.Relationship
|
||||
if err := c.ShouldBindJSON(&relationship); err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
rec, err := relationship.CreateRelationship(driver)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{"relationship": rec.AsMap()})
|
||||
}
|
||||
}
|
32
backend/handlers/create_relationship_and_person.go
Normal file
32
backend/handlers/create_relationship_and_person.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/backend/memgraph"
|
||||
)
|
||||
|
||||
func CreateRelationshipAndPerson(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var rp memgraph.RelationshipAndPerson
|
||||
if err := c.ShouldBindJSON(&rp); err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
rec, err := rp.CreateRelationshipAndPerson(driver)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{"relationship": rec.AsMap()})
|
||||
}
|
||||
}
|
48
backend/handlers/deletePerson.go
Normal file
48
backend/handlers/deletePerson.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/backend/memgraph"
|
||||
)
|
||||
|
||||
func DeletePerson(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if c.Request.Body == nil || c.ContentType() != "application/json" {
|
||||
log.Printf("ip: %s error: request body is empty or content type is not application/json", c.ClientIP())
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "content type must be application/json and request body must not be empty"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var person memgraph.Person
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&person)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if person.ID != "" {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no person ID provided"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = person.DeletePerson(driver)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "could not delete person with ID provided"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"status": "person deleted successfully"})
|
||||
}
|
||||
}
|
32
backend/handlers/deleteRelationship.go
Normal file
32
backend/handlers/deleteRelationship.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/backend/memgraph"
|
||||
)
|
||||
|
||||
func DeleteRelationship(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var relationship memgraph.Relationship
|
||||
if err := c.ShouldBindJSON(&relationship); err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err := relationship.DeleteRelationship(driver)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusAccepted, gin.H{"status": "relationship deleted successfully"})
|
||||
}
|
||||
}
|
48
backend/handlers/updatePerson.go
Normal file
48
backend/handlers/updatePerson.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/backend/memgraph"
|
||||
)
|
||||
|
||||
func UpdatePerson(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if c.Request.Body == nil || c.ContentType() != "application/json" {
|
||||
log.Printf("ip: %s error: request body is empty or content type is not application/json", c.ClientIP())
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "content type must be application/json and request body must not be empty"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var person memgraph.Person
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&person)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if person.ID == "" {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "No ID provided"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
rec, err := person.UpdatePerson(driver)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "could not update person with information provided"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"person": rec.AsMap()})
|
||||
}
|
||||
}
|
32
backend/handlers/verifyRelationship.go
Normal file
32
backend/handlers/verifyRelationship.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/backend/memgraph"
|
||||
)
|
||||
|
||||
func VerifyRelationship(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var relationship memgraph.Relationship
|
||||
if err := c.ShouldBindJSON(&relationship); err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
rec, err := relationship.VerifyRelationship(driver)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"relationship": rec.AsMap()})
|
||||
}
|
||||
}
|
55
backend/handlers/viewFamilyTree.go
Normal file
55
backend/handlers/viewFamilyTree.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
)
|
||||
|
||||
func ViewFamiliyTree(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeRead})
|
||||
defer session.Close(ctx)
|
||||
|
||||
id := c.Query("id")
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
query := `
|
||||
MATCH (n:Person {ID: $person_id})-[p:Parent*1..]->(family:Person)
|
||||
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`
|
||||
|
||||
result, err := session.Run(ctx, query, map[string]any{"person_id": id})
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
rec, err := result.Single(ctx)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "could not find family tree for person with id: " + id})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, rec.AsMap()["n"])
|
||||
}
|
||||
}
|
46
backend/handlers/viewPerson.go
Normal file
46
backend/handlers/viewPerson.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
)
|
||||
|
||||
func ViewPerson(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
session := driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeRead})
|
||||
defer session.Close(ctx)
|
||||
|
||||
id := c.Query("id")
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
result, err := session.Run(ctx, "MATCH (n:Person) WHERE n.ID = $person_id RETURN n;", map[string]any{"person_id": id})
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
rec, err := result.Single(ctx)
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "could not find person with information provided"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, rec.AsMap()["n"])
|
||||
}
|
||||
}
|
@@ -2,18 +2,16 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/backend/handlers"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/backend/memgraph"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/utilities"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/utilities/gin_liveness"
|
||||
)
|
||||
@@ -23,6 +21,9 @@ var (
|
||||
key = flag.String("key", "./private/keys/key.pem", "Specify the path of TLS key")
|
||||
httpsPort = flag.String("https", ":443", "Specify port for http secure hosting(example for format :443)")
|
||||
httpPort = flag.String("http", ":80", "Specify port for http hosting(example for format :80)")
|
||||
memgraphURI = flag.String("memgraph", "bolt+ssc://memgraph:7687", "Specify the Memgraph database URI")
|
||||
memgraphUser = flag.String("memgraph-user", "", "Specify the Memgraph database user")
|
||||
memgraphPass = flag.String("memgraph-pass", "", "Specify the Memgraph database password")
|
||||
release = flag.Bool("release", false, "Set true to release build")
|
||||
logToFile = flag.Bool("log-to-file", false, "Set true to log to file")
|
||||
logToFileAndStd = flag.Bool("log-to-file-and-std", false, "Set true to log to file and std")
|
||||
@@ -34,56 +35,26 @@ func main() {
|
||||
if *release {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
if *logToFileAndStd || *logToFile {
|
||||
gin.DisableConsoleColor() // Disable Console Color, you don't need console color when writing the logs to file.
|
||||
path := fmt.Sprintf("private/logs/%02dy_%02dm_%02dd_%02dh_%02dm_%02ds.log", time.Now().Year(), time.Now().Month(), time.Now().Day(), time.Now().Hour(), time.Now().Minute(), time.Now().Second())
|
||||
logerror1 := os.MkdirAll("private/logs/", 0755)
|
||||
f, logerror2 := os.Create(path)
|
||||
if logerror1 != nil || logerror2 != nil {
|
||||
log.Println("Cant log to file")
|
||||
} else if *logToFileAndStd {
|
||||
gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
|
||||
} else {
|
||||
gin.DefaultWriter = io.MultiWriter(f)
|
||||
}
|
||||
}
|
||||
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||||
log.SetOutput(gin.DefaultErrorWriter)
|
||||
|
||||
utilities.SetupLogger(*logToFileAndStd, *logToFile)
|
||||
|
||||
hc := gin_liveness.New()
|
||||
|
||||
memgraphDriver := memgraph.InitDatabase(*memgraphURI, *memgraphUser, *memgraphPass)
|
||||
|
||||
router := gin.Default()
|
||||
router.GET("/health", hc.HealthCheckHandler())
|
||||
router.GET("/person", handlers.ViewPerson(memgraphDriver))
|
||||
router.POST("/person", handlers.CreatePerson(memgraphDriver))
|
||||
router.DELETE("/person", handlers.DeletePerson(memgraphDriver))
|
||||
router.PUT("/person", handlers.UpdatePerson(memgraphDriver))
|
||||
router.POST("/relationship", handlers.CreateRelationship(memgraphDriver))
|
||||
router.DELETE("/relationship", handlers.DeleteRelationship(memgraphDriver))
|
||||
router.PUT("/relationship", handlers.VerifyRelationship(memgraphDriver))
|
||||
router.POST("/createRelationshipAndPerson", handlers.CreateRelationshipAndPerson(memgraphDriver))
|
||||
router.GET("/familyTree", handlers.ViewFamiliyTree(memgraphDriver))
|
||||
|
||||
var server *http.Server
|
||||
|
||||
if utilities.FileExists(*cert) && utilities.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)
|
||||
}
|
||||
}()
|
||||
}
|
||||
server := utilities.SetupHttpsServer(router, *cert, *key, *httpsPort, *httpPort, requestTimeout)
|
||||
|
||||
// Wait for interrupt signal to gracefully shutdown the server with some time to finish requests.
|
||||
quit := make(chan os.Signal, 1)
|
||||
|
34
backend/memgraph/create_person.go
Normal file
34
backend/memgraph/create_person.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"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(), 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
|
||||
}
|
||||
|
||||
p.ID = strings.ReplaceAll(uuid.New().String(), "-", "")
|
||||
|
||||
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
backend/memgraph/create_relationship.go
Normal file
39
backend/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)
|
||||
}
|
45
backend/memgraph/create_relationship_and_person.go
Normal file
45
backend/memgraph/create_relationship_and_person.go
Normal file
@@ -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
backend/memgraph/create_schema.go
Normal file
66
backend/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(Lastname);`,
|
||||
`CREATE INDEX ON :Person(Firstname);`,
|
||||
`CREATE INDEX ON :Person(Born);`,
|
||||
`CREATE INDEX ON :Person(MothersFirstname);`,
|
||||
`CREATE INDEX ON :Person(MothersLastname);`,
|
||||
}
|
||||
|
||||
// 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.Lastname);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.Firstname);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.Born);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.MothersFirstname);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT EXISTS (n.MothersLastname);`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT n.ID IS UNIQUE;`,
|
||||
`CREATE CONSTRAINT ON (n:Person) ASSERT n.Lastname, n.Firstname, n.Born, n.MothersFirstname, n.MothersLastname 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
backend/memgraph/cypher_verify_string.go
Normal file
124
backend/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
backend/memgraph/delete_person.go
Normal file
27
backend/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
backend/memgraph/delete_relationship.go
Normal file
36
backend/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
backend/memgraph/init_database.go
Normal file
32
backend/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
backend/memgraph/model.go
Normal file
272
backend/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, Firstname: '%s'", result, p.Firstname)
|
||||
}
|
||||
if p.Lastname != "" {
|
||||
result = fmt.Sprintf("%s, Lastname: '%s'", result, p.Lastname)
|
||||
}
|
||||
if p.Middlename != "" {
|
||||
result = fmt.Sprintf("%s, Middlename: '%s'", result, p.Middlename)
|
||||
}
|
||||
if p.MothersFirstname != "" {
|
||||
result = fmt.Sprintf("%s, MothersFirstname: '%s'", result, p.MothersFirstname)
|
||||
}
|
||||
if p.MothersLastname != "" {
|
||||
result = fmt.Sprintf("%s, MothersLastname: '%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, OccupationToDisplay: '%s'", result, p.OccupationToDisplay)
|
||||
}
|
||||
if p.ProfilePicture != "" {
|
||||
result = fmt.Sprintf("%s, ProfilePicture: '%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, ExtraNames: [", 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, LifeEvents: [", 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, OthersSaid: {", 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
backend/memgraph/model_test.go
Normal file
77
backend/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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
30
backend/memgraph/update_person.go
Normal file
30
backend/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
backend/memgraph/verify_relationship.go
Normal file
39
backend/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)
|
||||
}
|
22
deployment/auth-service-argo.yaml
Normal file
22
deployment/auth-service-argo.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: gh-auth-service
|
||||
spec:
|
||||
project: generations-heritage-vv
|
||||
source:
|
||||
repoURL: 'https://github.com/vcscsvcscs/GenerationsHeritage'
|
||||
path: deployment/auth-service
|
||||
targetRevision: main
|
||||
kustomize:
|
||||
namespace: generations-heritage
|
||||
destination:
|
||||
server: 'https://kubernetes.default.svc'
|
||||
namespace: generations-heritage
|
||||
syncPolicy:
|
||||
automated:
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
- ServerSideApply=true
|
||||
|
29
deployment/auth-service/certificate.yaml
Normal file
29
deployment/auth-service/certificate.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: gh-auth-service-certificate
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PreSync
|
||||
spec:
|
||||
isCA: false
|
||||
duration: 2160h # 90d
|
||||
renewBefore: 360h # 15d
|
||||
dnsNames:
|
||||
- gh-auth-service.generations-heritage.svc.cluster.local
|
||||
- gh-auth-service
|
||||
- localhost
|
||||
ipAddresses:
|
||||
- 127.0.0.1
|
||||
subject:
|
||||
organizations:
|
||||
- GenerationsHeritage
|
||||
secretName: gh-auth-service-tls
|
||||
privateKey:
|
||||
algorithm: RSA
|
||||
encoding: PKCS1
|
||||
size: 2048
|
||||
issuerRef:
|
||||
name: default-cluster-ca-issuer
|
||||
kind: ClusterIssuer
|
||||
group: cert-manager.io
|
||||
|
46
deployment/auth-service/deployment.yaml
Normal file
46
deployment/auth-service/deployment.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: gh-auth-service
|
||||
app.kubernetes.io/name: gh-auth-service
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "1"
|
||||
argocd.argoproj.io/hook: Synce
|
||||
name: gh-auth-service
|
||||
namespace: generations-heritage
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: gh-auth-service
|
||||
app.kubernetes.io/name: gh-auth-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: gh-auth-service
|
||||
app.kubernetes.io/name: gh-auth-service
|
||||
spec:
|
||||
containers:
|
||||
- image: vcscsvcscs/gheritage-auth-service:latest
|
||||
imagePullPolicy: Always
|
||||
name: gh-auth-service
|
||||
ports:
|
||||
- containerPort: 443
|
||||
name: gin
|
||||
securityContext:
|
||||
runAsUser: 0
|
||||
resources:
|
||||
limits:
|
||||
cpu: 250m
|
||||
memory: 200Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 50Mi
|
||||
volumeMounts:
|
||||
- name: gh-auth-service-certs
|
||||
mountPath: /etc/gh-auth-service/ssl
|
||||
volumes:
|
||||
- name: gh-auth-service-certs
|
||||
secret:
|
||||
secretName: gh-auth-service-tls
|
26
deployment/auth-service/horizontalPodAutoScaler.yaml
Normal file
26
deployment/auth-service/horizontalPodAutoScaler.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: gh-auth-service
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PostSync
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: gh-auth-service
|
||||
minReplicas: 1
|
||||
maxReplicas: 5
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 50
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 50
|
9
deployment/auth-service/kustomization.yaml
Normal file
9
deployment/auth-service/kustomization.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: generations-heritage
|
||||
|
||||
resources:
|
||||
- ./certificate.yaml
|
||||
- ./deployment.yaml
|
||||
- ./service.yaml
|
||||
- ./horizontalPodAutoScaler.yaml
|
17
deployment/auth-service/service.yaml
Normal file
17
deployment/auth-service/service.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: gh-auth-service
|
||||
app.kubernetes.io/name: gh-auth-service
|
||||
name: gh-auth-service
|
||||
spec:
|
||||
ports:
|
||||
- name: gin
|
||||
port: 443
|
||||
protocol: TCP
|
||||
targetPort: 443
|
||||
selector:
|
||||
app.kubernetes.io/instance: gh-auth-service
|
||||
app.kubernetes.io/name: gh-auth-service
|
||||
type: ClusterIP
|
22
deployment/backend-argo.yaml
Normal file
22
deployment/backend-argo.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: gh-backend
|
||||
spec:
|
||||
project: generations-heritage-vv
|
||||
source:
|
||||
repoURL: 'https://github.com/vcscsvcscs/GenerationsHeritage'
|
||||
path: deployment/backend
|
||||
targetRevision: main
|
||||
kustomize:
|
||||
namespace: generations-heritage
|
||||
destination:
|
||||
server: 'https://kubernetes.default.svc'
|
||||
namespace: generations-heritage
|
||||
syncPolicy:
|
||||
automated:
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
- ServerSideApply=true
|
||||
|
29
deployment/backend/certificate.yaml
Normal file
29
deployment/backend/certificate.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: gh-backend-certificate
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PreSync
|
||||
spec:
|
||||
isCA: false
|
||||
duration: 2160h # 90d
|
||||
renewBefore: 360h # 15d
|
||||
dnsNames:
|
||||
- gh-backend.generations-heritage.svc.cluster.local
|
||||
- gh-backend
|
||||
- localhost
|
||||
ipAddresses:
|
||||
- 127.0.0.1
|
||||
subject:
|
||||
organizations:
|
||||
- GenerationsHeritage
|
||||
secretName: gh-backend-tls
|
||||
privateKey:
|
||||
algorithm: RSA
|
||||
encoding: PKCS1
|
||||
size: 2048
|
||||
issuerRef:
|
||||
name: default-cluster-ca-issuer
|
||||
kind: ClusterIssuer
|
||||
group: cert-manager.io
|
||||
|
45
deployment/backend/deployment.yaml
Normal file
45
deployment/backend/deployment.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: gh-backend
|
||||
app.kubernetes.io/name: gh-backend
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "1"
|
||||
argocd.argoproj.io/hook: Synce
|
||||
name: gh-backend
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: gh-backend
|
||||
app.kubernetes.io/name: gh-backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: gh-backend
|
||||
app.kubernetes.io/name: gh-backend
|
||||
spec:
|
||||
containers:
|
||||
- image: vcscsvcscs/gheritage-backend-service:latest
|
||||
imagePullPolicy: Always
|
||||
name: gh-backend
|
||||
ports:
|
||||
- containerPort: 443
|
||||
name: gin
|
||||
securityContext:
|
||||
runAsUser: 0
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 500Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 100Mi
|
||||
volumeMounts:
|
||||
- name: gh-backend-certs
|
||||
mountPath: /etc/gh-backend/ssl
|
||||
volumes:
|
||||
- name: gh-backend-certs
|
||||
secret:
|
||||
secretName: gh-backend-tls
|
26
deployment/backend/horizontalPodAutoScaler.yaml
Normal file
26
deployment/backend/horizontalPodAutoScaler.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: gh-backend
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PostSync
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: gh-backend
|
||||
minReplicas: 1
|
||||
maxReplicas: 5
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 50
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 50
|
19
deployment/backend/ingressRoute.yaml
Normal file
19
deployment/backend/ingressRoute.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: gh-backend
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PostSync
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- kind: Rule
|
||||
match: Host(`heritagebackend.varghacsongor.hu`)
|
||||
services:
|
||||
- name: gh-backend
|
||||
port: 443
|
||||
passHostHeader: true
|
||||
scheme: https
|
||||
tls: {}
|
10
deployment/backend/kustomization.yaml
Normal file
10
deployment/backend/kustomization.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: generations-heritage
|
||||
|
||||
resources:
|
||||
- ./certificate.yaml
|
||||
- ./deployment.yaml
|
||||
- ./service.yaml
|
||||
- ./ingressRoute.yaml
|
||||
- ./horizontalPodAutoScaler.yaml
|
20
deployment/backend/service.yaml
Normal file
20
deployment/backend/service.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: gh-backend
|
||||
app.kubernetes.io/name: gh-backend
|
||||
name: gh-backend
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "2"
|
||||
argocd.argoproj.io/hook: Synce
|
||||
spec:
|
||||
ports:
|
||||
- name: gin
|
||||
port: 443
|
||||
protocol: TCP
|
||||
targetPort: 443
|
||||
selector:
|
||||
app.kubernetes.io/instance: gh-backend
|
||||
app.kubernetes.io/name: gh-backend
|
||||
type: ClusterIP
|
45
deployment/cert-issuer.yaml
Normal file
45
deployment/cert-issuer.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: trust-manager-selfsigned-issuer
|
||||
spec:
|
||||
selfSigned: {}
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: cluster-root-certificate
|
||||
namespace: cert-manager
|
||||
spec:
|
||||
isCA: true
|
||||
commonName: cluster-root-certificate-ca
|
||||
secretName: cluster-root-certificate-ca-secret
|
||||
privateKey:
|
||||
algorithm: ECDSA
|
||||
size: 256
|
||||
issuerRef:
|
||||
name: trust-manager-selfsigned-issuer
|
||||
kind: ClusterIssuer
|
||||
group: cert-manager.io
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: default-cluster-ca-issuer
|
||||
spec:
|
||||
ca:
|
||||
secretName: cluster-root-certificate-ca-secret
|
||||
---
|
||||
apiVersion: trust.cert-manager.io/v1alpha1
|
||||
kind: Bundle
|
||||
metadata:
|
||||
name: in-cluster-trust-bundle
|
||||
spec:
|
||||
sources:
|
||||
- useDefaultCAs: true
|
||||
- secret:
|
||||
name: "cluster-root-certificate-ca-secret"
|
||||
key: "tls.crt"
|
||||
target:
|
||||
configMap:
|
||||
key: "trust-bundle.pem"
|
22
deployment/memgraph-argo.yaml
Normal file
22
deployment/memgraph-argo.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: memgraph
|
||||
spec:
|
||||
project: generations-heritage-vv
|
||||
source:
|
||||
repoURL: 'https://github.com/vcscsvcscs/GenerationsHeritage'
|
||||
path: deployment/memgraph
|
||||
targetRevision: main
|
||||
kustomize:
|
||||
namespace: generations-heritage
|
||||
destination:
|
||||
server: 'https://kubernetes.default.svc'
|
||||
namespace: generations-heritage
|
||||
syncPolicy:
|
||||
automated:
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
- ServerSideApply=true
|
||||
|
30
deployment/memgraph/certificates.yaml
Normal file
30
deployment/memgraph/certificates.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: memraph-certificate
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PreSync
|
||||
spec:
|
||||
isCA: false
|
||||
duration: 2160h # 90d
|
||||
renewBefore: 360h # 15d
|
||||
dnsNames:
|
||||
- memgraph.generations-heritage.svc.cluster.local
|
||||
- memgraph
|
||||
- localhost
|
||||
ipAddresses:
|
||||
- 127.0.0.1
|
||||
subject:
|
||||
organizations:
|
||||
- Memgraph
|
||||
- GenerationsHeritage
|
||||
secretName: memgraph-tls
|
||||
privateKey:
|
||||
algorithm: RSA
|
||||
encoding: PKCS1
|
||||
size: 2048
|
||||
issuerRef:
|
||||
name: default-cluster-ca-issuer
|
||||
kind: ClusterIssuer
|
||||
group: cert-manager.io
|
||||
|
33
deployment/memgraph/kustomization.yaml
Normal file
33
deployment/memgraph/kustomization.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: generations-heritage
|
||||
|
||||
resources:
|
||||
- ./certificates.yaml
|
||||
|
||||
helmCharts:
|
||||
- name: memgraph
|
||||
repo: https://memgraph.github.io/helm-charts
|
||||
releaseName: memgraph
|
||||
namespace: generations-heritage
|
||||
version: 0.1.1
|
||||
valuesFile: ./values.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: StatefulSet
|
||||
name: memgraph
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/-
|
||||
value:
|
||||
name: memgraph-certs
|
||||
mountPath: /etc/memgraph/ssl
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/-
|
||||
value:
|
||||
name: memgraph-certs
|
||||
secret:
|
||||
secretName: memgraph-tls
|
||||
|
||||
|
52
deployment/memgraph/values.yaml
Normal file
52
deployment/memgraph/values.yaml
Normal file
@@ -0,0 +1,52 @@
|
||||
image:
|
||||
repository: memgraph/memgraph
|
||||
# Overrides the image tag whose default is v{{ .Chart.AppVersion }}
|
||||
tag: ""
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 7687
|
||||
targetPort: 7687
|
||||
protocol: TCP
|
||||
annotations: {}
|
||||
|
||||
persistentVolumeClaim:
|
||||
storagePVC: true
|
||||
storagePVCSize: 2Gi
|
||||
logPVC: true
|
||||
logPVCSize: 256Mi
|
||||
|
||||
memgraphConfig:
|
||||
- "--also-log-to-stderr=true"
|
||||
- "--bolt-cert-file=/etc/memgraph/ssl/tls.crt"
|
||||
- "--bolt-key-file=/etc/memgraph/ssl/tls.key"
|
||||
|
||||
# Annotations to add to the statefulSet
|
||||
statefulSetAnnotations: {}
|
||||
# Annotations to add to the Pod
|
||||
podAnnotations: {}
|
||||
|
||||
resources:
|
||||
{}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
14
deployment/project-argo.yaml
Normal file
14
deployment/project-argo.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: AppProject
|
||||
metadata:
|
||||
name: generations-heritage-vv
|
||||
spec:
|
||||
description: Generations heritages is a project that aims to preserve the heritage of families based on bloodlines.
|
||||
sourceRepos:
|
||||
- '*' # Allow all repositories
|
||||
destinations:
|
||||
- namespace: 'generations-heritage'
|
||||
server: '*'
|
||||
clusterResourceWhitelist:
|
||||
- group: '*'
|
||||
kind: '*' # Allow all kinds
|
22
deployment/zitadel-argo.yaml
Normal file
22
deployment/zitadel-argo.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: zitadel
|
||||
spec:
|
||||
project: generations-heritage-vv
|
||||
source:
|
||||
repoURL: 'https://github.com/vcscsvcscs/GenerationsHeritage'
|
||||
path: deployment/zitadel
|
||||
targetRevision: main
|
||||
kustomize:
|
||||
namespace: generations-heritage
|
||||
destination:
|
||||
server: 'https://kubernetes.default.svc'
|
||||
namespace: generations-heritage
|
||||
syncPolicy:
|
||||
automated:
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
- ServerSideApply=true
|
||||
|
113
deployment/zitadel/cert-job.yaml
Normal file
113
deployment/zitadel/cert-job.yaml
Normal file
@@ -0,0 +1,113 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: zitadel-cert-creator
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: Sync
|
||||
argocd.argoproj.io/sync-wave: "2"
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: secret-creator
|
||||
rules:
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ "secrets" ]
|
||||
verbs: [ "create" ]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: zitadel-cert-creator
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: Sync
|
||||
argocd.argoproj.io/sync-wave: "2"
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: zitadel-cert-creator
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: secret-creator
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: create-zitadel-cert
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: Sync
|
||||
argocd.argoproj.io/sync-wave: "2"
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
serviceAccountName: zitadel-cert-creator
|
||||
containers:
|
||||
- command:
|
||||
- /bin/bash
|
||||
- -ecx
|
||||
- |
|
||||
cockroach cert create-client \
|
||||
--certs-dir /cockroach/cockroach-certs \
|
||||
--ca-key /cockroach/cockroach-certs/ca.key \
|
||||
--lifetime 8760h \
|
||||
zitadel
|
||||
export SECRET=$(cat <<EOF
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Secret",
|
||||
"data": {
|
||||
"ca.crt": "$(base64 /cockroach/cockroach-certs/ca.crt --wrap 0)",
|
||||
"tls.crt": "$(base64 /cockroach/cockroach-certs/client.zitadel.crt --wrap 0)",
|
||||
"tls.key": "$(base64 /cockroach/cockroach-certs/client.zitadel.key --wrap 0)"
|
||||
},
|
||||
"metadata": {
|
||||
"name": "db-cockroachdb-zitadel-secret"
|
||||
},
|
||||
"type": "kubernetes.io/tls"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
export APISERVER=https://kubernetes.default.svc SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
|
||||
export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace) TOKEN=$(cat ${SERVICEACCOUNT}/token) CACERT=${SERVICEACCOUNT}/ca.crt
|
||||
curl \
|
||||
--cacert ${CACERT} \
|
||||
--header "Authorization: Bearer ${TOKEN}" \
|
||||
--header "Content-Type: application/json" \
|
||||
-X POST ${APISERVER}/api/v1/namespaces/${NAMESPACE}/secrets \
|
||||
--data "$(echo -n $SECRET | tr -d '\n')"
|
||||
image: cockroachdb/cockroach:v23.1.8
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: create-zitadel-cert
|
||||
volumeMounts:
|
||||
- mountPath: /cockroach/cockroach-certs/
|
||||
name: certs
|
||||
initContainers:
|
||||
- command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- cp -f /certs/* /cockroach-certs/; chmod 0400 /cockroach-certs/*.key
|
||||
image: busybox
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: copy-certs
|
||||
volumeMounts:
|
||||
- mountPath: /cockroach-certs/
|
||||
name: certs
|
||||
- mountPath: /certs/
|
||||
name: certs-secret
|
||||
volumes:
|
||||
- emptyDir: {}
|
||||
name: certs
|
||||
- name: certs-secret
|
||||
projected:
|
||||
defaultMode: 420
|
||||
sources:
|
||||
- secret:
|
||||
items:
|
||||
- key: ca.crt
|
||||
mode: 256
|
||||
path: ca.crt
|
||||
- key: ca.key
|
||||
mode: 256
|
||||
path: ca.key
|
||||
name: cockroachdb-ca-secret
|
13
deployment/zitadel/cockroach-values.yaml
Normal file
13
deployment/zitadel/cockroach-values.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
tls:
|
||||
enabled: true
|
||||
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: Sync
|
||||
|
||||
storage:
|
||||
persistentVolume:
|
||||
size: 5Gi
|
||||
|
||||
init:
|
||||
jobAnnotations:
|
||||
argocd.argoproj.io/hook: Sync
|
27
deployment/zitadel/ingressRoute.yaml
Normal file
27
deployment/zitadel/ingressRoute.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: zitadel-server
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PostSync
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- kind: Rule
|
||||
match: Host(`zitadel.varghacsongor.hu`)
|
||||
priority: 10
|
||||
services:
|
||||
- name: zitadel
|
||||
port: 8080
|
||||
passHostHeader: true
|
||||
- kind: Rule
|
||||
match: Host(`zitadel.varghacsongor.hu`) && Headers(`Content-Type`, `application/grpc`)
|
||||
priority: 11
|
||||
services:
|
||||
- name: zitadel
|
||||
port: 8080
|
||||
scheme: h2c
|
||||
passHostHeader: true
|
||||
tls: {}
|
58
deployment/zitadel/kustomization.yaml
Normal file
58
deployment/zitadel/kustomization.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: generations-heritage
|
||||
|
||||
resources:
|
||||
- ./cert-job.yaml
|
||||
- ./secrets.yaml
|
||||
- ./ingressRoute.yaml
|
||||
|
||||
helmCharts:
|
||||
- name: cockroachdb
|
||||
repo: https://charts.cockroachdb.com/
|
||||
releaseName: cockroachdb
|
||||
namespace: generations-heritage
|
||||
version: 12.0.2
|
||||
valuesFile: cockroach-values.yaml
|
||||
- name: zitadel
|
||||
repo: https://charts.zitadel.com
|
||||
releaseName: zitadel
|
||||
namespace: generations-heritage
|
||||
version: 7.10.0
|
||||
valuesFile: ./values.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: CronJob
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /apiVersion
|
||||
value: batch/v1
|
||||
- target:
|
||||
name: zitadel-setup
|
||||
kind: Job
|
||||
patch: |
|
||||
- op: add
|
||||
path: /metadata/annotations/argocd.argoproj.io~1sync-wave
|
||||
value: 4
|
||||
- target:
|
||||
name: zitadel-setup
|
||||
kind: Job
|
||||
patch: |
|
||||
- op: add
|
||||
path: /metadata/annotations/argocd.argoproj.io~1hook
|
||||
value: Sync
|
||||
- target:
|
||||
name: zitadel-init
|
||||
kind: Job
|
||||
patch: |
|
||||
- op: add
|
||||
path: /metadata/annotations/argocd.argoproj.io~1sync-wave
|
||||
value: 3
|
||||
- target:
|
||||
name: zitadel-init
|
||||
kind: Job
|
||||
patch: |
|
||||
- op: add
|
||||
path: /metadata/annotations/argocd.argoproj.io~1hook
|
||||
value: Sync
|
23
deployment/zitadel/secrets.yaml
Normal file
23
deployment/zitadel/secrets.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: zitadel-masterkey
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PreSync
|
||||
labels:
|
||||
secret-generator.cs.sap.com/enabled: "true"
|
||||
stringData:
|
||||
masterkey: "%generate"
|
||||
admin-password: "%generate"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: cockroach-auth
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PreSync
|
||||
labels:
|
||||
secret-generator.cs.sap.com/enabled: "true"
|
||||
stringData:
|
||||
cockroach-password: "%generate"
|
||||
user-password: "%generate"
|
47
deployment/zitadel/values.yaml
Normal file
47
deployment/zitadel/values.yaml
Normal file
@@ -0,0 +1,47 @@
|
||||
zitadel:
|
||||
masterkeySecretName: zitadel-masterkey
|
||||
configmapConfig:
|
||||
ExternalSecure: true
|
||||
ExternalDomain: zitadel.varghacsongor.hu
|
||||
ExternalPort: 443
|
||||
TLS:
|
||||
Enabled: false
|
||||
Database:
|
||||
Cockroach:
|
||||
Host: cockroachdb-public
|
||||
User:
|
||||
SSL:
|
||||
Mode: verify-full
|
||||
Admin:
|
||||
SSL:
|
||||
Mode: verify-full
|
||||
|
||||
dbSslCaCrtSecret: cockroachdb-ca-secret
|
||||
dbSslAdminCrtSecret: cockroachdb-client-secret
|
||||
dbSslUserCrtSecret: db-cockroachdb-zitadel-secret
|
||||
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "5"
|
||||
argocd.argoproj.io/hook: Sync
|
||||
|
||||
env:
|
||||
- name: ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME
|
||||
value: "admin"
|
||||
|
||||
- name: ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: zitadel-masterkey
|
||||
key: admin-password
|
||||
|
||||
- name: ZITADEL_DATABASE_COCKROACH_USER_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: cockroach-auth
|
||||
key: user-password
|
||||
|
||||
- name: ZITADEL_DATABASE_COCKROACH_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: cockroach-auth
|
||||
key: cockroach-password
|
39
frontend/.eslintignore
Normal file
39
frontend/.eslintignore
Normal file
@@ -0,0 +1,39 @@
|
||||
/.nyc_output
|
||||
/coverage
|
||||
/lib
|
||||
/node_modules
|
||||
/*.config.js
|
||||
!/.vscode
|
||||
!/.github
|
||||
!/.devcontainer
|
||||
/prettier-playground
|
||||
/tests/fixtures/rules/indent/invalid/ts
|
||||
/tests/fixtures/rules/indent/invalid/ts-v5
|
||||
/tests/fixtures/rules/indent/invalid/snippets01-input.svelte
|
||||
/tests/fixtures/rules/indent/valid/
|
||||
/tests/fixtures/rules/no-unused-class-name/valid/invalid-style01-input.svelte
|
||||
/tests/fixtures/rules/no-unused-class-name/valid/unknown-lang01-input.svelte
|
||||
/tests/fixtures/rules/valid-compile/invalid/ts
|
||||
/tests/fixtures/rules/valid-compile/valid/babel
|
||||
/tests/fixtures/rules/valid-compile/valid/ts
|
||||
/tests/fixtures/rules/prefer-style-directive
|
||||
/tests/fixtures/rules/@typescript-eslint
|
||||
/tests/fixtures/rules/valid-compile/valid/svelte3-options-custom-element-input.svelte
|
||||
/tests/fixtures/rules/mustache-spacing/valid/always/snippet-render01-input.svelte
|
||||
/tests/fixtures/rules/mustache-spacing/invalid/snippet-render01-input.svelte
|
||||
/.svelte-kit
|
||||
/svelte.config-dist.js
|
||||
/build
|
||||
/docs-svelte-kit/shim/eslint.mjs
|
||||
/docs-svelte-kit/shim/assert.mjs
|
||||
!/.*.js
|
||||
/docs-svelte-kit/src/routes/*.md
|
||||
/docs-svelte-kit/src/routes/**/*.md
|
||||
/docs-svelte-kit/src/app.html
|
||||
|
||||
# JSONSchema bug?
|
||||
/.devcontainer/devcontainer.json
|
||||
|
||||
# Parser bug?
|
||||
/tests/fixtures/rules/indent/invalid/const-tag01-input.svelte
|
||||
/tests/fixtures/rules/indent/invalid/const-tag01-output.svelte
|
19
frontend/.eslintrc.cjs
Normal file
19
frontend/.eslintrc.cjs
Normal file
@@ -0,0 +1,19 @@
|
||||
module.exports = {
|
||||
extends: ['plugin:svelte/base', 'plugin:svelte/recommended', 'plugin:svelte/prettier'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
parser: 'svelte-eslint-parser'
|
||||
}
|
||||
],
|
||||
env: {
|
||||
es6: true
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
jsx: true
|
||||
},
|
||||
sourceType: 'module'
|
||||
}
|
||||
};
|
8
frontend/.prettierignore
Normal file
8
frontend/.prettierignore
Normal file
@@ -0,0 +1,8 @@
|
||||
.svelte-kit
|
||||
.type-coverage
|
||||
build
|
||||
/lib
|
||||
.npmrc
|
||||
.eslintignore
|
||||
/tests/fixtures/rules/indent/valid/
|
||||
.changeset
|
31
frontend/.prettierrc.cjs
Normal file
31
frontend/.prettierrc.cjs
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
useTabs: true,
|
||||
singleQuote: true,
|
||||
trailingComma: 'none',
|
||||
printWidth: 100,
|
||||
plugins: ['prettier-plugin-svelte'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['.*rc'],
|
||||
excludeFiles: ['.browserslistrc', '.npmrc', '.nvmrc'],
|
||||
options: {
|
||||
parser: 'json'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
options: {
|
||||
bracketSameLine: false
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['*.md', 'package.json', '**/package.json'],
|
||||
options: {
|
||||
useTabs: false,
|
||||
tabWidth: 2
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
2101
frontend/package-lock.json
generated
2101
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,31 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/adapter-static": "^3.0.1",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"svelte": "^4.2.7",
|
||||
"vite": "^5.0.3"
|
||||
},
|
||||
"type": "module"
|
||||
"name": "frontend",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"format": "npx prettier --write --plugin prettier-plugin-svelte .",
|
||||
"lint": "npx eslint --ext .svelte --ext .js ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.0",
|
||||
"@babel/eslint-parser": "^7.23.10",
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/adapter-static": "^3.0.1",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-svelte": "^2.35.1",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-svelte": "^3.2.2",
|
||||
"svelte": "^4.2.12",
|
||||
"vite": "^5.0.3"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"svelte-eslint-parser": "^0.33.1"
|
||||
}
|
||||
}
|
||||
|
@@ -1,2 +1,4 @@
|
||||
<h1>Welcome to SvelteKit</h1>
|
||||
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
|
||||
<p>
|
||||
Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation
|
||||
</p>
|
||||
|
11
kustomization.yaml
Normal file
11
kustomization.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: argocd
|
||||
|
||||
resources:
|
||||
- ./deployment/cert-issuer.yaml
|
||||
- ./deployment/project-argo.yaml
|
||||
- ./deployment/auth-service-argo.yaml
|
||||
- ./deployment/memgraph-argo.yaml
|
||||
- ./deployment/backend-argo.yaml
|
||||
- ./deployment/zitadel-argo.yaml
|
@@ -1,6 +1,6 @@
|
||||
module github.com/vcscsvcscs/GenerationsHeritage/utilities
|
||||
|
||||
go 1.22.1
|
||||
go 1.22.2
|
||||
|
||||
require github.com/gin-gonic/gin v1.9.1
|
||||
|
||||
|
29
utilities/logger_setup.go
Normal file
29
utilities/logger_setup.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package utilities
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func SetupLogger(logToFileAndStd bool, logToFile bool) {
|
||||
if logToFileAndStd || logToFile {
|
||||
gin.DisableConsoleColor() // Disable Console Color, you don't need console color when writing the logs to file.
|
||||
path := fmt.Sprintf("private/logs/%02dy_%02dm_%02dd_%02dh_%02dm_%02ds.log", time.Now().Year(), time.Now().Month(), time.Now().Day(), time.Now().Hour(), time.Now().Minute(), time.Now().Second())
|
||||
logerror1 := os.MkdirAll("private/logs/", 0755)
|
||||
f, logerror2 := os.Create(path)
|
||||
if logerror1 != nil || logerror2 != nil {
|
||||
log.Println("Cant log to file")
|
||||
} else if logToFileAndStd {
|
||||
gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
|
||||
} else {
|
||||
gin.DefaultWriter = io.MultiWriter(f)
|
||||
}
|
||||
}
|
||||
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||||
log.SetOutput(gin.DefaultErrorWriter)
|
||||
}
|
40
utilities/server_setup.go
Normal file
40
utilities/server_setup.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package utilities
|
||||
|
||||
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