From 7d143b9cae2cde608c9cd33cbee6d3eea98eb05a Mon Sep 17 00:00:00 2001 From: zcubbs Date: Sun, 15 Oct 2023 18:56:47 +0200 Subject: [PATCH] :fire: wip: enhance structure --- .editorconfig | 5 - .golangci.yaml | 5 + .goreleaser.yaml | 105 +++++++++++++++ .gosec.config.json | 2 +- Taskfile.yaml | 126 +++++------------- {api => cmd/server/api}/authorization.go | 0 {api => cmd/server/api}/converter.go | 2 +- {api => cmd/server/api}/error.go | 0 {api => cmd/server/api}/logger.go | 0 {api => cmd/server/api}/main_test.go | 2 +- {api => cmd/server/api}/metadata.go | 0 {api => cmd/server/api}/rpc_create_user.go | 2 +- .../server/api}/rpc_create_user_test.go | 4 +- {api => cmd/server/api}/rpc_login_user.go | 2 +- {api => cmd/server/api}/rpc_ping.go | 0 {api => cmd/server/api}/rpc_update_user.go | 2 +- {api => cmd/server/api}/rpc_verify_user.go | 2 +- {api => cmd/server/api}/server.go | 2 +- cmd/server/config/config.go | 101 ++++++++++++++ cmd/server/config/defaults.go | 78 +++++++++++ cmd/server/config/types.go | 74 ++++++++++ .../db/migration}/000001_init_schema.down.sql | 0 .../db/migration}/000001_init_schema.up.sql | 0 .../000002_add_notifications.down.sql | 0 .../000002_add_notifications.up.sql | 0 .../db/migration}/000003_add_users.down.sql | 0 .../db/migration}/000003_add_users.up.sql | 0 .../migration}/000004_add_sessions.down.sql | 0 .../db/migration}/000004_add_sessions.up.sql | 0 .../db/migration}/000005_add_domains.down.sql | 0 .../db/migration}/000005_add_domains.up.sql | 0 .../000006_add_verify_email.down.sql | 0 .../migration}/000006_add_verify_email.up.sql | 0 .../server/db/migration}/migrations.go | 39 +++--- {db => cmd/server/db}/mock/store.go | 0 {db => cmd/server/db}/queries/domain.sql | 0 .../server/db}/queries/notification.sql | 0 {db => cmd/server/db}/queries/session.sql | 0 {db => cmd/server/db}/queries/user.sql | 0 .../server/db}/queries/verify_email.sql | 0 sqlc.yaml => cmd/server/db/sqlc.yaml | 6 +- {db => cmd/server/db}/sqlc/db.go | 0 {db => cmd/server/db}/sqlc/domain.sql.go | 0 {db => cmd/server/db}/sqlc/error.go | 0 {db => cmd/server/db}/sqlc/exec_tx.go | 0 {db => cmd/server/db}/sqlc/main_test.go | 3 +- {db => cmd/server/db}/sqlc/models.go | 0 .../server/db}/sqlc/notification.sql.go | 0 {db => cmd/server/db}/sqlc/querier.go | 0 {db => cmd/server/db}/sqlc/session.sql.go | 0 {db => cmd/server/db}/sqlc/store.go | 0 {db => cmd/server/db}/sqlc/tx_create_user.go | 0 {db => cmd/server/db}/sqlc/tx_verify_email.go | 0 {db => cmd/server/db}/sqlc/user.sql.go | 0 {db => cmd/server/db}/sqlc/user_test.go | 0 .../server/db}/sqlc/verify_email.sql.go | 0 cmd/server/db/util/connect.go | 55 ++++++++ cmd/server/db/util/error.go | 26 ++++ cmd/server/db/util/init_admin_user.go | 58 ++++++++ cmd/server/db/util/util.go | 26 ++++ .../server/docs}/swagger/favicon-16x16.png | Bin .../server/docs}/swagger/favicon-32x32.png | Bin {docs => cmd/server/docs}/swagger/index.css | 0 {docs => cmd/server/docs}/swagger/index.html | 0 .../server/docs}/swagger/oauth2-redirect.html | 0 .../docs}/swagger/swagger-initializer.js | 0 .../server/docs}/swagger/swagger-ui-bundle.js | 0 .../docs}/swagger/swagger-ui-bundle.js.map | 0 .../swagger/swagger-ui-es-bundle-core.js | 0 .../swagger/swagger-ui-es-bundle-core.js.map | 0 .../docs}/swagger/swagger-ui-es-bundle.js | 0 .../docs}/swagger/swagger-ui-es-bundle.js.map | 0 .../swagger/swagger-ui-standalone-preset.js | 0 .../swagger-ui-standalone-preset.js.map | 0 .../server/docs}/swagger/swagger-ui.css | 0 .../server/docs}/swagger/swagger-ui.css.map | 0 .../server/docs}/swagger/swagger-ui.js | 0 .../server/docs}/swagger/swagger-ui.js.map | 0 .../server/docs}/swagger/tlz.swagger.json | 0 .../server/internal}/logger/logger.go | 0 .../server/internal}/task/check_tls.go | 2 +- .../internal}/task/send_notification.go | 2 +- .../server/internal}/task/status.go | 0 .../server/internal}/task/task.go | 2 +- .../server/internal}/util/config.go | 0 .../server/internal}/util/config_defaults.go | 0 .../server/internal}/util/config_types.go | 0 .../server/internal}/util/db_connect.go | 0 .../server/internal}/validator/validator.go | 0 main.go => cmd/server/main.go | 19 ++- .../templates}/expiry_notification.html | 0 {web => cmd/server/web}/.eslintrc.cjs | 0 {web => cmd/server/web}/.gitignore | 0 {web => cmd/server/web}/index.html | 0 {web => cmd/server/web}/package-lock.json | 0 {web => cmd/server/web}/package.json | 0 {web => cmd/server/web}/public/vite.svg | 0 {web => cmd/server/web}/src/AddDomainForm.jsx | 0 {web => cmd/server/web}/src/App.jsx | 0 {web => cmd/server/web}/src/DomainsTable.jsx | 0 {web => cmd/server/web}/src/assets/react.svg | 0 {web => cmd/server/web}/src/main.jsx | 0 {web => cmd/server/web}/vite.config.js | 0 {worker => cmd/server/worker}/distributor.go | 0 {worker => cmd/server/worker}/logger.go | 0 .../server/worker}/mock/distributor.go | 0 {worker => cmd/server/worker}/processor.go | 0 .../server/worker}/task_send_verify_email.go | 0 {worker => cmd/server/worker}/worker.go | 0 project.toml | 3 - 110 files changed, 611 insertions(+), 144 deletions(-) create mode 100644 .golangci.yaml create mode 100644 .goreleaser.yaml rename {api => cmd/server/api}/authorization.go (100%) rename {api => cmd/server/api}/converter.go (89%) rename {api => cmd/server/api}/error.go (100%) rename {api => cmd/server/api}/logger.go (100%) rename {api => cmd/server/api}/main_test.go (95%) rename {api => cmd/server/api}/metadata.go (100%) rename {api => cmd/server/api}/rpc_create_user.go (98%) rename {api => cmd/server/api}/rpc_create_user_test.go (97%) rename {api => cmd/server/api}/rpc_login_user.go (97%) rename {api => cmd/server/api}/rpc_ping.go (100%) rename {api => cmd/server/api}/rpc_update_user.go (98%) rename {api => cmd/server/api}/rpc_verify_user.go (96%) rename {api => cmd/server/api}/server.go (98%) create mode 100644 cmd/server/config/config.go create mode 100644 cmd/server/config/defaults.go create mode 100644 cmd/server/config/types.go rename {db/migrations => cmd/server/db/migration}/000001_init_schema.down.sql (100%) rename {db/migrations => cmd/server/db/migration}/000001_init_schema.up.sql (100%) rename {db/migrations => cmd/server/db/migration}/000002_add_notifications.down.sql (100%) rename {db/migrations => cmd/server/db/migration}/000002_add_notifications.up.sql (100%) rename {db/migrations => cmd/server/db/migration}/000003_add_users.down.sql (100%) rename {db/migrations => cmd/server/db/migration}/000003_add_users.up.sql (100%) rename {db/migrations => cmd/server/db/migration}/000004_add_sessions.down.sql (100%) rename {db/migrations => cmd/server/db/migration}/000004_add_sessions.up.sql (100%) rename {db/migrations => cmd/server/db/migration}/000005_add_domains.down.sql (100%) rename {db/migrations => cmd/server/db/migration}/000005_add_domains.up.sql (100%) rename {db/migrations => cmd/server/db/migration}/000006_add_verify_email.down.sql (100%) rename {db/migrations => cmd/server/db/migration}/000006_add_verify_email.up.sql (100%) rename {db/migrations => cmd/server/db/migration}/migrations.go (70%) rename {db => cmd/server/db}/mock/store.go (100%) rename {db => cmd/server/db}/queries/domain.sql (100%) rename {db => cmd/server/db}/queries/notification.sql (100%) rename {db => cmd/server/db}/queries/session.sql (100%) rename {db => cmd/server/db}/queries/user.sql (100%) rename {db => cmd/server/db}/queries/verify_email.sql (100%) rename sqlc.yaml => cmd/server/db/sqlc.yaml (82%) rename {db => cmd/server/db}/sqlc/db.go (100%) rename {db => cmd/server/db}/sqlc/domain.sql.go (100%) rename {db => cmd/server/db}/sqlc/error.go (100%) rename {db => cmd/server/db}/sqlc/exec_tx.go (100%) rename {db => cmd/server/db}/sqlc/main_test.go (88%) rename {db => cmd/server/db}/sqlc/models.go (100%) rename {db => cmd/server/db}/sqlc/notification.sql.go (100%) rename {db => cmd/server/db}/sqlc/querier.go (100%) rename {db => cmd/server/db}/sqlc/session.sql.go (100%) rename {db => cmd/server/db}/sqlc/store.go (100%) rename {db => cmd/server/db}/sqlc/tx_create_user.go (100%) rename {db => cmd/server/db}/sqlc/tx_verify_email.go (100%) rename {db => cmd/server/db}/sqlc/user.sql.go (100%) rename {db => cmd/server/db}/sqlc/user_test.go (100%) rename {db => cmd/server/db}/sqlc/verify_email.sql.go (100%) create mode 100644 cmd/server/db/util/connect.go create mode 100644 cmd/server/db/util/error.go create mode 100644 cmd/server/db/util/init_admin_user.go create mode 100644 cmd/server/db/util/util.go rename {docs => cmd/server/docs}/swagger/favicon-16x16.png (100%) rename {docs => cmd/server/docs}/swagger/favicon-32x32.png (100%) rename {docs => cmd/server/docs}/swagger/index.css (100%) rename {docs => cmd/server/docs}/swagger/index.html (100%) rename {docs => cmd/server/docs}/swagger/oauth2-redirect.html (100%) rename {docs => cmd/server/docs}/swagger/swagger-initializer.js (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui-bundle.js (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui-bundle.js.map (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui-es-bundle-core.js (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui-es-bundle-core.js.map (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui-es-bundle.js (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui-es-bundle.js.map (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui-standalone-preset.js (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui-standalone-preset.js.map (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui.css (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui.css.map (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui.js (100%) rename {docs => cmd/server/docs}/swagger/swagger-ui.js.map (100%) rename {docs => cmd/server/docs}/swagger/tlz.swagger.json (100%) rename {internal => cmd/server/internal}/logger/logger.go (100%) rename {internal => cmd/server/internal}/task/check_tls.go (98%) rename {internal => cmd/server/internal}/task/send_notification.go (96%) rename {internal => cmd/server/internal}/task/status.go (100%) rename {internal => cmd/server/internal}/task/task.go (69%) rename {internal => cmd/server/internal}/util/config.go (100%) rename {internal => cmd/server/internal}/util/config_defaults.go (100%) rename {internal => cmd/server/internal}/util/config_types.go (100%) rename {internal => cmd/server/internal}/util/db_connect.go (100%) rename {internal => cmd/server/internal}/validator/validator.go (100%) rename main.go => cmd/server/main.go (86%) rename {templates => cmd/server/templates}/expiry_notification.html (100%) rename {web => cmd/server/web}/.eslintrc.cjs (100%) rename {web => cmd/server/web}/.gitignore (100%) rename {web => cmd/server/web}/index.html (100%) rename {web => cmd/server/web}/package-lock.json (100%) rename {web => cmd/server/web}/package.json (100%) rename {web => cmd/server/web}/public/vite.svg (100%) rename {web => cmd/server/web}/src/AddDomainForm.jsx (100%) rename {web => cmd/server/web}/src/App.jsx (100%) rename {web => cmd/server/web}/src/DomainsTable.jsx (100%) rename {web => cmd/server/web}/src/assets/react.svg (100%) rename {web => cmd/server/web}/src/main.jsx (100%) rename {web => cmd/server/web}/vite.config.js (100%) rename {worker => cmd/server/worker}/distributor.go (100%) rename {worker => cmd/server/worker}/logger.go (100%) rename {worker => cmd/server/worker}/mock/distributor.go (100%) rename {worker => cmd/server/worker}/processor.go (100%) rename {worker => cmd/server/worker}/task_send_verify_email.go (100%) rename {worker => cmd/server/worker}/worker.go (100%) delete mode 100644 project.toml diff --git a/.editorconfig b/.editorconfig index 240c146..f914b95 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,6 @@ indent_style = space indent_size = 2 [{Makefile,go.mod,go.sum,*.go,.gitmodules}] -indent_style = tab indent_size = 4 [*.md] @@ -16,8 +15,4 @@ indent_size = 4 trim_trailing_whitespace = false [Taskfile.yaml] -indent_size = 2 indent_style = tab - -[Dockerfile] -indent_size = 4 diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..ad2015b --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,5 @@ +linters-settings: + gosec: + # To specify a set of rules to explicitly exclude. + # Available rules: https://github.com/securego/gosec#available-rules + excludes: [] diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..4e74510 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,105 @@ +--- + +project_name: tlz +before: + hooks: + - go mod tidy +builds: + - env: [CGO_ENABLED=0] + binary: tlz + goos: + - linux + goarch: + - amd64 + - arm64 + id: "cli" + dir: . + main: ./cmd/server/main.go + ldflags: + - -s -w -X main.Version={{.Version}} -X main.Commit={{.Commit}} -X main.Date={{.Date}} + +archives: + - id: cli-archive + format: tar.gz + files: + - none* + builds: + - cli + format_overrides: + - goos: windows + format: zip + name_template: >- + {{ .ProjectName }}_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} + +dockers: + - use: buildx + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/zcubbs/{{ .ProjectName }}:{{ .Version }}-amd64" + - "ghcr.io/zcubbs/{{ .ProjectName }}:latest-amd64" + build_flag_templates: + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - use: buildx + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/zcubbs/{{ .ProjectName }}:{{ .Version }}-arm64" + - "ghcr.io/zcubbs/{{ .ProjectName }}:latest-arm64" + build_flag_templates: + - "--platform=linux/arm64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" +docker_manifests: + - name_template: ghcr.io/zcubbs/{{ .ProjectName }}:{{ .Version }} + image_templates: + - ghcr.io/zcubbs/{{ .ProjectName }}:{{ .Version }}-amd64 + - ghcr.io/zcubbs/{{ .ProjectName }}:{{ .Version }}-arm64 + - name_template: ghcr.io/zcubbs/{{ .ProjectName }}:latest + image_templates: + - ghcr.io/zcubbs/{{ .ProjectName }}:latest-amd64 + - ghcr.io/zcubbs/{{ .ProjectName }}:latest-arm64 +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' + - '^conf:' +snapshot: + name_template: SNAPSHOT-{{ .Commit }} +checksum: + name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt' +signs: + - cmd: gpg + args: + - --output + - $signature + - --detach-sig + - $artifact + signature: ${artifact}.sig + artifacts: none +release: + gittlz: + owner: zcubbs + name: tlz + draft: false + prerelease: auto + header: | + ## ({{ .Date }}) + + Welcome to this new release! + footer: | + ## Thanks! + Those were the changes on {{ .Tag }}! + name_template: "{{.Tag}}" diff --git a/.gosec.config.json b/.gosec.config.json index 906beaa..fdf2ce4 100644 --- a/.gosec.config.json +++ b/.gosec.config.json @@ -1,5 +1,5 @@ { "global": { - "exclude": "G404,G402" + "exclude": "G203" } } diff --git a/Taskfile.yaml b/Taskfile.yaml index 5b6bfeb..c0acef7 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -1,12 +1,5 @@ version: '3' -includes: - bootstrap_tasks: .taskfiles/bootstrap.yaml - container_tasks: .taskfiles/containers.yaml - build_tasks: .taskfiles/build.yaml - test_tasks: .taskfiles/test.yaml - gen_tasks: .taskfiles/gen.yaml - env: GOOS: "{{OS}}" @@ -15,114 +8,67 @@ vars: LOCAL_HOST: 127.0.0.1 tasks: - - ################################################################ - # Bootstrap tasks - ################################################################ - bootstrap: - desc: Install all necessary tools and CLI dependencies - cmds: - - task: bootstrap_tasks:local - - boostrap:gh: - desc: Install all necessary tools and CLI dependencies for GitHub Actions + test: cmds: - - task: bootstrap_tasks:gh - + - go test ./... - ################################################################ - # Build tasks - ################################################################ build: cmds: - - task: build_tasks:build + - task: build:{{OS}} - build:pack: + build:windows: cmds: - - task: build_tasks:build:pack + - go env -w GOOS=windows GOARCH=amd64 + - go build -o bin/server.exe ./cmd/server/main.go - build:pack:gh: + build:darwin: cmds: - - task: build_tasks:build:pack:gh + - go env -w GOOS=darwin GOARCH=amd64 + - go build -o bin/server ./cmd/server/main.go - ################################################################ - # Test tasks - ################################################################ - lint: + build:linux: cmds: - - task: test_tasks:lint - - scan: - cmds: - - task: test_tasks:scan - - test: - cmds: - - task: test_tasks:test + - go env -w GOOS=linux GOARCH=amd64 + - go build -o bin/server ./cmd/server/main.go run: cmds: - - task: test_tasks:run + - task: build:{{OS}} + - task: run:{{OS}} + vars: + ARGS: "{{.CLI_ARGS}}" - preview: + run:darwin: cmds: - - task: test_tasks:preview - - evans: + - bin/server {{.ARGS}} + run:linux: cmds: - - task: test_tasks:evans - - ################################################################ - # Generate tasks - ################################################################ - proto: + - bin/server {{.ARGS}} + run:windows: cmds: - - task: gen_tasks:proto + - bin/server.exe {{.ARGS}} - mock: - cmds: - - task: gen_tasks:mock - - sqlc: - cmds: - - task: gen_tasks:sqlc - - - ################################################################ - # Container tasks - ################################################################ - pg: - cmds: - - task: container_tasks:pg - - pg:start: - cmds: - - task: container_tasks:pg:start - - pg:down: - cmds: - - task: container_tasks:pg:down - - redis: + lint: cmds: - - task: container_tasks:redis + - golangci-lint run ./... -v --timeout 5m - redis:start: + scan: cmds: - - task: container_tasks:redis:start + - gosec -conf .gosec.config.json "./..." - redis:down: + tools:install: + desc: Install tools cmds: - - task: container_tasks:redis:down + - task tools:install:golangci-lint + - task tools:install:gosec - mailhog: + tools:install:golangci-lint: + desc: Install golangci-lint cmds: - - task: container_tasks:mailhog + - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest - mailhog:start: + tools:install:gosec: + desc: Install gosec cmds: - - task: container_tasks:mailhog:start + - go install github.com/securego/gosec/v2/cmd/gosec@latest - mailhog:down: - cmds: - - task: container_tasks:mailhog:down diff --git a/api/authorization.go b/cmd/server/api/authorization.go similarity index 100% rename from api/authorization.go rename to cmd/server/api/authorization.go diff --git a/api/converter.go b/cmd/server/api/converter.go similarity index 89% rename from api/converter.go rename to cmd/server/api/converter.go index 1f519a2..f0a2306 100644 --- a/api/converter.go +++ b/cmd/server/api/converter.go @@ -1,7 +1,7 @@ package api import ( - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/tlz/pb" "google.golang.org/protobuf/types/known/timestamppb" ) diff --git a/api/error.go b/cmd/server/api/error.go similarity index 100% rename from api/error.go rename to cmd/server/api/error.go diff --git a/api/logger.go b/cmd/server/api/logger.go similarity index 100% rename from api/logger.go rename to cmd/server/api/logger.go diff --git a/api/main_test.go b/cmd/server/api/main_test.go similarity index 95% rename from api/main_test.go rename to cmd/server/api/main_test.go index 83f1aec..97af490 100644 --- a/api/main_test.go +++ b/cmd/server/api/main_test.go @@ -2,7 +2,7 @@ package api import ( "github.com/stretchr/testify/require" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/tlz/internal/util" "github.com/zcubbs/tlz/worker" "github.com/zcubbs/x/random" diff --git a/api/metadata.go b/cmd/server/api/metadata.go similarity index 100% rename from api/metadata.go rename to cmd/server/api/metadata.go diff --git a/api/rpc_create_user.go b/cmd/server/api/rpc_create_user.go similarity index 98% rename from api/rpc_create_user.go rename to cmd/server/api/rpc_create_user.go index 7adf3c9..ac2d1ad 100644 --- a/api/rpc_create_user.go +++ b/cmd/server/api/rpc_create_user.go @@ -3,7 +3,7 @@ package api import ( "context" "github.com/hibiken/asynq" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/tlz/internal/validator" "github.com/zcubbs/tlz/pb" "github.com/zcubbs/tlz/worker" diff --git a/api/rpc_create_user_test.go b/cmd/server/api/rpc_create_user_test.go similarity index 97% rename from api/rpc_create_user_test.go rename to cmd/server/api/rpc_create_user_test.go index 9c93571..f3b45d4 100644 --- a/api/rpc_create_user_test.go +++ b/cmd/server/api/rpc_create_user_test.go @@ -5,8 +5,8 @@ import ( "database/sql" "fmt" "github.com/stretchr/testify/require" - mockdb "github.com/zcubbs/tlz/db/mock" - db "github.com/zcubbs/tlz/db/sqlc" + mockdb "github.com/zcubbs/tlz/cmd/server/db/mock" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/tlz/pb" "github.com/zcubbs/tlz/worker" mockwk "github.com/zcubbs/tlz/worker/mock" diff --git a/api/rpc_login_user.go b/cmd/server/api/rpc_login_user.go similarity index 97% rename from api/rpc_login_user.go rename to cmd/server/api/rpc_login_user.go index 645c859..4cc1bb1 100644 --- a/api/rpc_login_user.go +++ b/cmd/server/api/rpc_login_user.go @@ -3,7 +3,7 @@ package api import ( "context" "errors" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/tlz/pb" "github.com/zcubbs/x/password" "google.golang.org/grpc/codes" diff --git a/api/rpc_ping.go b/cmd/server/api/rpc_ping.go similarity index 100% rename from api/rpc_ping.go rename to cmd/server/api/rpc_ping.go diff --git a/api/rpc_update_user.go b/cmd/server/api/rpc_update_user.go similarity index 98% rename from api/rpc_update_user.go rename to cmd/server/api/rpc_update_user.go index 9ab1cfb..5e1082d 100644 --- a/api/rpc_update_user.go +++ b/cmd/server/api/rpc_update_user.go @@ -5,7 +5,7 @@ import ( "database/sql" "errors" "github.com/jackc/pgx/v5/pgtype" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/tlz/internal/validator" "github.com/zcubbs/tlz/pb" "github.com/zcubbs/x/password" diff --git a/api/rpc_verify_user.go b/cmd/server/api/rpc_verify_user.go similarity index 96% rename from api/rpc_verify_user.go rename to cmd/server/api/rpc_verify_user.go index afa7670..d2b668f 100644 --- a/api/rpc_verify_user.go +++ b/cmd/server/api/rpc_verify_user.go @@ -3,7 +3,7 @@ package api import ( "context" "github.com/google/uuid" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/tlz/internal/validator" "github.com/zcubbs/tlz/pb" "google.golang.org/genproto/googleapis/rpc/errdetails" diff --git a/api/server.go b/cmd/server/api/server.go similarity index 98% rename from api/server.go rename to cmd/server/api/server.go index 09a2c76..d95697b 100644 --- a/api/server.go +++ b/cmd/server/api/server.go @@ -7,7 +7,7 @@ import ( "github.com/charmbracelet/log" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/rs/cors" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/tlz/internal/util" "github.com/zcubbs/tlz/pb" "github.com/zcubbs/tlz/pkg/token" diff --git a/cmd/server/config/config.go b/cmd/server/config/config.go new file mode 100644 index 0000000..3c55719 --- /dev/null +++ b/cmd/server/config/config.go @@ -0,0 +1,101 @@ +package config + +import ( + "encoding/json" + "fmt" + "github.com/charmbracelet/log" + "github.com/joho/godotenv" + "github.com/spf13/viper" + "os" + "strings" + "sync" +) + +var ( + cfg Config + onceEnv sync.Once + onceLogger sync.Once + onceConfig sync.Once +) + +var ( + Version string + Commit string + Date string +) + +func Bootstrap() Config { + onceEnv.Do(LoadEnv) + onceLogger.Do(setupLogger) + onceConfig.Do(loadConfig) + log.Info("loaded configuration") + return cfg +} + +func LoadEnv() { + err := godotenv.Load(".env") + + if err != nil { + log.Debug("no .env file found") + } +} + +func setupLogger() { + // read environment variable for log level + env := os.Getenv("ENVIRONMENT") + if env == "production" || env == "prod" { + log.SetLevel(log.InfoLevel) + log.SetFormatter(log.JSONFormatter) + } else { + log.SetLevel(log.DebugLevel) + } +} + +func loadConfig() { + for k, v := range defaults { + viper.SetDefault(k, v) + } + + for _, p := range viperConfigPaths { + viper.AddConfigPath(p) + } + + viper.SetConfigType(ViperConfigType) + viper.SetConfigName(ViperConfigName) + + err := viper.ReadInConfig() + if err != nil && viper.GetString("debug") == "true" { + log.Warn("unable to load config file", + "path", ViperConfigName+"."+ViperConfigType, + ) + } + + viper.AutomaticEnv() // read in environment variables that match + viper.SetEnvPrefix(ViperConfigEnvPrefix) + + for _, key := range allowedEnvVarKeys { + err := viper.BindEnv(key) + if err != nil { + log.Printf("error: %s", err) + } + } + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + + err = viper.Unmarshal(&cfg) + if err != nil { + log.Printf("warn: could not decode config into struct: %v", err) + } + + if viper.GetString("debug") == "true" { + debugConfig() + } +} + +func debugConfig() { + jsonConfig, err := json.MarshalIndent(&cfg, "", " ") + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("%v\n", string(jsonConfig)) +} diff --git a/cmd/server/config/defaults.go b/cmd/server/config/defaults.go new file mode 100644 index 0000000..123da22 --- /dev/null +++ b/cmd/server/config/defaults.go @@ -0,0 +1,78 @@ +package config + +const ( + ViperConfigName = "config" + ViperConfigType = "yaml" + ViperConfigEnvPrefix = "LU" + DefaultDbName = "tlz" + Localhost = "127.0.0.1" + HttpPort = 8000 + GrpcPort = 9000 +) + +var ( + viperConfigPaths = [...]string{"./config"} + + defaults = map[string]interface{}{ + "debug": false, + "http_server.port": HttpPort, + "http_server.allow_origins": "http://localhost:8000,http://localhost:5173,http://127.0.0.1:5173,http://127.0.0.1:8000", + "http_server.allow_headers": "Origin, Content-Type, Accept", + "http_server.tz": "UTC", + "http_server.enable_print_routes": false, + "http_server.read_header_timeout": "3s", + "grpc_server.port": GrpcPort, + "grpc_server.enable_reflection": true, + "grpc_server.tls.enabled": false, + "grpc_server.tls.cert": "", + "grpc_server.tls.key": "", + "auth.token_symmetric_key": "12345678901234567890123456789012", + "auth.access_token_duration": "30s", + "auth.refresh_token_duration": "15m", + "database.auto_migration": true, + "database.postgres.enabled": true, + "database.postgres.host": Localhost, + "database.postgres.port": 5432, + "database.postgres.username": "postgres", + "database.postgres.password": "postgres", + "database.postgres.db_name": DefaultDbName, + "database.postgres.ssl_mode": false, + "database.postgres.verbose": false, + "database.postgres.cert_pem": "", + "database.postgres.cert_key": "", + "database.postgres.max_conns": 10, + "database.postgres.min_conns": 4, + } + + allowedEnvVarKeys = []string{ + "debug", + "init_admin_password", + "http_server.port", + "http_server.allow_origins", + "http_server.allow_headers", + "http_server.tz", + "http_server.enable_print_routes", + "http_server.read_header_timeout", + "grpc_server.port", + "grpc_server.enable_reflection", + "grpc_server.tls.enabled", + "grpc_server.tls.cert", + "grpc_server.tls.key", + "auth.token_symmetric_key", + "auth.access_token_duration", + "auth.refresh_token_duration", + "database.auto_migration", + "database.postgres.enabled", + "database.postgres.host", + "database.postgres.port", + "database.postgres.username", + "database.postgres.password", + "database.postgres.database", + "database.postgres.ssl_mode", + "database.postgres.verbose", + "database.postgres.cert_pem", + "database.postgres.cert_key", + "database.postgres.max_conns", + "database.postgres.min_conns", + } +) diff --git a/cmd/server/config/types.go b/cmd/server/config/types.go new file mode 100644 index 0000000..ec19ec2 --- /dev/null +++ b/cmd/server/config/types.go @@ -0,0 +1,74 @@ +package config + +import "time" + +type Config struct { + Debug bool `mapstructure:"debug"` + HttpServer HttpServerConfig `mapstructure:"http_server"` + GrpcServer GrpcServerConfig `mapstructure:"grpc_server"` + Auth AuthConfig `mapstructure:"auth"` + Database DatabaseConfig `mapstructure:"database"` + InitAdminPassword string `mapstructure:"init_admin_password"` +} + +type HttpServerConfig struct { + Port int `mapstructure:"port"` + AllowOrigins string `mapstructure:"allow_origins"` + AllowHeaders string `mapstructure:"allow_headers"` + TZ string `mapstructure:"tz"` + // ReadHeaderTimeout is the amount of time allowed to read request headers. Default values: '3s' + ReadHeaderTimeout time.Duration `mapstructure:"read_header_timeout"` +} + +type GrpcServerConfig struct { + Port int `mapstructure:"port"` + EnableReflection bool `mapstructure:"enable_reflection"` + Tls TlsConfig `mapstructure:"tls"` +} + +type TlsConfig struct { + Enabled bool `mapstructure:"enabled"` + Cert string `mapstructure:"cert"` + Key string `mapstructure:"key"` +} + +type AuthConfig struct { + TokenSymmetricKey string `mapstructure:"token_symmetric_key"` + AccessTokenDuration time.Duration `mapstructure:"access_token_duration"` + RefreshTokenDuration time.Duration `mapstructure:"refresh_token_duration"` +} + +type DatabaseType string + +const ( + Postgres DatabaseType = "postgres" +) + +type DatabaseConfig struct { + AutoMigration bool `mapstructure:"auto_migration" json:"auto_migration"` + Postgres PostgresConfig `mapstructure:"postgres" json:"postgres"` +} + +func (dc *DatabaseConfig) GetDatabaseType() DatabaseType { + if dc.Postgres.Enabled { + return Postgres + } + return "" +} + +type PostgresConfig struct { + Enabled bool `mapstructure:"enabled" json:"enabled"` + Host string `mapstructure:"host" json:"host"` + Port int `mapstructure:"port" json:"port"` + Username string `mapstructure:"username" json:"username"` + Password string `mapstructure:"password" json:"password"` + DbName string `mapstructure:"db_name" json:"db_name"` + SslMode bool `mapstructure:"ssl_mode" json:"ssl_mode"` + Verbose bool `mapstructure:"verbose" json:"verbose"` + CertPem string `mapstructure:"cert_pem"` + CertKey string `mapstructure:"cert_key"` + // MaxConns is the maximum number of connections in the pool. Default value: 10 + MaxConns int32 `mapstructure:"max_conns" json:"max_conns"` + // MinConns is the minimum number of connections in the pool. Default value: 2 + MinConns int32 `mapstructure:"min_conns" json:"min_conns"` +} diff --git a/db/migrations/000001_init_schema.down.sql b/cmd/server/db/migration/000001_init_schema.down.sql similarity index 100% rename from db/migrations/000001_init_schema.down.sql rename to cmd/server/db/migration/000001_init_schema.down.sql diff --git a/db/migrations/000001_init_schema.up.sql b/cmd/server/db/migration/000001_init_schema.up.sql similarity index 100% rename from db/migrations/000001_init_schema.up.sql rename to cmd/server/db/migration/000001_init_schema.up.sql diff --git a/db/migrations/000002_add_notifications.down.sql b/cmd/server/db/migration/000002_add_notifications.down.sql similarity index 100% rename from db/migrations/000002_add_notifications.down.sql rename to cmd/server/db/migration/000002_add_notifications.down.sql diff --git a/db/migrations/000002_add_notifications.up.sql b/cmd/server/db/migration/000002_add_notifications.up.sql similarity index 100% rename from db/migrations/000002_add_notifications.up.sql rename to cmd/server/db/migration/000002_add_notifications.up.sql diff --git a/db/migrations/000003_add_users.down.sql b/cmd/server/db/migration/000003_add_users.down.sql similarity index 100% rename from db/migrations/000003_add_users.down.sql rename to cmd/server/db/migration/000003_add_users.down.sql diff --git a/db/migrations/000003_add_users.up.sql b/cmd/server/db/migration/000003_add_users.up.sql similarity index 100% rename from db/migrations/000003_add_users.up.sql rename to cmd/server/db/migration/000003_add_users.up.sql diff --git a/db/migrations/000004_add_sessions.down.sql b/cmd/server/db/migration/000004_add_sessions.down.sql similarity index 100% rename from db/migrations/000004_add_sessions.down.sql rename to cmd/server/db/migration/000004_add_sessions.down.sql diff --git a/db/migrations/000004_add_sessions.up.sql b/cmd/server/db/migration/000004_add_sessions.up.sql similarity index 100% rename from db/migrations/000004_add_sessions.up.sql rename to cmd/server/db/migration/000004_add_sessions.up.sql diff --git a/db/migrations/000005_add_domains.down.sql b/cmd/server/db/migration/000005_add_domains.down.sql similarity index 100% rename from db/migrations/000005_add_domains.down.sql rename to cmd/server/db/migration/000005_add_domains.down.sql diff --git a/db/migrations/000005_add_domains.up.sql b/cmd/server/db/migration/000005_add_domains.up.sql similarity index 100% rename from db/migrations/000005_add_domains.up.sql rename to cmd/server/db/migration/000005_add_domains.up.sql diff --git a/db/migrations/000006_add_verify_email.down.sql b/cmd/server/db/migration/000006_add_verify_email.down.sql similarity index 100% rename from db/migrations/000006_add_verify_email.down.sql rename to cmd/server/db/migration/000006_add_verify_email.down.sql diff --git a/db/migrations/000006_add_verify_email.up.sql b/cmd/server/db/migration/000006_add_verify_email.up.sql similarity index 100% rename from db/migrations/000006_add_verify_email.up.sql rename to cmd/server/db/migration/000006_add_verify_email.up.sql diff --git a/db/migrations/migrations.go b/cmd/server/db/migration/migrations.go similarity index 70% rename from db/migrations/migrations.go rename to cmd/server/db/migration/migrations.go index 769da01..13b1c7c 100644 --- a/db/migrations/migrations.go +++ b/cmd/server/db/migration/migrations.go @@ -1,4 +1,4 @@ -package migrations +package migration import ( "database/sql" @@ -6,25 +6,32 @@ import ( "errors" "fmt" "github.com/charmbracelet/log" - "github.com/golang-migrate/migrate/v4" + mig "github.com/golang-migrate/migrate/v4" "github.com/golang-migrate/migrate/v4/database/postgres" _ "github.com/golang-migrate/migrate/v4/source/file" "github.com/golang-migrate/migrate/v4/source/httpfs" _ "github.com/mattes/migrate/source/file" - "github.com/zcubbs/tlz/internal/util" + "github.com/zcubbs/tlz/cmd/server/config" + dbUtil "github.com/zcubbs/tlz/cmd/server/db/util" "net/http" ) //go:embed *.sql var migrations embed.FS -func Run(dbCfg util.DatabaseConfig) error { - conn, err := connectToDb(dbCfg) - if err != nil { - return err - } - +func Run(dbCfg config.DatabaseConfig) error { if dbCfg.Postgres.Enabled { + conn, err := dbUtil.ConnectPostgresStdLib(dbCfg.Postgres) + if err != nil { + return err + } + defer func(conn *sql.DB) { + err := conn.Close() + if err != nil { + log.Fatal("failed to close database connection", "error", err) + } + }(conn) + err = migratePostgres(conn, dbCfg.Postgres.DbName) if err != nil { return err @@ -51,7 +58,7 @@ func migratePostgres(conn *sql.DB, dbname string) error { return fmt.Errorf("failed to create migrations source: %w", err) } - m, err := migrate.NewWithInstance( + m, err := mig.NewWithInstance( "FS", source, dbname, @@ -61,20 +68,10 @@ func migratePostgres(conn *sql.DB, dbname string) error { return fmt.Errorf("failed to create migration instance: %w", err) } err = m.Up() - if err != nil && !errors.Is(err, migrate.ErrNoChange) { + if err != nil && !errors.Is(err, mig.ErrNoChange) { return fmt.Errorf("failed to apply migrations: %w", err) } log.Info("✔️ applied database migrations") return nil } - -func connectToDb(dbCfg util.DatabaseConfig) (*sql.DB, error) { - dsn := util.GetDbConnectionString(dbCfg) - db, err := sql.Open("postgres", dsn) - if err != nil { - return nil, err - } - - return db, nil -} diff --git a/db/mock/store.go b/cmd/server/db/mock/store.go similarity index 100% rename from db/mock/store.go rename to cmd/server/db/mock/store.go diff --git a/db/queries/domain.sql b/cmd/server/db/queries/domain.sql similarity index 100% rename from db/queries/domain.sql rename to cmd/server/db/queries/domain.sql diff --git a/db/queries/notification.sql b/cmd/server/db/queries/notification.sql similarity index 100% rename from db/queries/notification.sql rename to cmd/server/db/queries/notification.sql diff --git a/db/queries/session.sql b/cmd/server/db/queries/session.sql similarity index 100% rename from db/queries/session.sql rename to cmd/server/db/queries/session.sql diff --git a/db/queries/user.sql b/cmd/server/db/queries/user.sql similarity index 100% rename from db/queries/user.sql rename to cmd/server/db/queries/user.sql diff --git a/db/queries/verify_email.sql b/cmd/server/db/queries/verify_email.sql similarity index 100% rename from db/queries/verify_email.sql rename to cmd/server/db/queries/verify_email.sql diff --git a/sqlc.yaml b/cmd/server/db/sqlc.yaml similarity index 82% rename from sqlc.yaml rename to cmd/server/db/sqlc.yaml index dc47eab..c8ebd6d 100644 --- a/sqlc.yaml +++ b/cmd/server/db/sqlc.yaml @@ -1,11 +1,11 @@ version: '2' sql: - engine: "postgresql" - schema: "db/migrations/" - queries: "db/queries/" + schema: "./migration/" + queries: "./queries/" gen: go: - out: "db/sqlc" + out: "./sqlc" package: "db" sql_package: "pgx/v5" emit_json_tags: true diff --git a/db/sqlc/db.go b/cmd/server/db/sqlc/db.go similarity index 100% rename from db/sqlc/db.go rename to cmd/server/db/sqlc/db.go diff --git a/db/sqlc/domain.sql.go b/cmd/server/db/sqlc/domain.sql.go similarity index 100% rename from db/sqlc/domain.sql.go rename to cmd/server/db/sqlc/domain.sql.go diff --git a/db/sqlc/error.go b/cmd/server/db/sqlc/error.go similarity index 100% rename from db/sqlc/error.go rename to cmd/server/db/sqlc/error.go diff --git a/db/sqlc/exec_tx.go b/cmd/server/db/sqlc/exec_tx.go similarity index 100% rename from db/sqlc/exec_tx.go rename to cmd/server/db/sqlc/exec_tx.go diff --git a/db/sqlc/main_test.go b/cmd/server/db/sqlc/main_test.go similarity index 88% rename from db/sqlc/main_test.go rename to cmd/server/db/sqlc/main_test.go index 75cf9d8..692754f 100644 --- a/db/sqlc/main_test.go +++ b/cmd/server/db/sqlc/main_test.go @@ -3,7 +3,6 @@ package db import ( "context" "github.com/charmbracelet/log" - "github.com/zcubbs/tlz/db/migrations" "github.com/zcubbs/tlz/internal/logger" "github.com/zcubbs/tlz/internal/util" "os" @@ -16,7 +15,7 @@ func TestMain(m *testing.M) { config := util.Bootstrap() ctx := context.Background() // Migrate database - err := migrations.Run(config.Database) + err := migration.Run(config.Database) if err != nil { log.Fatal("failed perform database migrations", "error", err) } diff --git a/db/sqlc/models.go b/cmd/server/db/sqlc/models.go similarity index 100% rename from db/sqlc/models.go rename to cmd/server/db/sqlc/models.go diff --git a/db/sqlc/notification.sql.go b/cmd/server/db/sqlc/notification.sql.go similarity index 100% rename from db/sqlc/notification.sql.go rename to cmd/server/db/sqlc/notification.sql.go diff --git a/db/sqlc/querier.go b/cmd/server/db/sqlc/querier.go similarity index 100% rename from db/sqlc/querier.go rename to cmd/server/db/sqlc/querier.go diff --git a/db/sqlc/session.sql.go b/cmd/server/db/sqlc/session.sql.go similarity index 100% rename from db/sqlc/session.sql.go rename to cmd/server/db/sqlc/session.sql.go diff --git a/db/sqlc/store.go b/cmd/server/db/sqlc/store.go similarity index 100% rename from db/sqlc/store.go rename to cmd/server/db/sqlc/store.go diff --git a/db/sqlc/tx_create_user.go b/cmd/server/db/sqlc/tx_create_user.go similarity index 100% rename from db/sqlc/tx_create_user.go rename to cmd/server/db/sqlc/tx_create_user.go diff --git a/db/sqlc/tx_verify_email.go b/cmd/server/db/sqlc/tx_verify_email.go similarity index 100% rename from db/sqlc/tx_verify_email.go rename to cmd/server/db/sqlc/tx_verify_email.go diff --git a/db/sqlc/user.sql.go b/cmd/server/db/sqlc/user.sql.go similarity index 100% rename from db/sqlc/user.sql.go rename to cmd/server/db/sqlc/user.sql.go diff --git a/db/sqlc/user_test.go b/cmd/server/db/sqlc/user_test.go similarity index 100% rename from db/sqlc/user_test.go rename to cmd/server/db/sqlc/user_test.go diff --git a/db/sqlc/verify_email.sql.go b/cmd/server/db/sqlc/verify_email.sql.go similarity index 100% rename from db/sqlc/verify_email.sql.go rename to cmd/server/db/sqlc/verify_email.sql.go diff --git a/cmd/server/db/util/connect.go b/cmd/server/db/util/connect.go new file mode 100644 index 0000000..ffeb42c --- /dev/null +++ b/cmd/server/db/util/connect.go @@ -0,0 +1,55 @@ +package util + +import ( + "context" + "database/sql" + "errors" + "fmt" + "github.com/charmbracelet/log" + "github.com/jackc/pgx/v5/pgxpool" + "github.com/zcubbs/tlz/cmd/server/config" +) + +func Connect(ctx context.Context, config config.DatabaseConfig) (*pgxpool.Pool, error) { + if config.Postgres.Enabled { + dbConn, err := connectToPostgres(ctx, config.Postgres) + if err != nil { + return nil, fmt.Errorf("cannot connect to db: %w", err) + } + return dbConn, nil + } + + return nil, errors.New("no supported database profile enabled, please enable one (ex: postgres)") +} + +func ConnectPostgresStdLib(dbCfg config.PostgresConfig) (*sql.DB, error) { + dsn := getPostgresConnectionString(dbCfg) + db, err := sql.Open("postgres", dsn) + if err != nil { + return nil, err + } + + return db, nil +} + +func connectToPostgres(ctx context.Context, dbCfg config.PostgresConfig) (*pgxpool.Pool, error) { + dsn := getPostgresConnectionString(dbCfg) + log.Info("connecting to Postgres", + "host", dbCfg.Host, + "port", dbCfg.Port, + "user", dbCfg.Username, + "dbname", dbCfg.DbName, + ) + poolConfig, err := pgxpool.ParseConfig(dsn) + if err != nil { + return nil, err + } + poolConfig.MaxConns = dbCfg.MaxConns + poolConfig.MinConns = dbCfg.MinConns + conn, err := pgxpool.NewWithConfig(ctx, poolConfig) + if err != nil { + return nil, err + } + + return conn, nil +} diff --git a/cmd/server/db/util/error.go b/cmd/server/db/util/error.go new file mode 100644 index 0000000..b5f3adf --- /dev/null +++ b/cmd/server/db/util/error.go @@ -0,0 +1,26 @@ +package util + +import ( + "errors" + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +const ( + ForeignKeyViolation = "23503" + UniqueViolation = "23505" +) + +var ErrRecordNotFound = pgx.ErrNoRows + +var ErrUniqueViolation = &pgconn.PgError{ + Code: UniqueViolation, +} + +func ErrorCode(err error) string { + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) { + return pgErr.Code + } + return "" +} diff --git a/cmd/server/db/util/init_admin_user.go b/cmd/server/db/util/init_admin_user.go new file mode 100644 index 0000000..7ae2fd2 --- /dev/null +++ b/cmd/server/db/util/init_admin_user.go @@ -0,0 +1,58 @@ +package util + +import ( + "context" + "github.com/charmbracelet/log" + "github.com/zcubbs/tlz/cmd/server/config" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" + "github.com/zcubbs/x/password" + "github.com/zcubbs/x/random" +) + +func InitAdminUser(store db.Store, cfg config.Config) error { + // Check if the admin user already exists. + _, err := store.GetUserByUsername(context.Background(), "admin") + if err == nil { + return nil + } + + var hashedPass string + var randPass string + + // check if init password is set + if cfg.InitAdminPassword != "" { + hashedPass, err = password.Hash(cfg.InitAdminPassword) + if err != nil { + return err + } + } else { + randPass = random.String(32) + hashedPass, err = password.Hash(randPass) + if err != nil { + return err + } + } + + _, err = store.CreateUser(context.Background(), db.CreateUserParams{ + Username: "admin", + HashedPassword: hashedPass, + FullName: "Administrator", + Email: "", + //Role: pb.Role_ROLE_ADMIN.String(), + }) + if err != nil { + errCode := ErrorCode(err) + if errCode == ForeignKeyViolation || errCode == UniqueViolation { + return nil + } + return err + } + + if cfg.InitAdminPassword == "" && randPass != "" { + log.Info("Admin user created", + "username", "admin", + "password", randPass) + } + + return nil +} diff --git a/cmd/server/db/util/util.go b/cmd/server/db/util/util.go new file mode 100644 index 0000000..bbe6520 --- /dev/null +++ b/cmd/server/db/util/util.go @@ -0,0 +1,26 @@ +package util + +import ( + "fmt" + "github.com/zcubbs/tlz/cmd/server/config" +) + +func getPostgresConnectionString(dbCfg config.PostgresConfig) string { + var sslMode string + if dbCfg.SslMode { + sslMode = "enable" + } else { + sslMode = "disable" + } + dsn := fmt.Sprintf( + "host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", + dbCfg.Host, + dbCfg.Port, + dbCfg.Username, + dbCfg.Password, + dbCfg.DbName, + sslMode, + ) + + return dsn +} diff --git a/docs/swagger/favicon-16x16.png b/cmd/server/docs/swagger/favicon-16x16.png similarity index 100% rename from docs/swagger/favicon-16x16.png rename to cmd/server/docs/swagger/favicon-16x16.png diff --git a/docs/swagger/favicon-32x32.png b/cmd/server/docs/swagger/favicon-32x32.png similarity index 100% rename from docs/swagger/favicon-32x32.png rename to cmd/server/docs/swagger/favicon-32x32.png diff --git a/docs/swagger/index.css b/cmd/server/docs/swagger/index.css similarity index 100% rename from docs/swagger/index.css rename to cmd/server/docs/swagger/index.css diff --git a/docs/swagger/index.html b/cmd/server/docs/swagger/index.html similarity index 100% rename from docs/swagger/index.html rename to cmd/server/docs/swagger/index.html diff --git a/docs/swagger/oauth2-redirect.html b/cmd/server/docs/swagger/oauth2-redirect.html similarity index 100% rename from docs/swagger/oauth2-redirect.html rename to cmd/server/docs/swagger/oauth2-redirect.html diff --git a/docs/swagger/swagger-initializer.js b/cmd/server/docs/swagger/swagger-initializer.js similarity index 100% rename from docs/swagger/swagger-initializer.js rename to cmd/server/docs/swagger/swagger-initializer.js diff --git a/docs/swagger/swagger-ui-bundle.js b/cmd/server/docs/swagger/swagger-ui-bundle.js similarity index 100% rename from docs/swagger/swagger-ui-bundle.js rename to cmd/server/docs/swagger/swagger-ui-bundle.js diff --git a/docs/swagger/swagger-ui-bundle.js.map b/cmd/server/docs/swagger/swagger-ui-bundle.js.map similarity index 100% rename from docs/swagger/swagger-ui-bundle.js.map rename to cmd/server/docs/swagger/swagger-ui-bundle.js.map diff --git a/docs/swagger/swagger-ui-es-bundle-core.js b/cmd/server/docs/swagger/swagger-ui-es-bundle-core.js similarity index 100% rename from docs/swagger/swagger-ui-es-bundle-core.js rename to cmd/server/docs/swagger/swagger-ui-es-bundle-core.js diff --git a/docs/swagger/swagger-ui-es-bundle-core.js.map b/cmd/server/docs/swagger/swagger-ui-es-bundle-core.js.map similarity index 100% rename from docs/swagger/swagger-ui-es-bundle-core.js.map rename to cmd/server/docs/swagger/swagger-ui-es-bundle-core.js.map diff --git a/docs/swagger/swagger-ui-es-bundle.js b/cmd/server/docs/swagger/swagger-ui-es-bundle.js similarity index 100% rename from docs/swagger/swagger-ui-es-bundle.js rename to cmd/server/docs/swagger/swagger-ui-es-bundle.js diff --git a/docs/swagger/swagger-ui-es-bundle.js.map b/cmd/server/docs/swagger/swagger-ui-es-bundle.js.map similarity index 100% rename from docs/swagger/swagger-ui-es-bundle.js.map rename to cmd/server/docs/swagger/swagger-ui-es-bundle.js.map diff --git a/docs/swagger/swagger-ui-standalone-preset.js b/cmd/server/docs/swagger/swagger-ui-standalone-preset.js similarity index 100% rename from docs/swagger/swagger-ui-standalone-preset.js rename to cmd/server/docs/swagger/swagger-ui-standalone-preset.js diff --git a/docs/swagger/swagger-ui-standalone-preset.js.map b/cmd/server/docs/swagger/swagger-ui-standalone-preset.js.map similarity index 100% rename from docs/swagger/swagger-ui-standalone-preset.js.map rename to cmd/server/docs/swagger/swagger-ui-standalone-preset.js.map diff --git a/docs/swagger/swagger-ui.css b/cmd/server/docs/swagger/swagger-ui.css similarity index 100% rename from docs/swagger/swagger-ui.css rename to cmd/server/docs/swagger/swagger-ui.css diff --git a/docs/swagger/swagger-ui.css.map b/cmd/server/docs/swagger/swagger-ui.css.map similarity index 100% rename from docs/swagger/swagger-ui.css.map rename to cmd/server/docs/swagger/swagger-ui.css.map diff --git a/docs/swagger/swagger-ui.js b/cmd/server/docs/swagger/swagger-ui.js similarity index 100% rename from docs/swagger/swagger-ui.js rename to cmd/server/docs/swagger/swagger-ui.js diff --git a/docs/swagger/swagger-ui.js.map b/cmd/server/docs/swagger/swagger-ui.js.map similarity index 100% rename from docs/swagger/swagger-ui.js.map rename to cmd/server/docs/swagger/swagger-ui.js.map diff --git a/docs/swagger/tlz.swagger.json b/cmd/server/docs/swagger/tlz.swagger.json similarity index 100% rename from docs/swagger/tlz.swagger.json rename to cmd/server/docs/swagger/tlz.swagger.json diff --git a/internal/logger/logger.go b/cmd/server/internal/logger/logger.go similarity index 100% rename from internal/logger/logger.go rename to cmd/server/internal/logger/logger.go diff --git a/internal/task/check_tls.go b/cmd/server/internal/task/check_tls.go similarity index 98% rename from internal/task/check_tls.go rename to cmd/server/internal/task/check_tls.go index a06dfc2..bc86e2b 100644 --- a/internal/task/check_tls.go +++ b/cmd/server/internal/task/check_tls.go @@ -5,7 +5,7 @@ import ( "context" "github.com/charmbracelet/log" "github.com/jackc/pgx/v5/pgtype" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/x/tls" "text/template" "time" diff --git a/internal/task/send_notification.go b/cmd/server/internal/task/send_notification.go similarity index 96% rename from internal/task/send_notification.go rename to cmd/server/internal/task/send_notification.go index 7d9a032..a5a1a2a 100644 --- a/internal/task/send_notification.go +++ b/cmd/server/internal/task/send_notification.go @@ -3,7 +3,7 @@ package task import ( "context" "github.com/charmbracelet/log" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/x/mail" "strings" ) diff --git a/internal/task/status.go b/cmd/server/internal/task/status.go similarity index 100% rename from internal/task/status.go rename to cmd/server/internal/task/status.go diff --git a/internal/task/task.go b/cmd/server/internal/task/task.go similarity index 69% rename from internal/task/task.go rename to cmd/server/internal/task/task.go index 1ebd421..b6456d0 100644 --- a/internal/task/task.go +++ b/cmd/server/internal/task/task.go @@ -1,6 +1,6 @@ package task -import db "github.com/zcubbs/tlz/db/sqlc" +import db "github.com/zcubbs/tlz/cmd/server/db/sqlc" type Task struct { store db.Store diff --git a/internal/util/config.go b/cmd/server/internal/util/config.go similarity index 100% rename from internal/util/config.go rename to cmd/server/internal/util/config.go diff --git a/internal/util/config_defaults.go b/cmd/server/internal/util/config_defaults.go similarity index 100% rename from internal/util/config_defaults.go rename to cmd/server/internal/util/config_defaults.go diff --git a/internal/util/config_types.go b/cmd/server/internal/util/config_types.go similarity index 100% rename from internal/util/config_types.go rename to cmd/server/internal/util/config_types.go diff --git a/internal/util/db_connect.go b/cmd/server/internal/util/db_connect.go similarity index 100% rename from internal/util/db_connect.go rename to cmd/server/internal/util/db_connect.go diff --git a/internal/validator/validator.go b/cmd/server/internal/validator/validator.go similarity index 100% rename from internal/validator/validator.go rename to cmd/server/internal/validator/validator.go diff --git a/main.go b/cmd/server/main.go similarity index 86% rename from main.go rename to cmd/server/main.go index 516dd77..f731c3c 100644 --- a/main.go +++ b/cmd/server/main.go @@ -3,17 +3,22 @@ package main import ( "context" "embed" - "github.com/zcubbs/tlz/api" - "github.com/zcubbs/tlz/db/migrations" - db "github.com/zcubbs/tlz/db/sqlc" - "github.com/zcubbs/tlz/internal/logger" - "github.com/zcubbs/tlz/internal/task" - "github.com/zcubbs/tlz/internal/util" + "github.com/zcubbs/tlz/cmd/server/api" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" + "github.com/zcubbs/tlz/cmd/server/internal/logger" + "github.com/zcubbs/tlz/cmd/server/internal/task" + "github.com/zcubbs/tlz/cmd/server/internal/util" "github.com/zcubbs/tlz/worker" "github.com/zcubbs/x/cron" "github.com/zcubbs/x/mail" ) +var ( + Version = "0.0.0" + Commit = "none" + Date = "unknown" +) + //go:embed web/dist/* var webDist embed.FS @@ -34,7 +39,7 @@ func main() { ctx := context.Background() // Migrate database - err := migrations.Run(cfg.Database) + err := migration.Run(cfg.Database) if err != nil { log.Fatal("failed perform database migrations", "error", err) } diff --git a/templates/expiry_notification.html b/cmd/server/templates/expiry_notification.html similarity index 100% rename from templates/expiry_notification.html rename to cmd/server/templates/expiry_notification.html diff --git a/web/.eslintrc.cjs b/cmd/server/web/.eslintrc.cjs similarity index 100% rename from web/.eslintrc.cjs rename to cmd/server/web/.eslintrc.cjs diff --git a/web/.gitignore b/cmd/server/web/.gitignore similarity index 100% rename from web/.gitignore rename to cmd/server/web/.gitignore diff --git a/web/index.html b/cmd/server/web/index.html similarity index 100% rename from web/index.html rename to cmd/server/web/index.html diff --git a/web/package-lock.json b/cmd/server/web/package-lock.json similarity index 100% rename from web/package-lock.json rename to cmd/server/web/package-lock.json diff --git a/web/package.json b/cmd/server/web/package.json similarity index 100% rename from web/package.json rename to cmd/server/web/package.json diff --git a/web/public/vite.svg b/cmd/server/web/public/vite.svg similarity index 100% rename from web/public/vite.svg rename to cmd/server/web/public/vite.svg diff --git a/web/src/AddDomainForm.jsx b/cmd/server/web/src/AddDomainForm.jsx similarity index 100% rename from web/src/AddDomainForm.jsx rename to cmd/server/web/src/AddDomainForm.jsx diff --git a/web/src/App.jsx b/cmd/server/web/src/App.jsx similarity index 100% rename from web/src/App.jsx rename to cmd/server/web/src/App.jsx diff --git a/web/src/DomainsTable.jsx b/cmd/server/web/src/DomainsTable.jsx similarity index 100% rename from web/src/DomainsTable.jsx rename to cmd/server/web/src/DomainsTable.jsx diff --git a/web/src/assets/react.svg b/cmd/server/web/src/assets/react.svg similarity index 100% rename from web/src/assets/react.svg rename to cmd/server/web/src/assets/react.svg diff --git a/web/src/main.jsx b/cmd/server/web/src/main.jsx similarity index 100% rename from web/src/main.jsx rename to cmd/server/web/src/main.jsx diff --git a/web/vite.config.js b/cmd/server/web/vite.config.js similarity index 100% rename from web/vite.config.js rename to cmd/server/web/vite.config.js diff --git a/worker/distributor.go b/cmd/server/worker/distributor.go similarity index 100% rename from worker/distributor.go rename to cmd/server/worker/distributor.go diff --git a/worker/logger.go b/cmd/server/worker/logger.go similarity index 100% rename from worker/logger.go rename to cmd/server/worker/logger.go diff --git a/worker/mock/distributor.go b/cmd/server/worker/mock/distributor.go similarity index 100% rename from worker/mock/distributor.go rename to cmd/server/worker/mock/distributor.go diff --git a/worker/processor.go b/cmd/server/worker/processor.go similarity index 100% rename from worker/processor.go rename to cmd/server/worker/processor.go diff --git a/worker/task_send_verify_email.go b/cmd/server/worker/task_send_verify_email.go similarity index 100% rename from worker/task_send_verify_email.go rename to cmd/server/worker/task_send_verify_email.go diff --git a/worker/worker.go b/cmd/server/worker/worker.go similarity index 100% rename from worker/worker.go rename to cmd/server/worker/worker.go diff --git a/project.toml b/project.toml deleted file mode 100644 index f0a9cd9..0000000 --- a/project.toml +++ /dev/null @@ -1,3 +0,0 @@ -[ _ ] -schema-version = "0.2" -