- build: somewhat polished dockerization setup - build: io/fs migrations with `golang-migrate` - feat: automatic init. admin account creation (.env creds) - feat(routers): combined user & token routers into single auth router - feat(routers): improved route layouts (`Routes`) - feat(middlewares): removed redundant `userCtx` middleware - fix(schema): note <-> note_versions relation (versioning) - feat(queries): removed redundant rollback functionality - feat(queries): combined duplicate version check & insertion/creation - tests: decreased redundancy by removing 'unnecessary' unit tests - refactor: hid internal packages behind `server/internal` - docs: notes & auth handler comments
93 lines
2.5 KiB
Go
93 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"embed"
|
|
"fmt"
|
|
"os"
|
|
|
|
"git.umbrella.haus/ae/notatest/internal/data"
|
|
"git.umbrella.haus/ae/notatest/internal/service"
|
|
"github.com/caarlos0/env/v10"
|
|
"github.com/golang-migrate/migrate/v4"
|
|
_ "github.com/golang-migrate/migrate/v4/database/postgres"
|
|
"github.com/golang-migrate/migrate/v4/source/iofs"
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/rs/zerolog"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
//go:embed sql/migrations/*.sql
|
|
var migrationsFS embed.FS
|
|
|
|
var (
|
|
config Config
|
|
)
|
|
|
|
type Config struct {
|
|
JWTSecret string `env:"JWT_SECRET,notEmpty"`
|
|
DatabaseURL string `env:"DB_URL,notEmpty"`
|
|
LogLevel string `env:"LOG_LEVEL" envDefault:"info"`
|
|
AdminUsername string `env:"ADMIN_USERNAME,notEmpty,unset"`
|
|
AdminPassword string `env:"ADMIN_PASSWORD,notEmpty,unset"`
|
|
}
|
|
|
|
func init() {
|
|
config = Config{}
|
|
if err := env.Parse(&config); err != nil {
|
|
log.Fatal().Err(err).Msg("Failed to parse environment variables")
|
|
}
|
|
initLogger()
|
|
log.Debug().Msg("Initialization completed")
|
|
}
|
|
|
|
func main() {
|
|
log.Debug().Msgf("Database URL: %s", config.DatabaseURL)
|
|
conn, err := pgx.Connect(context.Background(), config.DatabaseURL)
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("Failed to connect to database")
|
|
}
|
|
log.Info().Msg("Successfully connected to the database")
|
|
log.Info().Msg("Applying migrations...")
|
|
|
|
d, err := iofs.New(migrationsFS, "sql/migrations")
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("Failed constructing io/fs driver")
|
|
}
|
|
migrator, err := migrate.NewWithSourceInstance("iofs", d, config.DatabaseURL)
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("Failed to apply migrations")
|
|
}
|
|
defer migrator.Close()
|
|
|
|
if err := migrator.Up(); err != nil && err != migrate.ErrNoChange {
|
|
log.Fatal().Err(err).Msg("Failed to apply migrations")
|
|
}
|
|
|
|
q := data.New(conn)
|
|
err = service.CreateAdminIfNotExists(context.Background(), q, config.AdminUsername, config.AdminPassword)
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("Failed initial admin account creation")
|
|
}
|
|
|
|
log.Info().Msg("Migrations applied succesfully, proceeding to HTTP server startup")
|
|
service.Run(conn, q, config.JWTSecret)
|
|
}
|
|
|
|
func initLogger() {
|
|
fmt.Println(config.LogLevel)
|
|
level, err := zerolog.ParseLevel(config.LogLevel)
|
|
if err != nil {
|
|
level = zerolog.InfoLevel
|
|
}
|
|
zerolog.SetGlobalLevel(level)
|
|
|
|
output := zerolog.ConsoleWriter{
|
|
Out: os.Stdout,
|
|
TimeFormat: "2006-01-02 15:04:05",
|
|
}
|
|
log.Logger = log.Output(output).With().Timestamp().Caller().Logger()
|
|
|
|
log.Info().Msgf("Logger initialized (log level: %s)", level)
|
|
}
|