aboutsummaryrefslogblamecommitdiff
path: root/cmd/app/main.go
blob: 65e8b5a49af92b4dbda73472595b33883aebea77 (plain) (tree)



























                                                                         



                            


































                                                           
                              















































































                                                                                    
                                 







                                                                                     
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}, ":"))
}