From 559a463b5b0fc59d408b34b548bb8b2a35ee2a47 Mon Sep 17 00:00:00 2001 From: zcubbs Date: Sun, 15 Oct 2023 21:57:11 +0200 Subject: [PATCH] :fire: wip: enhance structure --- Taskfile.yaml | 70 ++++++------- cmd/server/api/main_test.go | 10 +- cmd/server/api/rpc_create_user.go | 4 +- cmd/server/api/rpc_create_user_test.go | 4 +- cmd/server/api/rpc_update_user.go | 2 +- cmd/server/api/rpc_verify_user.go | 2 +- cmd/server/api/server.go | 8 +- cmd/server/config/types.go | 54 ++++++++-- cmd/server/db/mock/store.go | 2 +- cmd/server/db/sqlc/main_test.go | 11 ++- cmd/server/internal/util/config.go | 80 --------------- cmd/server/internal/util/config_defaults.go | 93 ----------------- cmd/server/internal/util/config_types.go | 104 -------------------- cmd/server/internal/util/db_connect.go | 65 ------------ cmd/server/main.go | 20 ++-- cmd/server/worker/mock/distributor.go | 2 +- cmd/server/worker/processor.go | 2 +- cmd/server/worker/task_send_verify_email.go | 2 +- cmd/server/worker/worker.go | 6 +- proto/domain.proto | 2 +- proto/empty.proto | 7 ++ proto/rpc_create_domain.proto | 2 +- proto/rpc_create_user.proto | 2 +- proto/rpc_get_domain.proto | 0 proto/rpc_get_domains.proto | 11 +++ proto/rpc_login_user.proto | 2 +- proto/rpc_ping.proto | 8 +- proto/rpc_update_user.proto | 2 +- proto/rpc_verify_email.proto | 2 +- proto/service_tlz.proto | 23 ++++- proto/user.proto | 2 +- 31 files changed, 172 insertions(+), 432 deletions(-) delete mode 100644 cmd/server/internal/util/config.go delete mode 100644 cmd/server/internal/util/config_defaults.go delete mode 100644 cmd/server/internal/util/config_types.go delete mode 100644 cmd/server/internal/util/db_connect.go create mode 100644 proto/empty.proto delete mode 100644 proto/rpc_get_domain.proto create mode 100644 proto/rpc_get_domains.proto diff --git a/Taskfile.yaml b/Taskfile.yaml index 99d26b6..806e907 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -7,47 +7,20 @@ vars: # sqlite connection string TEST_DB_URL: "file:./db.sqlite?cache=shared&mode=rwc" LOCAL_HOST: 127.0.0.1 - GO_PACKAGE: github.com/zcubbs/linkup - GO_PACKAGE_SHORT: linkup + GO_PACKAGE: github.com/zcubbs/tlz + GO_PACKAGE_SHORT: tlz tasks: build: desc: Build Go Binaries cmds: - - go build -o ./bin/agent ./cmd/agent - go build -o ./bin/server ./cmd/server - - go build -o ./bin/cli ./cmd/cli - - build:cli: - desc: Build the CLI - cmds: - - task: build:cli:{{OS}} - - build:cli:windows: - desc: Build the CLI - cmds: - - go build -o ./bin/linkup.exe ./cmd/cli - - build:docker:server: - desc: Build the Docker image for the server - cmds: - - docker build -t server:latest -f build/server/Dockerfile . run:server: desc: Run the server cmds: - cmd: go run .\cmd\server\main.go - run:registry: - desc: Run the registry - cmds: - - cmd: go run .\cmd\registry\main.go - - run:docker:server: - desc: Run the server inside a Docker container - cmds: - - docker run -p 50051:50051 server:latest - migrate:new: desc: "Generate migration. Usage: task migrate:new -- " cmds: @@ -113,11 +86,6 @@ tasks: cmds: - cmd: sqlc generate - evans: - desc: Run Evans CLI - cmds: - - evans --host localhost --port 9000 -r repl - lint: desc: Run linter cmds: @@ -127,7 +95,6 @@ tasks: desc: Generate mocks cmds: - task: mock:server:db - - task: mock:cli:rpc mock:server:db: desc: Generate mocks for server db @@ -217,6 +184,20 @@ tasks: cmds: - scoop install gcc + containers:up: + desc: Start all containers + cmds: + - task: pg + - task: redis + - task: mailpit + + containers:down: + desc: Stop all containers + cmds: + - task: pg:stop + - task: redis:down + - task: mailpit:down + pg: desc: Start Postgres cmds: @@ -227,6 +208,25 @@ tasks: cmds: - docker stop linkup-postgres + redis: + desc: Start Redis + cmds: + - docker run --rm --name tlz-redis -p 6379:6379 -d redis:alpine + + redis:down: + desc: Stop Redis + cmds: + - docker stop tlz-redis + + mailpit: + desc: Start Mailpit + cmds: + - >- + docker run --rm -d --name tlz-mailpit + -p 1025:1025 -p 1080:1080 + -e MP_SMTP_AUTH_ACCEPT_ANY=true -e MP_SMTP_AUTH_ALLOW_INSECURE=true + axllent/mailpit + test-grpc: desc: Run grpcurl tests cmds: diff --git a/cmd/server/api/main_test.go b/cmd/server/api/main_test.go index 97af490..c99194d 100644 --- a/cmd/server/api/main_test.go +++ b/cmd/server/api/main_test.go @@ -2,24 +2,24 @@ package api import ( "github.com/stretchr/testify/require" + "github.com/zcubbs/tlz/cmd/server/config" db "github.com/zcubbs/tlz/cmd/server/db/sqlc" - "github.com/zcubbs/tlz/internal/util" - "github.com/zcubbs/tlz/worker" + "github.com/zcubbs/tlz/cmd/server/worker" "github.com/zcubbs/x/random" "testing" "time" ) func newTestServer(t *testing.T, store db.Store, taskDistributor worker.TaskDistributor) *Server { - config := util.Config{ - Auth: util.AuthConfig{ + cfg := config.Config{ + Auth: config.AuthConfig{ TokenSymmetricKey: random.String(32), AccessTokenDuration: time.Minute, RefreshTokenDuration: 5 * time.Minute, }, } - server, err := NewServer(store, taskDistributor, config) + server, err := NewServer(store, taskDistributor, cfg) require.NoError(t, err) return server diff --git a/cmd/server/api/rpc_create_user.go b/cmd/server/api/rpc_create_user.go index ac2d1ad..8837eef 100644 --- a/cmd/server/api/rpc_create_user.go +++ b/cmd/server/api/rpc_create_user.go @@ -4,9 +4,9 @@ import ( "context" "github.com/hibiken/asynq" db "github.com/zcubbs/tlz/cmd/server/db/sqlc" - "github.com/zcubbs/tlz/internal/validator" + "github.com/zcubbs/tlz/cmd/server/internal/validator" + "github.com/zcubbs/tlz/cmd/server/worker" "github.com/zcubbs/tlz/pb" - "github.com/zcubbs/tlz/worker" "github.com/zcubbs/x/password" "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc/codes" diff --git a/cmd/server/api/rpc_create_user_test.go b/cmd/server/api/rpc_create_user_test.go index f3b45d4..7487174 100644 --- a/cmd/server/api/rpc_create_user_test.go +++ b/cmd/server/api/rpc_create_user_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/require" mockdb "github.com/zcubbs/tlz/cmd/server/db/mock" db "github.com/zcubbs/tlz/cmd/server/db/sqlc" + "github.com/zcubbs/tlz/cmd/server/worker" + mockwk "github.com/zcubbs/tlz/cmd/server/worker/mock" "github.com/zcubbs/tlz/pb" - "github.com/zcubbs/tlz/worker" - mockwk "github.com/zcubbs/tlz/worker/mock" "github.com/zcubbs/x/password" "github.com/zcubbs/x/random" "go.uber.org/mock/gomock" diff --git a/cmd/server/api/rpc_update_user.go b/cmd/server/api/rpc_update_user.go index 5e1082d..b3292a9 100644 --- a/cmd/server/api/rpc_update_user.go +++ b/cmd/server/api/rpc_update_user.go @@ -6,7 +6,7 @@ import ( "errors" "github.com/jackc/pgx/v5/pgtype" db "github.com/zcubbs/tlz/cmd/server/db/sqlc" - "github.com/zcubbs/tlz/internal/validator" + "github.com/zcubbs/tlz/cmd/server/internal/validator" "github.com/zcubbs/tlz/pb" "github.com/zcubbs/x/password" "google.golang.org/genproto/googleapis/rpc/errdetails" diff --git a/cmd/server/api/rpc_verify_user.go b/cmd/server/api/rpc_verify_user.go index d2b668f..70d12e3 100644 --- a/cmd/server/api/rpc_verify_user.go +++ b/cmd/server/api/rpc_verify_user.go @@ -4,7 +4,7 @@ import ( "context" "github.com/google/uuid" db "github.com/zcubbs/tlz/cmd/server/db/sqlc" - "github.com/zcubbs/tlz/internal/validator" + "github.com/zcubbs/tlz/cmd/server/internal/validator" "github.com/zcubbs/tlz/pb" "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc/codes" diff --git a/cmd/server/api/server.go b/cmd/server/api/server.go index d95697b..e3114cf 100644 --- a/cmd/server/api/server.go +++ b/cmd/server/api/server.go @@ -7,11 +7,11 @@ import ( "github.com/charmbracelet/log" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/rs/cors" + "github.com/zcubbs/tlz/cmd/server/config" db "github.com/zcubbs/tlz/cmd/server/db/sqlc" - "github.com/zcubbs/tlz/internal/util" + "github.com/zcubbs/tlz/cmd/server/worker" "github.com/zcubbs/tlz/pb" "github.com/zcubbs/tlz/pkg/token" - "github.com/zcubbs/tlz/worker" "google.golang.org/grpc" "google.golang.org/grpc/reflection" "google.golang.org/protobuf/encoding/protojson" @@ -24,7 +24,7 @@ type Server struct { pb.UnimplementedTlzServer store db.Store tokenMaker token.Maker - cfg util.Config + cfg config.Config embedAssets []EmbedAssetsOpts taskDistributor worker.TaskDistributor } @@ -38,7 +38,7 @@ type EmbedAssetsOpts struct { } func NewServer(store db.Store, taskDistributor worker.TaskDistributor, - cfg util.Config, embedOpts ...EmbedAssetsOpts) (*Server, error) { + cfg config.Config, embedOpts ...EmbedAssetsOpts) (*Server, error) { tokenMaker, err := token.NewPasetoMaker(cfg.Auth.TokenSymmetricKey) if err != nil { return nil, fmt.Errorf("cannot create new tokenMaker: %w", err) diff --git a/cmd/server/config/types.go b/cmd/server/config/types.go index ec19ec2..5ebc720 100644 --- a/cmd/server/config/types.go +++ b/cmd/server/config/types.go @@ -3,12 +3,15 @@ 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"` + 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"` + Redis RedisConfig `mapstructure:"redis"` + Cron CronConfig `mapstructure:"cron"` + Notification NotificationConfig `mapstructure:"notification"` } type HttpServerConfig struct { @@ -72,3 +75,42 @@ type PostgresConfig struct { // MinConns is the minimum number of connections in the pool. Default value: 2 MinConns int32 `mapstructure:"min_conns" json:"min_conns"` } + +type RedisConfig struct { + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` +} + +type CronConfig struct { + CheckCertificateValidity `mapstructure:"check_certificate_validity"` + SendMailNotification `mapstructure:"send_mail_notification"` +} + +type CheckCertificateValidity struct { + Enabled bool `mapstructure:"enabled"` + CronPattern string `mapstructure:"cron_pattern"` +} + +type SendMailNotification struct { + Enabled bool `mapstructure:"enabled"` + CronPattern string `mapstructure:"cron_pattern"` +} + +type NotificationConfig struct { + Mail MailConfig `mapstructure:"mail"` + ApiDomainName string `mapstructure:"api_domain_name"` +} + +type MailConfig struct { + Smtp SmtpConfig `mapstructure:"smtp"` +} + +type SmtpConfig struct { + Enabled bool `mapstructure:"enabled"` + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + FromAddress string `mapstructure:"from_address"` + FromName string `mapstructure:"from_name"` +} diff --git a/cmd/server/db/mock/store.go b/cmd/server/db/mock/store.go index 719e984..986dc2c 100644 --- a/cmd/server/db/mock/store.go +++ b/cmd/server/db/mock/store.go @@ -9,7 +9,7 @@ import ( reflect "reflect" uuid "github.com/google/uuid" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" gomock "go.uber.org/mock/gomock" ) diff --git a/cmd/server/db/sqlc/main_test.go b/cmd/server/db/sqlc/main_test.go index 692754f..7e71b6c 100644 --- a/cmd/server/db/sqlc/main_test.go +++ b/cmd/server/db/sqlc/main_test.go @@ -3,8 +3,9 @@ package db import ( "context" "github.com/charmbracelet/log" - "github.com/zcubbs/tlz/internal/logger" - "github.com/zcubbs/tlz/internal/util" + "github.com/zcubbs/tlz/cmd/server/config" + "github.com/zcubbs/tlz/cmd/server/db/migration" + "github.com/zcubbs/tlz/cmd/server/db/util" "os" "testing" ) @@ -12,14 +13,14 @@ import ( var testStore Store func TestMain(m *testing.M) { - config := util.Bootstrap() + cfg := config.Bootstrap() ctx := context.Background() // Migrate database - err := migration.Run(config.Database) + err := migration.Run(cfg.Database) if err != nil { log.Fatal("failed perform database migrations", "error", err) } - conn, err := util.DbConnect(ctx, config.Database, logger.GetLogger()) + conn, err := util.Connect(ctx, cfg.Database) if err != nil { log.Fatal("failed to connect to database", "error", err) } diff --git a/cmd/server/internal/util/config.go b/cmd/server/internal/util/config.go deleted file mode 100644 index 5fa68ed..0000000 --- a/cmd/server/internal/util/config.go +++ /dev/null @@ -1,80 +0,0 @@ -package util - -import ( - "github.com/charmbracelet/log" - "github.com/joho/godotenv" - "github.com/spf13/viper" - "os" - "strings" - "sync" -) - -var ( - config Config - onceEnv sync.Once - onceLogger sync.Once - onceConfig sync.Once -) - -func Bootstrap() Config { - onceEnv.Do(LoadEnv) - onceLogger.Do(setupLogger) - onceConfig.Do(loadConfig) - log.Info("loaded configuration") - return config -} - -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(&config) - if err != nil { - log.Printf("warn: could not decode config into struct: %v", err) - } -} diff --git a/cmd/server/internal/util/config_defaults.go b/cmd/server/internal/util/config_defaults.go deleted file mode 100644 index 7138b17..0000000 --- a/cmd/server/internal/util/config_defaults.go +++ /dev/null @@ -1,93 +0,0 @@ -package util - -import "fmt" - -const ( - ViperConfigName = "config" - ViperConfigType = "yaml" - ViperConfigEnvPrefix = "TLZ" - 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, - "auth.token_symmetric_key": "12345678901234567890123456789012", - "auth.access_token_duration": "15m", - "auth.refresh_token_duration": "24h", - "database.auto_migration": false, - "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, - "redis.host": Localhost, - "redis.port": 6379, - "cron.check_certificate_validity.enabled": true, - "cron.check_certificate_validity.cron_pattern": "*/10 * * * * *", - "cron.send_mail_notification.enabled": true, - "cron.send_mail_notification.cron_pattern": "*/10 * * * * *", - "notification.api_domain_name": fmt.Sprintf("http://%s:%d", Localhost, HttpPort), - "notification.mail.smtp.enabled": true, - "notification.mail.smtp.host": Localhost, - "notification.mail.smtp.port": 1025, - "notification.mail.smtp.username": "", - "notification.mail.smtp.password": "", - "notification.mail.smtp.from_address": "no-reply@localhost", - "notification.mail.smtp.from_name": "TLZ", - } - - allowedEnvVarKeys = []string{ - "debug", - "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", - "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.sqlite.enabled", - "database.sqlite.db_name", - "redis.host", - "redis.port", - "cron.check_certificate_validity.enabled", - "cron.check_certificate_validity.cron_pattern", - "cron.send_mail_notification.enabled", - "cron.send_mail_notification.cron_pattern", - "notification.api_domain_name", - "notification.mail.smtp.enabled", - "notification.mail.smtp.host", - "notification.mail.smtp.port", - "notification.mail.smtp.username", - "notification.mail.smtp.password", - "notification.mail.smtp.from_address", - "notification.mail.smtp.from_name", - } -) diff --git a/cmd/server/internal/util/config_types.go b/cmd/server/internal/util/config_types.go deleted file mode 100644 index 90fba19..0000000 --- a/cmd/server/internal/util/config_types.go +++ /dev/null @@ -1,104 +0,0 @@ -package util - -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"` - Redis RedisConfig `mapstructure:"redis"` - Cron CronConfig `mapstructure:"cron"` - Notification NotificationConfig `mapstructure:"notification"` -} - -type HttpServerConfig struct { - Port int `mapstructure:"port"` - AllowOrigins string `mapstructure:"allow_origins"` - AllowHeaders string `mapstructure:"allow_headers"` - TZ string `mapstructure:"tz"` - EnablePrintRoutes bool `mapstructure:"enable_print_routes"` - // 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"` -} - -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"` -} - -type RedisConfig struct { - Host string `mapstructure:"host"` - Port int `mapstructure:"port"` -} - -type CronConfig struct { - CheckCertificateValidity `mapstructure:"check_certificate_validity"` - SendMailNotification `mapstructure:"send_mail_notification"` -} - -type CheckCertificateValidity struct { - Enabled bool `mapstructure:"enabled"` - CronPattern string `mapstructure:"cron_pattern"` -} - -type SendMailNotification struct { - Enabled bool `mapstructure:"enabled"` - CronPattern string `mapstructure:"cron_pattern"` -} - -type NotificationConfig struct { - Mail MailConfig `mapstructure:"mail"` - ApiDomainName string `mapstructure:"api_domain_name"` -} - -type MailConfig struct { - Smtp SmtpConfig `mapstructure:"smtp"` -} - -type SmtpConfig struct { - Enabled bool `mapstructure:"enabled"` - Host string `mapstructure:"host"` - Port int `mapstructure:"port"` - Username string `mapstructure:"username"` - Password string `mapstructure:"password"` - FromAddress string `mapstructure:"from_address"` - FromName string `mapstructure:"from_name"` -} diff --git a/cmd/server/internal/util/db_connect.go b/cmd/server/internal/util/db_connect.go deleted file mode 100644 index f796f41..0000000 --- a/cmd/server/internal/util/db_connect.go +++ /dev/null @@ -1,65 +0,0 @@ -package util - -import ( - "context" - "errors" - "fmt" - "github.com/jackc/pgx/v5/pgxpool" - "github.com/zcubbs/logwrapper/logger" -) - -func DbConnect(ctx context.Context, config DatabaseConfig, logger logger.Logger) (*pgxpool.Pool, error) { - if config.Postgres.Enabled { - dbConn, err := connectToPostgres(ctx, config.Postgres, logger) - 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 connectToPostgres(ctx context.Context, dbCfg PostgresConfig, logger logger.Logger) (*pgxpool.Pool, error) { - dsn := getPostgresConnectionString(dbCfg) - logger.Info("connecting to Postgres", - "host", dbCfg.Host, - "port", dbCfg.Port, - "user", dbCfg.Username, - "dbname", dbCfg.DbName, - ) - conn, err := pgxpool.New(ctx, dsn) - if err != nil { - return nil, err - } - - return conn, nil -} - -func GetDbConnectionString(config DatabaseConfig) string { - if config.Postgres.Enabled { - return getPostgresConnectionString(config.Postgres) - } - - return "" -} - -func getPostgresConnectionString(dbCfg 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/cmd/server/main.go b/cmd/server/main.go index f731c3c..3fa2967 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -4,11 +4,13 @@ import ( "context" "embed" "github.com/zcubbs/tlz/cmd/server/api" + "github.com/zcubbs/tlz/cmd/server/config" + "github.com/zcubbs/tlz/cmd/server/db/migration" db "github.com/zcubbs/tlz/cmd/server/db/sqlc" + dbUtil "github.com/zcubbs/tlz/cmd/server/db/util" "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/tlz/cmd/server/worker" "github.com/zcubbs/x/cron" "github.com/zcubbs/x/mail" ) @@ -25,11 +27,15 @@ var webDist embed.FS //go:embed docs/swagger/* var swaggerDist embed.FS -var cfg util.Config +var cfg config.Config func init() { - // Bootstrap configuration - cfg = util.Bootstrap() + // Load configuration + cfg = config.Bootstrap() + + config.Version = Version + config.Commit = Commit + config.Date = Date } func main() { @@ -45,7 +51,7 @@ func main() { } // Connect to database with pgx pool - conn, err := util.DbConnect(ctx, cfg.Database, log) + conn, err := dbUtil.Connect(ctx, cfg.Database) if err != nil { log.Fatal("failed to connect to database", "error", err) } @@ -96,7 +102,7 @@ func main() { gs.StartGrpcServer() } -func startCronJobs(store db.Store, cfg util.CronConfig) { +func startCronJobs(store db.Store, cfg config.CronConfig) { t := task.New(store) if cfg.CheckCertificateValidity.Enabled { cj := cron.NewJob( diff --git a/cmd/server/worker/mock/distributor.go b/cmd/server/worker/mock/distributor.go index e6e2a97..1b96265 100644 --- a/cmd/server/worker/mock/distributor.go +++ b/cmd/server/worker/mock/distributor.go @@ -9,7 +9,7 @@ import ( reflect "reflect" asynq "github.com/hibiken/asynq" - worker "github.com/zcubbs/tlz/worker" + worker "github.com/zcubbs/tlz/cmd/server/worker" gomock "go.uber.org/mock/gomock" ) diff --git a/cmd/server/worker/processor.go b/cmd/server/worker/processor.go index 4a19f19..57c548f 100644 --- a/cmd/server/worker/processor.go +++ b/cmd/server/worker/processor.go @@ -4,7 +4,7 @@ import ( "context" "github.com/charmbracelet/log" "github.com/hibiken/asynq" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/x/mail" ) diff --git a/cmd/server/worker/task_send_verify_email.go b/cmd/server/worker/task_send_verify_email.go index 33f9d0c..2da61ad 100644 --- a/cmd/server/worker/task_send_verify_email.go +++ b/cmd/server/worker/task_send_verify_email.go @@ -9,7 +9,7 @@ import ( "github.com/charmbracelet/log" "github.com/google/uuid" "github.com/hibiken/asynq" - db "github.com/zcubbs/tlz/db/sqlc" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/x/mail" "github.com/zcubbs/x/random" ) diff --git a/cmd/server/worker/worker.go b/cmd/server/worker/worker.go index 155fb46..4cea8f0 100644 --- a/cmd/server/worker/worker.go +++ b/cmd/server/worker/worker.go @@ -4,8 +4,8 @@ import ( "fmt" "github.com/charmbracelet/log" "github.com/hibiken/asynq" - db "github.com/zcubbs/tlz/db/sqlc" - "github.com/zcubbs/tlz/internal/util" + "github.com/zcubbs/tlz/cmd/server/config" + db "github.com/zcubbs/tlz/cmd/server/db/sqlc" "github.com/zcubbs/x/mail" ) @@ -21,7 +21,7 @@ type Attributes struct { ApiDomainName string } -func New(cfg util.Config, store db.Store, mailer mail.Mailer, attributes Attributes) *Worker { +func New(cfg config.Config, store db.Store, mailer mail.Mailer, attributes Attributes) *Worker { redisOpt := asynq.RedisClientOpt{ Addr: fmt.Sprintf("%s:%d", cfg.Redis.Host, cfg.Redis.Port), } diff --git a/proto/domain.proto b/proto/domain.proto index 5309a7b..9c99ee8 100644 --- a/proto/domain.proto +++ b/proto/domain.proto @@ -4,7 +4,7 @@ package pb; import "google/protobuf/timestamp.proto"; -option go_package = "github.com/zcubbs/tlz/pb"; +option go_package = "github.com/zcubbs/tlz"; message Domain { string name = 1; diff --git a/proto/empty.proto b/proto/empty.proto new file mode 100644 index 0000000..8a1a0cc --- /dev/null +++ b/proto/empty.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package pb; + +option go_package = "github.com/zcubbs/tlz"; + +message Empty {} diff --git a/proto/rpc_create_domain.proto b/proto/rpc_create_domain.proto index af7c384..9cd8642 100644 --- a/proto/rpc_create_domain.proto +++ b/proto/rpc_create_domain.proto @@ -4,7 +4,7 @@ package pb; import "domain.proto"; -option go_package = "github.com/zcubbs/tlz/pb"; +option go_package = "github.com/zcubbs/tlz"; message CreateDomainRequest { string name = 1; diff --git a/proto/rpc_create_user.proto b/proto/rpc_create_user.proto index 70bc409..fd1c1d4 100644 --- a/proto/rpc_create_user.proto +++ b/proto/rpc_create_user.proto @@ -4,7 +4,7 @@ package pb; import "user.proto"; -option go_package = "github.com/zcubbs/tlz/pb"; +option go_package = "github.com/zcubbs/tlz"; message CreateUserRequest { string username = 1; diff --git a/proto/rpc_get_domain.proto b/proto/rpc_get_domain.proto deleted file mode 100644 index e69de29..0000000 diff --git a/proto/rpc_get_domains.proto b/proto/rpc_get_domains.proto new file mode 100644 index 0000000..2f758be --- /dev/null +++ b/proto/rpc_get_domains.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package pb; + +import "domain.proto"; + +option go_package = "github.com/zcubbs/tlz"; + +message GetDomainsResponse { + repeated Domain domains = 1; +} diff --git a/proto/rpc_login_user.proto b/proto/rpc_login_user.proto index fb3f336..8ddbac8 100644 --- a/proto/rpc_login_user.proto +++ b/proto/rpc_login_user.proto @@ -5,7 +5,7 @@ package pb; import "user.proto"; import "google/protobuf/timestamp.proto"; -option go_package = "github.com/zcubbs/tlz/pb"; +option go_package = "github.com/zcubbs/tlz"; message LoginUserRequest { string username = 1; diff --git a/proto/rpc_ping.proto b/proto/rpc_ping.proto index bc1cad8..8aac38b 100644 --- a/proto/rpc_ping.proto +++ b/proto/rpc_ping.proto @@ -2,10 +2,12 @@ syntax = "proto3"; package pb; -option go_package = "github.com/zcubbs/tlz/pb"; - -message PingRequest {} +option go_package = "github.com/zcubbs/tlz"; message PingResponse { string message = 1; + string version = 2; + string commit = 3; + string buildTime = 4; } + diff --git a/proto/rpc_update_user.proto b/proto/rpc_update_user.proto index 8e5fbd2..ac2edd8 100644 --- a/proto/rpc_update_user.proto +++ b/proto/rpc_update_user.proto @@ -4,7 +4,7 @@ package pb; import "user.proto"; -option go_package = "github.com/zcubbs/tlz/pb"; +option go_package = "github.com/zcubbs/tlz"; message UpdateUserRequest { string username = 1; diff --git a/proto/rpc_verify_email.proto b/proto/rpc_verify_email.proto index efd0147..1e97670 100644 --- a/proto/rpc_verify_email.proto +++ b/proto/rpc_verify_email.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package pb; -option go_package = "github.com/zcubbs/tlz/pb"; +option go_package = "github.com/zcubbs/tlz"; message VerifyEmailRequest { string email_id = 1; diff --git a/proto/service_tlz.proto b/proto/service_tlz.proto index f311ef6..383eab7 100644 --- a/proto/service_tlz.proto +++ b/proto/service_tlz.proto @@ -3,20 +3,22 @@ syntax = "proto3"; package pb; import "google/api/annotations.proto"; +import "protoc-gen-openapiv2/options/annotations.proto"; import "rpc_create_user.proto"; import "rpc_update_user.proto"; import "rpc_login_user.proto"; import "rpc_verify_email.proto"; -import "rpc_ping.proto"; import "rpc_create_domain.proto"; -import "protoc-gen-openapiv2/options/annotations.proto"; +import "rpc_get_domains.proto"; +import "rpc_ping.proto"; +import "empty.proto"; -option go_package = "github.com/zcubbs/tlz/pb"; +option go_package = "github.com/zcubbs/tlz"; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { info: { title: "TLZ API"; - version: "1.0.1"; + version: "0.1.0"; contact: { name: "TLZ API"; url: "https://github.com/zcubbs/tlz"; @@ -66,11 +68,12 @@ service Tlz { }; } - rpc Ping(PingRequest) returns (PingResponse) { + rpc Ping (Empty) returns (PingResponse){ option (google.api.http) = { get: "/v1/ping" }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: "Ops" summary: "Ping the server"; description: "Ping the server"; }; @@ -86,4 +89,14 @@ service Tlz { description: "Create a new domain for a user"; }; } + + rpc GetDomains(Empty) returns (GetDomainsResponse) { + option (google.api.http) = { + get: "/v1/get_domains" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Get domains"; + description: "Get domains for a user"; + }; + } } diff --git a/proto/user.proto b/proto/user.proto index 48afa2f..6b3ee39 100644 --- a/proto/user.proto +++ b/proto/user.proto @@ -4,7 +4,7 @@ package pb; import "google/protobuf/timestamp.proto"; -option go_package = "github.com/zcubbs/tlz/pb"; +option go_package = "github.com/zcubbs/tlz"; message User { string username = 1;