package main
import (
"fmt"
"path"
"strings"
"time"
"immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/api"
"immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/db"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/jloup/utils"
)
var log = utils.StandardL().WithField("module", "api")
type AppConfig struct {
PublicDir string `toml:"public_dir"`
}
type ApiConfig struct {
Domain string `toml:"domain"`
JwtSecret string `toml:"jwt_secret"`
}
type Config struct {
App AppConfig
Api ApiConfig
Db db.DBConfig
Redis db.RedisConfig
utils.LogConfiguration
Address string
Port string
Mode string
}
func (c *Config) SetToDefaults() {
*c = Config{
Address: "localhost",
Port: "8000",
Mode: "dev",
App: AppConfig{
PublicDir: "./public",
},
Api: ApiConfig{
JwtSecret: "secret",
},
}
c.LogConfiguration.SetToDefaults()
}
var C Config
func init() {
utils.MustParseStdConfigFile(&C)
err := utils.ConfigureStdLogger(C.LogConfiguration)
if err != nil {
panic(err)
}
api.SetJwtSecretKey(C.Api.JwtSecret)
db.Init(C.Db, C.Redis)
if C.Mode == "production" {
gin.SetMode(gin.ReleaseMode)
}
log.Infof("CONFIG:")
log.Infof("LISTEN: %s", strings.Join([]string{C.Address, C.Port}, ":"))
log.Infof("PUBLIC_DIR: %s", C.App.PublicDir)
}
func SetApiRoute(router *gin.RouterGroup, route api.Route) {
switch route.Method {
case "GET":
router.GET(route.Path, route.Handlers...)
case "POST":
router.POST(route.Path, route.Handlers...)
case "OPTIONS":
router.OPTIONS(route.Path, route.Handlers...)
default:
panic(fmt.Errorf("%s method not handled", route.Method))
}
}
func SetGroup(router *gin.RouterGroup, group api.Group) {
var r *gin.RouterGroup
if group.Root == "" {
r = router
} else {
r = router.Group(group.Root)
}
if group.Middlewares != nil {
for _, middleware := range group.Middlewares {
r.Use(api.M(middleware))
}
}
for _, route := range group.Routes {
SetApiRoute(r, route)
}
}
func main() {
engine := gin.New()
apiGroup := engine.Group("/api")
appGroup := engine
engine.Use(gin.Recovery())
if C.Mode == "production" {
engine.Use(api.Logger())
apiGroup.Use(api.Logger())
} else {
engine.Use(gin.Logger())
apiGroup.Use(gin.Logger())
}
apiGroup.Use(cors.New(cors.Config{
AllowOrigins: []string{fmt.Sprintf("https://%s", C.Api.Domain)},
AllowMethods: []string{"POST", "GET", "OPTIONS"},
AllowHeaders: []string{"Authorization"},
ExposeHeaders: []string{"Authorization"},
AllowCredentials: true,
MaxAge: 12 * time.Hour,
}))
for _, group := range api.Groups {
SetGroup(apiGroup, group)
}
appGroup.Static("/public", C.App.PublicDir)
availableRoutes := []string{
"/",
"/signup",
"/signin",
"/signout",
"/me",
"/otp/enroll",
"/otp/validate",
"/not_confirmed",
}
for _, route := range availableRoutes {
appGroup.StaticFile(route, path.Join(C.App.PublicDir, "/index.html"))
}
engine.Run(strings.Join([]string{C.Address, C.Port}, ":"))
}