package main import ( "context" "log" "regexp" "strings" "time" jwtware "github.com/gofiber/contrib/jwt" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/limiter" "github.com/golang-jwt/jwt/v5" "github.com/jackc/pgx/v5/pgxpool" "nim.jasinco.work/app/internal" "nim.jasinco.work/app/internal/handlers" "nim.jasinco.work/app/nimdb" ) func main() { err := internal.ReadFromENV() if err != nil { log.Fatal(err.Error()) } dbpool, err := pgxpool.New(context.Background(), internal.POSTGRES_URL) if err != nil { log.Fatal("Failed to open connection to db") } defer dbpool.Close() internal.POOL = dbpool internal.NIMDB = nimdb.New(dbpool) if internal.IGAPI_ACTIVATE { conn, client := internal.IGAPI_establish() defer conn.Close() go internal.IGAPI_chan_exec(client) } app := fiber.New(fiber.Config{Prefork: internal.PREFORK}) app.Static("/", "./static/webpage/") app.Use(limiter.New(limiter.Config{ Next: func(c *fiber.Ctx) bool { return c.IP() == "127.0.0.1" }, Max: 50, Expiration: 30 * time.Second, KeyGenerator: func(c *fiber.Ctx) string { return c.Get("x-forwarded-for") }, LimitReached: func(c *fiber.Ctx) error { return c.SendFile("./toofast.html") }, })) if len(internal.CORS_ALLOW) > 0 { app.Use(cors.New(cors.Config{ AllowOrigins: internal.CORS_ALLOW, AllowCredentials: true, })) } app.Get("/api/post", handlers.Fetch_post) app.Post("/api/post", handlers.Insert_Post) app.Delete("/api/post", handlers.Delete_post) app.Get("/api/heart", handlers.Add_heart) app.Static("/static", "./static/") app.Get("/admin", func(c *fiber.Ctx) error { return c.Redirect("/admin/login") }) app.Post("/api/admin/login", func(c *fiber.Ctx) error { token, err := handlers.Admin_Login_JWT(c) if err != nil { return err } return c.JSON(fiber.Map{"token": *token}) }) app.Post("/admin/login", func(c *fiber.Ctx) error { _, err := handlers.Admin_Login_JWT(c) if err != nil { return err } return c.Redirect("/admin/panel") }) app.Static("/admin/login", "./admin/login", fiber.Static{Index: "index.html"}) app.Use(jwtware.New(jwtware.Config{ SigningKey: jwtware.SigningKey{Key: []byte(internal.JWT_SECRET)}, TokenLookup: "cookie:token", ErrorHandler: func(ctx *fiber.Ctx, err error) error { webpanel, regxerr := regexp.Match("^/admin/.*", []byte(ctx.Path())) if regxerr == nil && webpanel { return ctx.Redirect("/admin/login") } else if regxerr != nil { log.Printf("RegErr %s\n", regxerr.Error()) } if !strings.ContainsAny(ctx.Path(), "admin") { return ctx.SendStatus(404) } if err == jwtware.ErrJWTMissingOrMalformed { return ctx.Status(400).SendString(err.Error()) } if err == jwtware.ErrJWTAlg { return ctx.Status(401).SendString(err.Error()) } return nil }, })) app.Static("/admin/panel", "./admin/panel", fiber.Static{Index: "index.html"}) app.Use("/admin/create", func(c *fiber.Ctx) error { user := c.Locals("user").(*jwt.Token) claims := user.Claims.(jwt.MapClaims) super := claims["admin"].(bool) if !super { return c.SendStatus(fiber.StatusNotFound) } return c.Next() }) app.Static("/admin/create", "./admin/create", fiber.Static{Index: "index.html"}) app.Get("/api/admin/new_totp", handlers.Admin_new_totp_code) app.Get("/api/admin/fetch_post", handlers.Admin_Fetch_Post) app.Put("/api/admin/verify_post", handlers.AdminVerify) app.Post("/api/admin/create", handlers.Admin_create) log.Panic(app.Listen(":3000")) }