diff --git a/.env b/.env index 418a240f..8773c627 100644 --- a/.env +++ b/.env @@ -1,3 +1,15 @@ -POSTGRES_USER=postgres -POSTGRES_PASSWORD=postgres -POSTGRES_DB=postgres \ No newline at end of file +APP_DB_ADDR="postgres" +APP_DB_PORT=5432 +APP_DB_USERNAME="postgres" +APP_DB_PASSWORD="postgres" +APP_DB_DATABASE="postgres" +APP_DB_SSL_MODE=0 + +APP_PORT=3000 +APP_SHOW_FRONTEND=1 +APP_SHOW_SWAGGER=1 + + + + + diff --git a/.github/workflows/execute-tests.yaml b/.github/workflows/execute-tests.yaml new file mode 100644 index 00000000..c0fc1971 --- /dev/null +++ b/.github/workflows/execute-tests.yaml @@ -0,0 +1,38 @@ +name: "CI: Test Software" + +on: + push: + +jobs: + test-backend: + runs-on: ubuntu-latest + # continue-on-error: true + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: run backend tests + if: ${{ always() }} + run: make test-be + env: + APP_DATABASE_HOST: postgres + APP_DATABASE_PORT: 5432 + APP_DATABASE_USERNAME: postgres + APP_DATABASE_PASSWORD: postgres + APP_DATABASE_DATABASE: postgres + APP_DATABASE_SSLMODE: False + + # test-frontend: + # runs-on: ubuntu-latest + # continue-on-error: true + + # steps: + # - uses: actions/checkout@v4 + # with: + # fetch-depth: 0 + + # - name: run frontend tests + # if: ${{ always() }} + # run: make test-fe diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index f264e401..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: goreleaser - -on: - push: - tags: - - "*" - -permissions: - contents: write - -jobs: - backendTests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - run: git fetch --force --tags - - uses: actions/setup-go@v5 - with: - go-version: stable - - goreleaser: - needs: backendTests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - run: git fetch --force --tags - - uses: actions/setup-go@v5 - with: - go-version: stable - - uses: goreleaser/goreleaser-action@v5 - with: - distribution: goreleaser - version: latest - args: release --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index c9b0b4a8..a2c41f1e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,9 @@ services/frontend/.svelte-kit services/frontend/node_modules services/backend/src/assets/frontend -.DS_Store \ No newline at end of file +.DS_Store +*.tgz + +.input +.secrets +node_modules diff --git a/Makefile b/Makefile index de8db193..4ecd34eb 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ @bash ./devops/scripts/utils/install-dependencies.sh dev: .install-deps ## start debugging in docker compose microservices (auto reload) - @docker compose -f compose-dev.yaml up backend frontend reverse-proxy + @docker compose -f compose-dev.yaml up --abort-on-container-exit backend frontend reverse-proxy build-full: .install-deps ## build current plattform @bash ./devops/scripts/build-service/binary.sh @@ -12,10 +12,10 @@ local-release: .install-deps ## build all app versions locally (via goreleaser) @bash ./devops/scripts/utils/local-release.sh test-be: ## run golang tests - @docker compose -f compose-dev.yaml up postgres backend-tests + @docker compose -f compose-dev.yaml up --abort-on-container-exit postgres backend-tests test-fe: ## run sveltekit tests - @docker compose -f compose-dev.yaml up fontend-tests + @docker compose -f compose-dev.yaml up --abort-on-container-exit frontend-tests build-dockerfile-binary: ## build one dockerimage that contains everything @bash ./devops/scripts/build-container/binary.sh diff --git a/compose-dev.yaml b/compose-dev.yaml index ec7e380f..66817eb5 100644 --- a/compose-dev.yaml +++ b/compose-dev.yaml @@ -68,6 +68,21 @@ services: - intranet command: ["sh", "-c", "cd /app && npm install && npm run test"] + frontend-tests-ci: + image: node:latest + container_name: web-ui-test + restart: always + volumes: + - ./services/frontend/package.json:/app/package.json + - ./services/frontend/svelte.config.js:/app/svelte.config.js + - ./services/frontend/tsconfig.json:/app/tsconfig.json + - ./services/frontend/vite.config.ts:/app/vite.config.ts + - ./services/frontend/static:/app/static + - ./services/frontend/src:/app/src + networks: + - intranet + command: ["sh", "-c", "cd /app && npm install && npm run test"] + # ----------------------------------------------------------------------------------------------------- # # BACKEND @@ -89,7 +104,8 @@ services: condition: service_started # gotify: # condition: service_started - restart: always + env_file: + - "./.env" labels: - "traefik.enable=true" - "traefik.http.routers.backend.rule=Host(`web.localhost`)&&(PathPrefix(`/api`)||PathPrefix(`/swagger`))" @@ -115,6 +131,16 @@ services: - TERM=xterm-256color` command: ["sh", "-c", "cd /app && bash scripts/test-local-docker.sh"] + backend-tests-ci: + image: golang:latest + container_name: web-api-test + volumes: + - ./services/backend:/app + tty: true + environment: + - TERM=xterm-256color` + command: ["sh", "-c", "cd /app && bash scripts/test-local-docker.sh"] + # ----------------------------------------------------------------------------------------------------- # # DATABASE @@ -125,9 +151,9 @@ services: image: postgis/postgis restart: always environment: - POSTGRES_USER: ${POSTGRES_USER} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${APP_DB_USERNAME} + POSTGRES_PASSWORD: ${APP_DB_PASSWORD} + POSTGRES_DB: ${APP_DB_DATABASE} PGDATA: /var/lib/postgresql/data/pgdata ports: - "5432:5432" diff --git a/devops/deployments/.ci-pipeline/.gitignore b/devops/deployments/.ci-pipeline/.gitignore new file mode 100644 index 00000000..4d3eda31 --- /dev/null +++ b/devops/deployments/.ci-pipeline/.gitignore @@ -0,0 +1,2 @@ +config +k8s.civo.config \ No newline at end of file diff --git a/devops/deployments/application-services/backend/.helmignore b/devops/deployments/application-services/backend/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/devops/deployments/application-services/backend/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/devops/deployments/application-services/backend/Chart.yaml b/devops/deployments/application-services/backend/Chart.yaml new file mode 100644 index 00000000..c5d4bdee --- /dev/null +++ b/devops/deployments/application-services/backend/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: backend +description: A Helm chart for Kubernetes + +type: application +version: 0.1.0 +appVersion: "1.16.0" diff --git a/devops/deployments/application-services/backend/charts/.gitkeep b/devops/deployments/application-services/backend/charts/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/devops/deployments/application-services/backend/templates/.gitkeep b/devops/deployments/application-services/backend/templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/devops/deployments/application-services/backend/values.yaml b/devops/deployments/application-services/backend/values.yaml new file mode 100644 index 00000000..e69de29b diff --git a/devops/deployments/application-services/frontend/.helmignore b/devops/deployments/application-services/frontend/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/devops/deployments/application-services/frontend/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/devops/deployments/application-services/frontend/Chart.yaml b/devops/deployments/application-services/frontend/Chart.yaml new file mode 100644 index 00000000..b6d9df81 --- /dev/null +++ b/devops/deployments/application-services/frontend/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: frontend +description: A Helm chart for Kubernetes + +type: application +version: 0.1.0 +appVersion: "1.16.0" diff --git a/devops/deployments/application-services/frontend/charts/.gitkeep b/devops/deployments/application-services/frontend/charts/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/devops/deployments/application-services/frontend/templates/.gitkeep b/devops/deployments/application-services/frontend/templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/devops/deployments/application-services/frontend/values.yaml b/devops/deployments/application-services/frontend/values.yaml new file mode 100644 index 00000000..e69de29b diff --git a/devops/deployments/application-services/helmfile.yaml b/devops/deployments/application-services/helmfile.yaml new file mode 100644 index 00000000..1d0b754f --- /dev/null +++ b/devops/deployments/application-services/helmfile.yaml @@ -0,0 +1,25 @@ +environments: + develop: {} + prod: {} + +--- + +releases: + - name: frontend + chart: ./frontend + namespace: application-{{ .Environment.Name }} + createNamespace: true + installed: true + values: + - "./values/frontend-{{ .Environment.Name }}.yaml" + + - name: backend + chart: ./backend + namespace: application-{{ .Environment.Name }} + createNamespace: true + installed: true + values: + - "./values/backend-{{ .Environment.Name }}.yaml" + # set: + # - name: database.password + # value: {{ requiredEnv "SOMETHING" }} \ No newline at end of file diff --git a/devops/deployments/application-services/standalone/.helmignore b/devops/deployments/application-services/standalone/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/devops/deployments/application-services/standalone/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/devops/deployments/application-services/standalone/Chart.yaml b/devops/deployments/application-services/standalone/Chart.yaml new file mode 100644 index 00000000..e7aa0fbc --- /dev/null +++ b/devops/deployments/application-services/standalone/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: standalone +description: A Helm chart for Kubernetes + +type: application +version: 0.1.0 +appVersion: "1.16.0" diff --git a/devops/deployments/application-services/standalone/charts/.gitkeep b/devops/deployments/application-services/standalone/charts/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/devops/deployments/application-services/standalone/templates/.gitkeep b/devops/deployments/application-services/standalone/templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/devops/deployments/application-services/standalone/values.yaml b/devops/deployments/application-services/standalone/values.yaml new file mode 100644 index 00000000..e69de29b diff --git a/devops/deployments/application-services/values/backend-develop.yaml b/devops/deployments/application-services/values/backend-develop.yaml new file mode 100644 index 00000000..b48a35f0 --- /dev/null +++ b/devops/deployments/application-services/values/backend-develop.yaml @@ -0,0 +1,3 @@ +application: + environment: + name: "develop" diff --git a/devops/deployments/application-services/values/backend-prod.yaml b/devops/deployments/application-services/values/backend-prod.yaml new file mode 100644 index 00000000..f202c7d2 --- /dev/null +++ b/devops/deployments/application-services/values/backend-prod.yaml @@ -0,0 +1,3 @@ +application: + environment: + name: "production" diff --git a/devops/deployments/application-services/values/frontend-develop.yaml b/devops/deployments/application-services/values/frontend-develop.yaml new file mode 100644 index 00000000..b48a35f0 --- /dev/null +++ b/devops/deployments/application-services/values/frontend-develop.yaml @@ -0,0 +1,3 @@ +application: + environment: + name: "develop" diff --git a/devops/deployments/application-services/values/frontend-prod.yaml b/devops/deployments/application-services/values/frontend-prod.yaml new file mode 100644 index 00000000..f202c7d2 --- /dev/null +++ b/devops/deployments/application-services/values/frontend-prod.yaml @@ -0,0 +1,3 @@ +application: + environment: + name: "production" diff --git a/devops/deployments/base-applications/helmfile.yaml b/devops/deployments/base-applications/helmfile.yaml new file mode 100644 index 00000000..d4d5da27 --- /dev/null +++ b/devops/deployments/base-applications/helmfile.yaml @@ -0,0 +1,54 @@ +repositories: + - name: ingress-nginx + url: https://kubernetes.github.io/ingress-nginx + - name: goauthentik + url: https://charts.goauthentik.io/ + - name: longhorn + url: https://charts.longhorn.io + - name: bitnami + url: https://charts.bitnami.com/bitnami + +releases: + - name: ingress + chart: ingress-nginx/ingress-nginx + namespace: ingress + createNamespace: true + values: + - "./values/ingress-nginx.yaml" + + - name: longhorn + chart: longhorn/longhorn + version: 1.6.0 + namespace: longhorn + createNamespace: true + values: + - "./values/storage-longhorn.yaml" + + - name: postgres + chart: bitnami/postgresql + namespace: postgres + createNamespace: true + needs: + - longhorn/longhorn + set: + - name: global.storageClass + value: longhorn + - name: global.postgresql.auth.postgresPassword + value: adminpw + - name: global.postgresql.auth.username + value: user + - name: global.postgresql.auth.password + value: userpassword + + # - name: authentik + # chart: goauthentik/authentik + # version: 2024.2.2 + # namespace: identityprovider + # createNamespace: true + # needs: + # - ingress + # - longhorn + # - postgres + # values: + # - "./values/authentik-identity-provider.yaml" + \ No newline at end of file diff --git a/devops/deployments/base-applications/makefile b/devops/deployments/base-applications/makefile new file mode 100644 index 00000000..3d0aafa9 --- /dev/null +++ b/devops/deployments/base-applications/makefile @@ -0,0 +1,2 @@ +run: + helmfile sync --kube-context my-cluster --kubeconfig ../.ci-pipeline/k8s.civo.config \ No newline at end of file diff --git a/devops/deployments/base-applications/values/authentik-identity-provider.yaml b/devops/deployments/base-applications/values/authentik-identity-provider.yaml new file mode 100644 index 00000000..f801e6c5 --- /dev/null +++ b/devops/deployments/base-applications/values/authentik-identity-provider.yaml @@ -0,0 +1,37 @@ +authentik: + secret_key: "PleaseGenerateA50CharKey" + # This sends anonymous usage-data, stack traces on errors and + # performance data to authentik.error-reporting.a7k.io, and is fully opt-in + error_reporting: + enabled: true + postgresql: + host: postgres.domain.tld + user: file:///postgres-creds/username + password: file:///postgres-creds/password + +server: + volumes: + - name: postgres-creds + secret: + secretName: authentik-postgres-credentials + volumeMounts: + - name: postgres-creds + mountPath: /postgres-creds + readOnly: true +worker: + volumes: + - name: postgres-creds + secret: + secretName: authentik-postgres-credentials + volumeMounts: + - name: postgres-creds + mountPath: /postgres-creds + readOnly: true + +postgresql: + enabled: true + auth: + password: "ThisIsNotASecurePassword" + +redis: + enabled: true \ No newline at end of file diff --git a/devops/deployments/base-applications/values/ingress-nginx.yaml b/devops/deployments/base-applications/values/ingress-nginx.yaml new file mode 100644 index 00000000..6bb3e1f3 --- /dev/null +++ b/devops/deployments/base-applications/values/ingress-nginx.yaml @@ -0,0 +1,8 @@ +appName: ingress + +container: + imagename: nginx:latest + pod: + webserverPort: 80 + service: + webserverPort: 80 \ No newline at end of file diff --git a/devops/deployments/base-applications/values/storage-longhorn.yaml b/devops/deployments/base-applications/values/storage-longhorn.yaml new file mode 100644 index 00000000..e69de29b diff --git a/services/backend/config.yaml b/services/backend/config.yaml new file mode 100644 index 00000000..604c5a18 --- /dev/null +++ b/services/backend/config.yaml @@ -0,0 +1,17 @@ +database: + host: postgres + port: 5432 + username: postgres + password: postgres + database: postgres + sslmode: 0 + +webserver: + host: 127.0.0.1 + port: 3000 + show_frontend: 1 + show_swagger: 1 + +security: + jwtsecret: loafofbread + secretgreet: "Secret Hello World" \ No newline at end of file diff --git a/services/backend/go.mod b/services/backend/go.mod index 8b516f7d..10d9298a 100644 --- a/services/backend/go.mod +++ b/services/backend/go.mod @@ -6,7 +6,7 @@ require ( github.com/charmbracelet/lipgloss v0.10.0 github.com/google/uuid v1.6.0 github.com/qeesung/image2ascii v1.0.1 - github.com/swaggo/swag v1.16.3 // indirect + github.com/swaggo/swag v1.16.3 ) require ( @@ -15,13 +15,10 @@ require ( github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/fxamacker/cbor/v2 v2.5.0 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/spec v0.20.11 // indirect github.com/go-openapi/swag v0.22.4 // indirect - github.com/go-webauthn/x v0.1.8 // indirect - github.com/google/go-tpm v0.9.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -51,7 +48,6 @@ require ( github.com/valyala/fasthttp v1.51.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect github.com/wayneashleyberry/terminal-dimensions v1.1.0 // indirect - github.com/x448/float16 v0.8.4 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect @@ -69,10 +65,7 @@ require ( golang.org/x/term v0.18.0 // indirect ) -require ( - github.com/go-sqlx/sqlx v1.3.7 - github.com/go-webauthn/webauthn v0.10.1 -) +require github.com/go-sqlx/sqlx v1.3.7 require ( github.com/gofiber/fiber/v2 v2.52.2 diff --git a/services/backend/go.sum b/services/backend/go.sum index 7d78a818..b10c803b 100644 --- a/services/backend/go.sum +++ b/services/backend/go.sum @@ -39,8 +39,6 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= -github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -60,10 +58,6 @@ github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrt github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sqlx/sqlx v1.3.7 h1:C6x4U4wWXtyssy+5IP6WguSjHMJChEbWB6/sw6mu/9E= github.com/go-sqlx/sqlx v1.3.7/go.mod h1:07mPTHP408293M6g7jFbllQW5O428VG2jX5dqYbTHkE= -github.com/go-webauthn/webauthn v0.10.1 h1:+RFKj4yHPy282teiiy5sqTYPfRilzBpJyedrz9KsNFE= -github.com/go-webauthn/webauthn v0.10.1/go.mod h1:a7BwAtrSMkeuJXtIKz433Av99nAv01pdfzB0a9xkDnI= -github.com/go-webauthn/x v0.1.8 h1:f1C6k1AyUlDvnIzWSW+G9rN9nbp1hhLXZagUtyxZ8nc= -github.com/go-webauthn/x v0.1.8/go.mod h1:i8UNlGVt3oy6oAFcP4SZB1djZLx/4pbekCbWowjTaJg= github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo= github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/gofiber/swagger v1.0.0 h1:BzUzDS9ZT6fDUa692kxmfOjc1DZiloLiPK/W5z1H1tc= @@ -76,8 +70,6 @@ github.com/golang-migrate/migrate/v4 v4.17.0 h1:rd40H3QXU0AA4IoLllFcEAEo9dYKRHYN github.com/golang-migrate/migrate/v4 v4.17.0/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= -github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= 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/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -198,8 +190,6 @@ github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVS github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/wayneashleyberry/terminal-dimensions v1.1.0 h1:EB7cIzBdsOzAgmhTUtTTQXBByuPheP/Zv1zL2BRPY6g= github.com/wayneashleyberry/terminal-dimensions v1.1.0/go.mod h1:2lc/0eWCObmhRczn2SdGSQtgBooLUzIotkkEGXqghyg= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= diff --git a/services/backend/modd.conf b/services/backend/modd.conf index 85b21189..ebfde656 100644 --- a/services/backend/modd.conf +++ b/services/backend/modd.conf @@ -2,5 +2,5 @@ src/**/* !src/assets/frontend/**/* { prep: swag fmt -g src/web-app/app.go && swag init -g src/web-app/app.go -o swagger-docs - daemon +sigterm: go run src/main.go run --show-swagger + daemon +sigterm: go run src/main.go run } \ No newline at end of file diff --git a/services/backend/scripts/test-local-docker.sh b/services/backend/scripts/test-local-docker.sh index 154bbd6f..ec2c9e32 100644 --- a/services/backend/scripts/test-local-docker.sh +++ b/services/backend/scripts/test-local-docker.sh @@ -1,6 +1,13 @@ go mod download go install golang.org/x/tools/cmd/goimports +go install github.com/swaggo/swag/cmd/swag@latest go install gotest.tools/gotestsum@latest + +mkdir -p src/assets/frontend +echo "Hello World 2" > src/assets/frontend/test.txt + +swag fmt -g src/web-app/app.go && swag init -g src/web-app/app.go -o swagger-docs + go run src/main.go migrate-db gotestsum --format testname \ No newline at end of file diff --git a/services/backend/src/cmd/migrate/migrate.go b/services/backend/src/cmd/migrate/migrate.go index 2ee6185d..92551d2b 100644 --- a/services/backend/src/cmd/migrate/migrate.go +++ b/services/backend/src/cmd/migrate/migrate.go @@ -21,9 +21,9 @@ var MigrateCmd = &cobra.Command{ Long: `🚀 Migrate your database to a newer version`, Run: func(cmd *cobra.Command, args []string) { - configuration := config.LoadData() + config.LoadData() branding.PrintBranding() - err := migrator.NewMigrator(configuration).MigrateUp() + err := migrator.NewMigrator().MigrateUp() messageStyle := lipgloss.NewStyle().Bold(true) successMessageStyle := messageStyle.Foreground(lipgloss.Color("#1eb523")) diff --git a/services/backend/src/cmd/run/run.go b/services/backend/src/cmd/run/run.go index d4a817aa..23ef53c9 100644 --- a/services/backend/src/cmd/run/run.go +++ b/services/backend/src/cmd/run/run.go @@ -5,7 +5,6 @@ package cmd import ( "github.com/spf13/cobra" - "github.com/spf13/viper" "github.com/uvulpos/go-svelte/src/helper/branding" "github.com/uvulpos/go-svelte/src/helper/config" webApp "github.com/uvulpos/go-svelte/src/web-app" @@ -23,17 +22,9 @@ var RunAppCmd = &cobra.Command{ Long: `starts the webserver to provide the application`, Run: func(cmd *cobra.Command, args []string) { - configuration := config.LoadData() + config.LoadData() branding.PrintBrandingWithConfig() - webApp.NewApp(configuration).RunApp(configuration) - }, -} -func init() { - RunAppCmd.Flags().BoolVar(&showNoFrontend, "no-frontend", false, "disable the frontend and deliver just an api") - RunAppCmd.Flags().BoolVar(&showSwaggger, "show-swagger", false, "enable the swagger api for developing") - RunAppCmd.Flags().IntVarP(&webserverPort, "port", "p", 3000, "define a port, where the application should listen to") - - flagSet := RunAppCmd.Flags() - viper.BindPFlags(flagSet) + webApp.NewApp().RunApp() + }, } diff --git a/services/backend/src/helper/branding/main.go b/services/backend/src/helper/branding/main.go index 84d43834..1572c40d 100644 --- a/services/backend/src/helper/branding/main.go +++ b/services/backend/src/helper/branding/main.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/uvulpos/go-svelte/src/helper/branding/models" + "github.com/uvulpos/go-svelte/src/helper/config" ) func PrintBranding() { @@ -28,8 +29,10 @@ func PrintBrandingWithConfig() { startupInformation, defaultConfConfiguraton := getAsciiStartupInformation() startupPresetTable := getAsciiConfigurationTable(models.ConfigurationTable{ - Host: "127.0.0.1", - Port: "8080", + Host: config.GetWebserver().Host, + Port: fmt.Sprint(config.GetWebserver().Port), + ShowFrontend: config.GetWebserver().ShowFrontend, + ShowSwagger: config.GetWebserver().ShowSwagger, }, defaultConfConfiguraton) fmt.Println(logo) diff --git a/services/backend/src/helper/branding/models/configuration_table_model.go b/services/backend/src/helper/branding/models/configuration_table_model.go index 4559747d..f2d19cb6 100644 --- a/services/backend/src/helper/branding/models/configuration_table_model.go +++ b/services/backend/src/helper/branding/models/configuration_table_model.go @@ -1,6 +1,8 @@ package models type ConfigurationTable struct { - Host string - Port string + Host string + Port string + ShowFrontend bool + ShowSwagger bool } diff --git a/services/backend/src/helper/branding/preset_table.go b/services/backend/src/helper/branding/preset_table.go index 6af51327..2c97585f 100644 --- a/services/backend/src/helper/branding/preset_table.go +++ b/services/backend/src/helper/branding/preset_table.go @@ -1,6 +1,8 @@ package branding import ( + "fmt" + "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss/table" "github.com/uvulpos/go-svelte/src/helper/branding/models" @@ -10,6 +12,8 @@ func getAsciiConfigurationTable(configuration models.ConfigurationTable, presetS configurationRows := [][]string{ {"Host:", configuration.Host}, {"Port:", configuration.Port}, + {"ShowFrontend:", fmt.Sprintf("%t", configuration.ShowFrontend)}, + {"ShowSwagger:", fmt.Sprintf("%t", configuration.ShowSwagger)}, } informationTable := table.New(). @@ -19,8 +23,8 @@ func getAsciiConfigurationTable(configuration models.ConfigurationTable, presetS Rows(configurationRows...) styleInformation := presetStle.Align(lipgloss.Left). - PaddingLeft(5). - PaddingRight(5). + PaddingLeft(3). + PaddingRight(3). Underline(false). Bold(false) diff --git a/services/backend/src/helper/config/config.go b/services/backend/src/helper/config/config.go index 8cb79280..e04096ca 100644 --- a/services/backend/src/helper/config/config.go +++ b/services/backend/src/helper/config/config.go @@ -2,25 +2,119 @@ package config import ( "fmt" + "log" + "reflect" + "strings" "github.com/spf13/viper" ) -func LoadData() *Configuration { +var ( + config Config +) + +/* +* +* I encountered issues by autodetecting the struct from viper so temporary manual +* TODO: autoread struct +* + */ +func LoadData() { + + viperConfig := viper.New() + viperConfig.AddConfigPath(".") + viperConfig.AddConfigPath("$HOME/.my-application") + viperConfig.SetConfigName("config") + viperConfig.SetConfigType("yaml") + + viperConfig.SetEnvPrefix("app") + + replacer := strings.NewReplacer(".", "_") + viperConfig.SetEnvKeyReplacer(replacer) + viperConfig.AllowEmptyEnv(true) + + viperConfig.AutomaticEnv() + bindEnvVariables(reflect.TypeOf(Config{}), "", viperConfig) - config := createDefaultConfiguration() - fmt.Println("---- LOAD CONFIG") + err := viperConfig.ReadInConfig() + if err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + fmt.Println("[INFORMATION]: No config file found, relying on environment variables only.") + } else { + log.Fatalf("Fatal error config file: %s", err) + } + } - viperInstance := viper.New() + if err := viperConfig.Unmarshal(&config); err != nil { + log.Fatalf("Unable to decode into struct, %s", err) + } + + fmt.Println("Keys: ", viperConfig.AllKeys()) + fmt.Println("Keys: ", viperConfig.AllSettings()) + fmt.Println("Webserver: ", config.Webserver) + fmt.Println("Database: ", config.Database) + fmt.Println("Security: ", config.Security) +} + +func bindEnvVariables(t reflect.Type, parent string, viperConfig *viper.Viper) { + if t.Kind() == reflect.Struct { + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + jsonTag := field.Tag.Get("mapstructure") + if jsonTag == "" { + jsonTag = strings.ToLower(field.Name) + } + + fullPath := jsonTag + if parent != "" { + fullPath = parent + "." + jsonTag + } + + viperConfig.BindEnv(fullPath, strings.ToUpper(viperConfig.GetEnvPrefix()+"_"+strings.ReplaceAll(fullPath, ".", "_"))) + bindEnvVariables(field.Type, fullPath, viperConfig) + } + } +} - viperInstance.SetDefault("db-host", "postgres") - viperInstance.SetDefault("db-port", "5432") - viperInstance.SetDefault("db-username", "postgres") - viperInstance.SetDefault("db-password", "postgres") - viperInstance.SetDefault("db-database", "postgres") - viperInstance.SetDefault("db-sslmode", false) +func GetSqlConnectionString() (string, string) { - viperInstance.AutomaticEnv() + var sslMode string = "disable" + if config.Database.SslMode { + + sslMode = "require" + } + + connString := fmt.Sprintf( + "postgres://%s:%s@%s:%d/%s?sslmode=%s", + config.Database.Username, + config.Database.Password, + config.Database.Host, + config.Database.Port, + config.Database.Database, + sslMode, + ) + + humanString := fmt.Sprintf( + "%s:%d", + config.Database.Host, + config.Database.Port, + ) + + return connString, humanString +} + +func GetDatabase() DatabaseConfig { + return config.Database +} + +func GetWebserver() WebserverConfig { + return config.Webserver +} + +func ShowFrontend() bool { + return config.Webserver.ShowFrontend +} - return config +func GetJwtSecret() string { + return config.Security.JwtSecret } diff --git a/services/backend/src/helper/config/structs.go b/services/backend/src/helper/config/structs.go index c595ece9..de705494 100644 --- a/services/backend/src/helper/config/structs.go +++ b/services/backend/src/helper/config/structs.go @@ -1,17 +1,12 @@ package config -type Configuration struct { - Webserver Webserver `mapstructure:"webserver"` - DB DatabaseCredentials `mapstructure:"db"` +type Config struct { + Database DatabaseConfig + Webserver WebserverConfig + Security SecurityConfig } -type Webserver struct { - Port int `mapstructure:"port"` - NoFrontend bool `mapstructure:"nofrontend"` - ShowSwagger bool `mapstructure:"showswagger"` -} - -type DatabaseCredentials struct { +type DatabaseConfig struct { Host string `mapstructure:"host"` Port int `mapstructure:"port"` Username string `mapstructure:"username"` @@ -20,20 +15,14 @@ type DatabaseCredentials struct { SslMode bool `mapstructure:"sslmode"` } -func createDefaultConfiguration() *Configuration { - return &Configuration{ - Webserver: Webserver{ - Port: 3000, - NoFrontend: false, - ShowSwagger: true, - }, - DB: DatabaseCredentials{ - Host: "postgres", - Port: 5432, - Username: "postgres", - Password: "postgres", - Database: "postgres", - SslMode: false, - }, - } +type WebserverConfig struct { + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + ShowFrontend bool `mapstructure:"show_frontend"` + ShowSwagger bool `mapstructure:"show_swagger"` +} + +type SecurityConfig struct { + JwtSecret string + SecretGreet string } diff --git a/services/backend/src/helper/database/create-database.go b/services/backend/src/helper/database/create-database.go index 83253a29..6915bece 100644 --- a/services/backend/src/helper/database/create-database.go +++ b/services/backend/src/helper/database/create-database.go @@ -1,36 +1,13 @@ package database import ( - "fmt" - "github.com/go-sqlx/sqlx" "github.com/uvulpos/go-svelte/src/helper/config" ) -func CreateDatabase(configuration *config.Configuration) (*Sql, error) { - dbHost := configuration.DB.Host - dbPort := configuration.DB.Port - dbUsername := configuration.DB.Username - dbPassword := configuration.DB.Password - dbDatabase := configuration.DB.Database - - addr := fmt.Sprintf("%s:%d", dbHost, dbPort) - - var sslMode string = "disable" - if configuration.DB.SslMode { - sslMode = "require" - } - - connStr := fmt.Sprintf( - "postgres://%s:%s@%s/%s?sslmode=%s", - dbUsername, - dbPassword, - addr, - dbDatabase, - sslMode, - ) +func CreateDatabase() (*Sql, error) { + connStr, _ := config.GetSqlConnectionString() - fmt.Println("DB CONN: ", connStr) db, dbErr := sqlx.Connect("postgres", connStr) if dbErr != nil { return nil, dbErr diff --git a/services/backend/src/helper/jwt/create_jwt.go b/services/backend/src/helper/jwt/create_jwt.go index 3509cbb8..1525896c 100644 --- a/services/backend/src/helper/jwt/create_jwt.go +++ b/services/backend/src/helper/jwt/create_jwt.go @@ -2,11 +2,10 @@ package jwt import ( "github.com/golang-jwt/jwt/v5" + "github.com/uvulpos/go-svelte/src/helper/config" userService "github.com/uvulpos/go-svelte/src/resources/users/service" ) -const jwtTokenSecret = `loafofbread` - func NewJWT(user *userService.UserWithPermission) (string, error) { var key []byte // *ecdsa.PrivateKey ->> https://golang-jwt.github.io/jwt/usage/create/ var t *jwt.Token @@ -17,7 +16,7 @@ func NewJWT(user *userService.UserWithPermission) (string, error) { roleIndicators = append(roleIndicators, r.Identifier) } - key = []byte("loafofbread") + key = []byte(config.GetJwtSecret()) t = jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{ "user-uuid": user.Id.String(), "username": user.Username, diff --git a/services/backend/src/helper/jwt/verify_jwt.go b/services/backend/src/helper/jwt/verify_jwt.go index d854dd02..67db12a0 100644 --- a/services/backend/src/helper/jwt/verify_jwt.go +++ b/services/backend/src/helper/jwt/verify_jwt.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/golang-jwt/jwt/v5" + "github.com/uvulpos/go-svelte/src/helper/config" ) type AppJWTClaims struct { @@ -25,7 +26,7 @@ func VerifyJWToken(jwtToken string) (bool, *AppJWTClaims, error) { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } - return []byte(jwtTokenSecret), nil + return []byte(config.GetJwtSecret()), nil }) if tokenErr != nil { fmt.Println("Verify JWT", tokenErr) diff --git a/services/backend/src/helper/webauthn/login.go b/services/backend/src/helper/webauthn/login.go deleted file mode 100644 index 0957c97d..00000000 --- a/services/backend/src/helper/webauthn/login.go +++ /dev/null @@ -1,9 +0,0 @@ -package webauthn - -func (webN *WebAuthN) BeginLogin() { - -} - -func (webN *WebAuthN) FinishLogin() { - -} diff --git a/services/backend/src/helper/webauthn/main.go b/services/backend/src/helper/webauthn/main.go deleted file mode 100644 index e1163d92..00000000 --- a/services/backend/src/helper/webauthn/main.go +++ /dev/null @@ -1,38 +0,0 @@ -package webauthn - -import ( - "fmt" - - "github.com/go-webauthn/webauthn/webauthn" -) - -type WebAuthN struct { - webAuthn *webauthn.WebAuthn -} - -func CreateNewWebAuthN(DisplayName, Domain string, AllowedDomains ...string) *WebAuthN { - - if len(AllowedDomains) == 0 { - AllowedDomains = []string{Domain} - } - - wconfig := &webauthn.Config{ - RPDisplayName: DisplayName, // Display Name for your site - RPID: Domain, // Generally the FQDN for your site - RPOrigins: AllowedDomains, // The origin URLs allowed for WebAuthn requests - } - - webAuthn, err := webauthn.New(wconfig) - if err != nil { - fmt.Println(err) - } - - return &WebAuthN{ - webAuthn, - } -} - -// // get Configuration of WebAuthN Handler -// func (webN *WebAuthN) GetConfig() *webauthn.Config { -// return webN.webAuthn.Config -// } diff --git a/services/backend/src/helper/webauthn/registration.go b/services/backend/src/helper/webauthn/registration.go deleted file mode 100644 index eb8c9c78..00000000 --- a/services/backend/src/helper/webauthn/registration.go +++ /dev/null @@ -1,24 +0,0 @@ -package webauthn - -import ( - "github.com/go-webauthn/webauthn/protocol" - "github.com/go-webauthn/webauthn/webauthn" -) - -func (webN *WebAuthN) BeginRegistration(user *WebAuthNUser) (*protocol.CredentialCreation, *webauthn.SessionData, error) { - options, session, err := webN.webAuthn.BeginRegistration(user) - if err != nil { - return nil, nil, err - } - return options, session, nil -} - -func (webN *WebAuthN) FinishRegistration() { - // _, err := webN.webAuthn.FinishRegistration(user, session, r) - // if err != nil { - // // Handle Error and return. - - // return - // } - -} diff --git a/services/backend/src/helper/webauthn/user.go b/services/backend/src/helper/webauthn/user.go deleted file mode 100644 index b113204d..00000000 --- a/services/backend/src/helper/webauthn/user.go +++ /dev/null @@ -1,63 +0,0 @@ -package webauthn - -import "github.com/go-webauthn/webauthn/webauthn" - -type WebAuthNUser struct { - ID string - Name string - DisplayName string - Icon string - Credentials []webauthn.Credential -} - -func CreateWebAuthNUser( - ID, - Name, - DisplayName string, - Credentials []webauthn.Credential, - CredentialsSignIn []webauthn.Credential, -) *WebAuthNUser { - return &WebAuthNUser{ - ID, - Name, - DisplayName, - "", - Credentials, - } -} - -func CreateWebAuthNUserWithOutCertificates( - ID, - Name, - DisplayName string, -) *WebAuthNUser { - return &WebAuthNUser{ - ID, - Name, - DisplayName, - "", - []webauthn.Credential{}, - } -} - -func (u *WebAuthNUser) WebAuthnID() []byte { - return []byte(u.ID) -} - -func (u *WebAuthNUser) WebAuthnName() string { - return u.Name -} - -func (u *WebAuthNUser) WebAuthnDisplayName() string { - return u.DisplayName -} - -func (u *WebAuthNUser) WebAuthnCredentials() []webauthn.Credential { - return u.Credentials -} - -// WebAuthnIcon is a deprecated option. -// Deprecated: this has been removed from the specification recommendation. Suggest a blank string. -func (u *WebAuthNUser) WebAuthnIcon() string { - return "" -} diff --git a/services/backend/src/migrator/migration-files/1_add_user.up.sql b/services/backend/src/migrator/migration-files/1_add_user.up.sql index c15b9e96..74fcb880 100644 --- a/services/backend/src/migrator/migration-files/1_add_user.up.sql +++ b/services/backend/src/migrator/migration-files/1_add_user.up.sql @@ -57,7 +57,6 @@ INSERT INTO role_permissions (role_id, permission_id) VALUES ((SELECT id FROM roles WHERE name = 'User'), (SELECT id FROM permissions WHERE identifier = 'GREET_USER')), ((SELECT id FROM roles WHERE name = 'Admin'), (SELECT id FROM permissions WHERE identifier = 'GREET_ADMIN')), ((SELECT id FROM roles WHERE name = 'Admin'), (SELECT id FROM permissions WHERE identifier = 'MANAGE_USERS')); -dvdkgcridb -- password is default "123" INSERT INTO users (username, email, password, ldap_uuid, auth_source, role_id) VALUES diff --git a/services/backend/src/migrator/migrator.go b/services/backend/src/migrator/migrator.go index 2e53a89d..e943e2c2 100644 --- a/services/backend/src/migrator/migrator.go +++ b/services/backend/src/migrator/migrator.go @@ -10,7 +10,6 @@ import ( "github.com/golang-migrate/migrate/v4/database/postgres" "github.com/golang-migrate/migrate/v4/source/httpfs" _ "github.com/lib/pq" - "github.com/uvulpos/go-svelte/src/helper/config" dbHelper "github.com/uvulpos/go-svelte/src/helper/database" ) @@ -21,8 +20,8 @@ type Migrator struct { db *sql.DB } -func NewMigrator(configuration *config.Configuration) *Migrator { - dbConn, dbConnErr := dbHelper.CreateDatabase(configuration) +func NewMigrator() *Migrator { + dbConn, dbConnErr := dbHelper.CreateDatabase() if dbConn == nil || dbConn.DB == nil || dbConnErr != nil { err := fmt.Errorf("could not connect to database") if err != nil { diff --git a/services/backend/src/resources/passkeys-fido/http/handler.go b/services/backend/src/resources/passkeys-fido/http/handler.go deleted file mode 100644 index 9bfdffc1..00000000 --- a/services/backend/src/resources/passkeys-fido/http/handler.go +++ /dev/null @@ -1,13 +0,0 @@ -package http - -import "github.com/uvulpos/go-svelte/src/resources/passkeys-fido/service" - -type PasskeyHandler struct { - service *service.PasskeySvc -} - -func NewPasskeyHandler(service *service.PasskeySvc) *PasskeyHandler { - return &PasskeyHandler{ - service, - } -} diff --git a/services/backend/src/resources/passkeys-fido/http/register_fido2_begin.go b/services/backend/src/resources/passkeys-fido/http/register_fido2_begin.go deleted file mode 100644 index d31ad339..00000000 --- a/services/backend/src/resources/passkeys-fido/http/register_fido2_begin.go +++ /dev/null @@ -1,25 +0,0 @@ -package http - -import ( - "net/http" - - "github.com/gofiber/fiber/v2" -) - -func (h *PasskeyHandler) BeginWebAuthNRegistration(c *fiber.Ctx) error { - // requestUser := c.Locals("user-uuid") - // userUuid, ok := requestUser.(string) - // if !ok { - // return c.SendStatus(http.StatusUnauthorized) - // } - - // credential, err := h.service.RegisterUserFidoBegin(userUuid) - // if err != nil { - // fmt.Println(err) - // return err - // } - - // return c.JSON(credential) - - return c.SendStatus(http.StatusOK) -} diff --git a/services/backend/src/resources/passkeys-fido/http/register_fido2_finish.go b/services/backend/src/resources/passkeys-fido/http/register_fido2_finish.go deleted file mode 100644 index 33106606..00000000 --- a/services/backend/src/resources/passkeys-fido/http/register_fido2_finish.go +++ /dev/null @@ -1,33 +0,0 @@ -package http - -import ( - "net/http" - - "github.com/gofiber/fiber/v2" -) - -type FidoRegisterFinishPayload struct { - ID string `json:"id"` - RawID string `json:"rawId"` - Type string `json:"type"` - Response struct { - AttestationObject string `json:"attestationObject"` - ClientDataJSON string `json:"clientDataJSON"` - } `json:"response"` -} - -func (h *PasskeyHandler) FinishWebAuthNRegistration(c *fiber.Ctx) error { - // requestUser := c.Locals("user-uuid") - // userUuid, ok := requestUser.(string) - // if !ok { - // return c.SendStatus(http.StatusUnauthorized) - // } - - // err := h.service.RegisterUserFidoFinish(userUuid) - // if err != nil { - // fmt.Println(err) - // return err - // } - - return c.SendStatus(http.StatusOK) -} diff --git a/services/backend/src/resources/passkeys-fido/service/handler.go b/services/backend/src/resources/passkeys-fido/service/handler.go deleted file mode 100644 index 3dd099f4..00000000 --- a/services/backend/src/resources/passkeys-fido/service/handler.go +++ /dev/null @@ -1,29 +0,0 @@ -package service - -import ( - "time" - - "github.com/go-sqlx/sqlx" - "github.com/uvulpos/go-svelte/src/helper/webauthn" - - userSvc "github.com/uvulpos/go-svelte/src/resources/users/service" -) - -type PasskeySvc struct { - storage PasskeyStorage - userService *userSvc.UserSvc - webAuthN *webauthn.WebAuthN -} - -func NewPasskeySvc(storage PasskeyStorage, user *userSvc.UserSvc, webAuthN *webauthn.WebAuthN) *PasskeySvc { - return &PasskeySvc{ - storage, - user, - webAuthN, - } -} - -type PasskeyStorage interface { - CreateTransaction() (*sqlx.Tx, error) - InsertFidoSession(tx *sqlx.Tx, uuid string, sessionJson []byte, expires time.Time) error -} diff --git a/services/backend/src/resources/passkeys-fido/service/register_user_fido_begin.go b/services/backend/src/resources/passkeys-fido/service/register_user_fido_begin.go deleted file mode 100644 index 90f64181..00000000 --- a/services/backend/src/resources/passkeys-fido/service/register_user_fido_begin.go +++ /dev/null @@ -1,38 +0,0 @@ -package service - -import ( - "encoding/json" - - "github.com/go-webauthn/webauthn/protocol" - "github.com/uvulpos/go-svelte/src/helper/webauthn" -) - -func (h *PasskeySvc) RegisterUserFidoBegin(uuid string) (*protocol.CredentialCreation, error) { - user, userErr := h.userService.GetUserByUUID(nil, uuid) - if userErr != nil { - return nil, userErr - } - - webAuthUser := webauthn.CreateWebAuthNUserWithOutCertificates( - user.Id.String(), - user.Username, - user.Username, - ) - - credential, session, err := h.webAuthN.BeginRegistration(webAuthUser) - if err != nil { - return nil, err - } - - sessionJson, sessionJsonErr := json.Marshal(session) - if sessionJsonErr != nil { - return nil, sessionJsonErr - } - - sessionErr := h.storage.InsertFidoSession(nil, uuid, sessionJson, session.Expires) - if sessionErr != nil { - return nil, sessionErr - } - - return credential, nil -} diff --git a/services/backend/src/resources/passkeys-fido/service/register_user_fido_finish.go b/services/backend/src/resources/passkeys-fido/service/register_user_fido_finish.go deleted file mode 100644 index c054590e..00000000 --- a/services/backend/src/resources/passkeys-fido/service/register_user_fido_finish.go +++ /dev/null @@ -1,12 +0,0 @@ -package service - -func (h *PasskeySvc) RegisterUserFidoFinish(userUuid string) error { - - // get user - - // get session - - // finish registration - - return nil -} diff --git a/services/backend/src/resources/passkeys-fido/storage/create_transaction.go b/services/backend/src/resources/passkeys-fido/storage/create_transaction.go deleted file mode 100644 index 3aeaeb43..00000000 --- a/services/backend/src/resources/passkeys-fido/storage/create_transaction.go +++ /dev/null @@ -1,11 +0,0 @@ -package storage - -import "github.com/go-sqlx/sqlx" - -func (h *PasskeyStore) CreateTransaction() (*sqlx.Tx, error) { - tx, txErr := h.dbstore.DB.Beginx() - if txErr != nil { - return nil, txErr - } - return tx, nil -} diff --git a/services/backend/src/resources/passkeys-fido/storage/get_session.go b/services/backend/src/resources/passkeys-fido/storage/get_session.go deleted file mode 100644 index 02ec2ca3..00000000 --- a/services/backend/src/resources/passkeys-fido/storage/get_session.go +++ /dev/null @@ -1,25 +0,0 @@ -package storage - -import ( - "errors" - "time" - - "github.com/go-sqlx/sqlx" -) - -func (h *PasskeyStore) GetFidoSession(tx *sqlx.Tx, uuid string, sessionJson []byte, expires time.Time) error { - var rowErr error - const sql = `` - - if tx == nil { - _, rowErr = h.dbstore.DB.Exec(sql) - } else { - _, rowErr = tx.Exec(sql) - } - - if rowErr != nil { - return errors.New("could not insert session into database") - } - - return nil -} diff --git a/services/backend/src/resources/passkeys-fido/storage/handler.go b/services/backend/src/resources/passkeys-fido/storage/handler.go deleted file mode 100644 index fdcbce58..00000000 --- a/services/backend/src/resources/passkeys-fido/storage/handler.go +++ /dev/null @@ -1,15 +0,0 @@ -package storage - -import ( - "github.com/uvulpos/go-svelte/src/helper/database" -) - -type PasskeyStore struct { - dbstore database.Sql -} - -func NewUserStore(db database.Sql) *PasskeyStore { - return &PasskeyStore{ - db, - } -} diff --git a/services/backend/src/resources/passkeys-fido/storage/insert_credential.go b/services/backend/src/resources/passkeys-fido/storage/insert_credential.go deleted file mode 100644 index 9b1aabae..00000000 --- a/services/backend/src/resources/passkeys-fido/storage/insert_credential.go +++ /dev/null @@ -1,25 +0,0 @@ -package storage - -import ( - "errors" - "time" - - "github.com/go-sqlx/sqlx" -) - -func (h *PasskeyStore) InsertFidoCredential(tx *sqlx.Tx, uuid string, sessionJson []byte, expires time.Time) error { - var rowErr error - const sql = `` - - if tx == nil { - _, rowErr = h.dbstore.DB.Exec(sql) - } else { - _, rowErr = tx.Exec(sql) - } - - if rowErr != nil { - return errors.New("could not insert session into database") - } - - return nil -} diff --git a/services/backend/src/resources/passkeys-fido/storage/insert_session.go b/services/backend/src/resources/passkeys-fido/storage/insert_session.go deleted file mode 100644 index c7d8742b..00000000 --- a/services/backend/src/resources/passkeys-fido/storage/insert_session.go +++ /dev/null @@ -1,25 +0,0 @@ -package storage - -import ( - "errors" - "time" - - "github.com/go-sqlx/sqlx" -) - -func (h *PasskeyStore) InsertFidoSession(tx *sqlx.Tx, uuid string, sessionJson []byte, expires time.Time) error { - var rowErr error - const sql = `` - - if tx == nil { - _, rowErr = h.dbstore.DB.Exec(sql) - } else { - _, rowErr = tx.Exec(sql) - } - - if rowErr != nil { - return errors.New("could not insert session into database") - } - - return nil -} diff --git a/services/backend/src/web-app/app.go b/services/backend/src/web-app/app.go index 1907e675..e376072e 100644 --- a/services/backend/src/web-app/app.go +++ b/services/backend/src/web-app/app.go @@ -16,25 +16,19 @@ import ( "github.com/uvulpos/go-svelte/src/assets" "github.com/uvulpos/go-svelte/src/helper/config" dbHelper "github.com/uvulpos/go-svelte/src/helper/database" - "github.com/uvulpos/go-svelte/src/helper/webauthn" userHttp "github.com/uvulpos/go-svelte/src/resources/users/http" userService "github.com/uvulpos/go-svelte/src/resources/users/service" userStorage "github.com/uvulpos/go-svelte/src/resources/users/storage" - - passkeyHttp "github.com/uvulpos/go-svelte/src/resources/passkeys-fido/http" - passkeyService "github.com/uvulpos/go-svelte/src/resources/passkeys-fido/service" - passkeyStorage "github.com/uvulpos/go-svelte/src/resources/passkeys-fido/storage" ) type App struct { - UserHandler UserHandler - PasskeyHandler PasskeyHandler + UserHandler UserHandler } -func NewApp(configuration *config.Configuration) *App { +func NewApp() *App { - dbConn, dbConnErr := dbHelper.CreateDatabase(configuration) + dbConn, dbConnErr := dbHelper.CreateDatabase() if dbConn == nil || dbConn.DB == nil || dbConnErr != nil { err := fmt.Errorf("could not connect to database") if err != nil { @@ -43,28 +37,16 @@ func NewApp(configuration *config.Configuration) *App { return nil } - webAuthNHandler := webauthn.CreateNewWebAuthN( - "Go Svelte Binary Localhost", - "web.localhost", - "http://web.localhost/", - ) - userStore := userStorage.NewUserStore(*dbConn) userSvc := userService.NewUserSvc(userStore) userHandler := userHttp.NewUserHandler(userSvc) - passkeyStore := passkeyStorage.NewUserStore(*dbConn) - passkeySvc := passkeyService.NewPasskeySvc(passkeyStore, userSvc, webAuthNHandler) - passkeyHandler := passkeyHttp.NewPasskeyHandler(passkeySvc) - return &App{ - UserHandler: userHandler, - PasskeyHandler: passkeyHandler, + UserHandler: userHandler, } } -func (a *App) RunApp(configuration *config.Configuration) { - +func (a *App) RunApp() { publicFS, err := fs.Sub(assets.SvelteFS, "frontend") if err != nil { log.Fatal(err) @@ -85,7 +67,7 @@ func (a *App) RunApp(configuration *config.Configuration) { router.Get("/swagger/*", swagger.HandlerDefault) } - if !configuration.Webserver.NoFrontend { + if config.ShowFrontend() { router.Use("/", filesystem.New(filesystem.Config{ Root: http.FS(publicFS), NotFoundFile: "index.html", @@ -94,8 +76,8 @@ func (a *App) RunApp(configuration *config.Configuration) { router.Use(Handle404) - serverPort := fmt.Sprintf(":%d", configuration.Webserver.Port) - log.Printf("server listens on %s\n", serverPort) + serverPort := fmt.Sprintf(":%d", config.GetWebserver().Port) + fmt.Println("_") router.Listen(serverPort) } diff --git a/services/backend/src/web-app/handler.go b/services/backend/src/web-app/handler.go index d6181fff..42c28917 100644 --- a/services/backend/src/web-app/handler.go +++ b/services/backend/src/web-app/handler.go @@ -14,8 +14,3 @@ type UserHandler interface { HandleUpdateUserData(c *fiber.Ctx) error HandleJWTRefresh(c *fiber.Ctx) error } - -type PasskeyHandler interface { - BeginWebAuthNRegistration(c *fiber.Ctx) error - FinishWebAuthNRegistration(c *fiber.Ctx) error -} diff --git a/services/backend/src/web-app/routes.go b/services/backend/src/web-app/routes.go index 6507f919..e9517a55 100644 --- a/services/backend/src/web-app/routes.go +++ b/services/backend/src/web-app/routes.go @@ -17,10 +17,6 @@ func (a *App) createRoutes(router *fiber.App) { apiV1 := api.Group("v1") - // FIDO2 - apiV1.Get("u2f/login", a.PasskeyHandler.BeginWebAuthNRegistration) - apiV1.Post("u2f/login", a.PasskeyHandler.FinishWebAuthNRegistration) - apiV1.Post("login", a.UserHandler.HandleLogin) apiV1.Post("logout", a.UserHandler.HandleLogout) @@ -31,10 +27,6 @@ func (a *App) createRoutes(router *fiber.App) { apiV1.Post("login/is-available-username", a.UserHandler.HandleCheckUsername) apiV1.Post("login/change-password", a.UserHandler.HandleChangePassword) - // FIDO2 - apiV1.Get("u2f/register", a.PasskeyHandler.BeginWebAuthNRegistration) - apiV1.Post("u2f/register", a.PasskeyHandler.FinishWebAuthNRegistration) - // own user operations apiV1.Get("self/get-user-data", a.UserHandler.HandleGetProfile) apiV1.Post("self/update-user-data", a.UserHandler.HandleUpdateUserData) diff --git a/services/frontend/.gitignore b/services/frontend/.gitignore index 2cda9b0a..395bf4d2 100644 --- a/services/frontend/.gitignore +++ b/services/frontend/.gitignore @@ -8,4 +8,4 @@ node_modules !.env.example vite.config.js.timestamp-* vite.config.ts.timestamp-* -dist/ +dist diff --git a/services/frontend/package-lock.json b/services/frontend/package-lock.json index 7f80dc60..7a199bd5 100644 --- a/services/frontend/package-lock.json +++ b/services/frontend/package-lock.json @@ -2223,4 +2223,4 @@ "dev": true } } -} \ No newline at end of file +} diff --git a/services/frontend/static/favicon.ico b/services/frontend/static/favicon.ico new file mode 100644 index 00000000..9789f434 Binary files /dev/null and b/services/frontend/static/favicon.ico differ