package main import ( "context" "os" "strings" swagger "github.com/arsmn/fiber-swagger/v2" "github.com/gofiber/fiber/v2" "github.com/google/uuid" "github.com/jackc/pgx/v4/pgxpool" "github.com/joho/godotenv" "gitlab.larvit.se/power-plan/auth/src/db" h "gitlab.larvit.se/power-plan/auth/src/handlers" "gitlab.larvit.se/power-plan/auth/src/utils" "go.uber.org/zap" // docs are generated by Swag CLI, you have to import them. _ "gitlab.larvit.se/power-plan/auth/src/docs" ) // Don't put in utils, because it creates import cycle with db... just left it here for now func createAdminAccount(Db db.Db, log *zap.SugaredLogger) { adminAccountID, uuidErr := uuid.NewRandom() if uuidErr != nil { log.Fatal("Could not create new Uuid", "err", uuidErr.Error()) } _, adminAccountErr := Db.AccountCreate(db.AccountCreateInput{ ID: adminAccountID, Name: "admin", APIKey: os.Getenv("ADMIN_API_KEY"), Password: "", Fields: []db.AccountCreateInputFields{{Name: "role", Values: []string{"admin"}}}, }) if adminAccountErr != nil && strings.HasPrefix(adminAccountErr.Error(), "ERROR: duplicate key") { log.Info("Admin account already created, nothing written to database") } else if adminAccountErr != nil { log.Fatal("Could not create admin account", "err", adminAccountErr.Error()) } } // @title JWT Auth API // @version 0.1 // @description This is a tiny http API for auth. Register accounts, auth with api-key or name/password, renew JWT tokens... // @contact.name Power Plan // @contact.url https://pwrpln.com/ // @contact.email lilleman@larvit.se // @license.name MIT // @BasePath / func main() { log := utils.GetLog() err := godotenv.Load() if err != nil { log.Warn("Error loading .env file, this could be ok if the env file does not exist", "err", err.Error()) } if os.Getenv("JWT_SHARED_SECRET") == "changeMe" { log.Fatal("You must change JWT_SHARED_SECRET in .env") } if os.Getenv("ADMIN_API_KEY") == "changeMe" { log.Fatal("You must change ADMIN_API_KEY in .env") } jwtKey := []byte(os.Getenv("JWT_SHARED_SECRET")) dbPool, err := pgxpool.Connect(context.Background(), os.Getenv("DATABASE_URL")) if err != nil { log.Fatal("Failed to open DB connection", "err", err.Error()) } else { log.Info("Connected to PostgreSQL database") } defer dbPool.Close() app := fiber.New() Db := db.Db{DbPool: dbPool, Log: log} handlers := h.Handlers{Db: Db, JwtKey: jwtKey, Log: log} createAdminAccount(Db, log) // Log all requests app.Use(handlers.LogReq) // Always require application/json app.Use(handlers.RequireJSON) app.Get("/", func(c *fiber.Ctx) error { return c.Redirect("/swagger/index.html") }) app.Get("/swagger", func(c *fiber.Ctx) error { return c.Redirect("/swagger/index.html") }) app.Get("/swagger/*", swagger.Handler) app.Delete("/account/:accountID", handlers.AccountDel) app.Get("/account/:accountID", handlers.AccountGet) app.Post("/account", handlers.AccountCreate) app.Post("/auth/api-key", handlers.AccountAuthAPIKey) app.Post("/auth/password", handlers.AccountAuthPassword) app.Post("/renew-token", handlers.RenewToken) log.Info("Trying to start web server", "WEB_BIND_HOST", os.Getenv("WEB_BIND_HOST")) if err := app.Listen(os.Getenv("WEB_BIND_HOST")); err != nil { log.Fatal("Could not start web server", "err", err.Error()) } log.Info("Webb server closed, shutting down") }