Bump major version à 9 package main déplacé vers cmd/bottin/ pour garder `go install` qui nomme l'exécutable `bottin`, sans empêcher d'importer le code à l'extérieur du projet avec pkg/bottin/. Déplacer fichiers SQL vers queries/ Déplacer fichiers html vers templates/ Ajouter scripts/ avec génération et injection de certificats x509 (https) et les ajouter au Makefile Ajouter début d'exemple de manifests dans deployments/kubernetes/
717 lines
16 KiB
Go
717 lines
16 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"crypto/subtle"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"codeberg.org/vlbeaudoin/voki/v3"
|
|
"git.agecem.com/agecem/bottin/v9/pkg/bottin"
|
|
"git.agecem.com/agecem/bottin/v9/templates"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/labstack/echo/v4/middleware"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
var cfgFile string
|
|
|
|
// initConfig reads in config file and ENV variables if set.
|
|
func initConfig() {
|
|
if cfgFile != "" {
|
|
// Use config file from the flag.
|
|
viper.SetConfigFile(cfgFile)
|
|
} else {
|
|
// Find home directory.
|
|
home, err := os.UserHomeDir()
|
|
cobra.CheckErr(err)
|
|
|
|
// Search config in home directory with name ".bottin" (without extension).
|
|
viper.AddConfigPath(home)
|
|
viper.SetConfigType("yaml")
|
|
viper.SetConfigName(".bottin")
|
|
}
|
|
|
|
viper.SetEnvPrefix("BOTTIN")
|
|
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
|
viper.AutomaticEnv() // read in environment variables that match
|
|
|
|
// If a config file is found, read it in.
|
|
if err := viper.ReadInConfig(); err == nil {
|
|
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
/* TODO
|
|
if err := Run(context.Background(), Config{}, nil, os.Stdout); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
*/
|
|
|
|
// Handle the command-line via cobra and viper
|
|
execute()
|
|
}
|
|
|
|
func init() {
|
|
// rootCmd
|
|
|
|
cobra.OnInitialize(initConfig)
|
|
|
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.bottin.yaml)")
|
|
|
|
// client.api.host
|
|
rootCmd.PersistentFlags().String(
|
|
"client-api-host",
|
|
"api",
|
|
"API server host",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"client.api.host",
|
|
rootCmd.PersistentFlags().Lookup("client-api-host"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// client.api.key
|
|
rootCmd.PersistentFlags().String(
|
|
"client-api-key",
|
|
"bottin",
|
|
"API server key",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"client.api.key",
|
|
rootCmd.PersistentFlags().Lookup("client-api-key"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// client.api.port
|
|
rootCmd.PersistentFlags().Int(
|
|
"client-api-port",
|
|
1312,
|
|
"API server port",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"client.api.port",
|
|
rootCmd.PersistentFlags().Lookup("client-api-port"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// client.api.protocol
|
|
rootCmd.PersistentFlags().String(
|
|
"client-api-protocol",
|
|
"https",
|
|
"API server protocol",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"client.api.protocol",
|
|
rootCmd.PersistentFlags().Lookup("client-api-protocol"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server
|
|
rootCmd.AddCommand(serverCmd)
|
|
|
|
// server api
|
|
serverCmd.AddCommand(apiCmd)
|
|
|
|
// server api db
|
|
// server.api.db.database
|
|
apiCmd.PersistentFlags().String(
|
|
"server-api-db-database",
|
|
"bottin",
|
|
"Postgres database name",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.db.database",
|
|
apiCmd.PersistentFlags().Lookup("server-api-db-database"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.db.host
|
|
apiCmd.PersistentFlags().String(
|
|
"server-api-db-host",
|
|
"db",
|
|
"Postgres host name",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.db.host",
|
|
apiCmd.PersistentFlags().Lookup("server-api-db-host"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.db.password
|
|
apiCmd.PersistentFlags().String(
|
|
"server-api-db-password",
|
|
"bottin",
|
|
"Postgres password",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.db.password",
|
|
apiCmd.PersistentFlags().Lookup("server-api-db-password"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.db.port
|
|
apiCmd.PersistentFlags().Int(
|
|
"server-api-db-port",
|
|
5432,
|
|
"Postgres port",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.db.port",
|
|
apiCmd.PersistentFlags().Lookup("server-api-db-port"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.db.sslmode
|
|
apiCmd.PersistentFlags().String(
|
|
"server-api-db-sslmode",
|
|
"prefer",
|
|
"Postgres sslmode",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.db.sslmode",
|
|
apiCmd.PersistentFlags().Lookup("server-api-db-sslmode"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.db.user
|
|
apiCmd.PersistentFlags().String(
|
|
"server-api-db-user",
|
|
"bottin",
|
|
"Postgres user name",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.db.user",
|
|
apiCmd.PersistentFlags().Lookup("server-api-db-user"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.host
|
|
apiCmd.PersistentFlags().String(
|
|
"server-api-host",
|
|
"",
|
|
"API server hostname or IP to answer on (empty = any)",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.host",
|
|
apiCmd.PersistentFlags().Lookup("server-api-host"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.key
|
|
apiCmd.PersistentFlags().String(
|
|
"server-api-key",
|
|
"bottin",
|
|
"API server key",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.key",
|
|
apiCmd.PersistentFlags().Lookup("server-api-key"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.port
|
|
apiCmd.PersistentFlags().Int(
|
|
"server-api-port",
|
|
1312,
|
|
"API server port",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.port",
|
|
apiCmd.PersistentFlags().Lookup("server-api-port"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server api tls
|
|
// server.api.tls.enabled
|
|
apiCmd.PersistentFlags().Bool(
|
|
"server-api-tls-enabled",
|
|
true,
|
|
"Use TLS for API server connections (requires certfile and keyfile)",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.tls.enabled",
|
|
apiCmd.PersistentFlags().Lookup("server-api-tls-enabled"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.tls.certfile
|
|
apiCmd.PersistentFlags().String(
|
|
"server-api-tls-certfile",
|
|
"/etc/bottin/cert.pem",
|
|
"Path to certificate file",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.tls.certfile",
|
|
apiCmd.PersistentFlags().Lookup("server-api-tls-certfile"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.api.tls.keyfile
|
|
apiCmd.PersistentFlags().String(
|
|
"server-api-tls-keyfile",
|
|
"/etc/bottin/key.pem",
|
|
"Path to private key file",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.api.tls.keyfile",
|
|
apiCmd.PersistentFlags().Lookup("server-api-tls-keyfile"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server ui
|
|
serverCmd.AddCommand(uiCmd)
|
|
|
|
// server ui api
|
|
|
|
// server.ui.api.host
|
|
uiCmd.PersistentFlags().String(
|
|
"server-ui-api-host",
|
|
"api",
|
|
"Web UI backend API server host name",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.api.host",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-api-host"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.api.key
|
|
uiCmd.PersistentFlags().String(
|
|
"server-ui-api-key",
|
|
"bottin",
|
|
"Web UI backend API server key",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.api.key",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-api-key"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.api.port
|
|
uiCmd.PersistentFlags().Int(
|
|
"server-ui-api-port",
|
|
1312,
|
|
"Web UI backend API server port",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.api.port",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-api-port"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.api.protocol
|
|
uiCmd.PersistentFlags().String(
|
|
"server-ui-api-protocol",
|
|
"https",
|
|
"Web UI backend API server protocol",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.api.protocol",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-api-protocol"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.api.tls.skipverify
|
|
uiCmd.PersistentFlags().Bool(
|
|
"server-ui-api-tls-skipverify",
|
|
false,
|
|
"Skip API server TLS certificate verification",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.api.tls.skipverify",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-api-tls-skipverify"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.host
|
|
uiCmd.PersistentFlags().String(
|
|
"server-ui-host",
|
|
"",
|
|
"Web UI host",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.host",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-host"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.password
|
|
uiCmd.PersistentFlags().String(
|
|
"server-ui-password",
|
|
"bottin",
|
|
"Web UI password",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.password",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-password"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.port
|
|
uiCmd.PersistentFlags().Int(
|
|
"server-ui-port",
|
|
2312,
|
|
"Web UI port",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.port",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-port"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.user
|
|
uiCmd.PersistentFlags().String(
|
|
"server-ui-user",
|
|
"bottin",
|
|
"Web UI user",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.user",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-user"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server ui tls
|
|
// server.ui.tls.enabled
|
|
uiCmd.PersistentFlags().Bool(
|
|
"server-ui-tls-enabled",
|
|
true,
|
|
"Web UI enable TLS (requires certfile and keyfile)",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.tls.enabled",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-tls-enabled"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.tls.certfile
|
|
uiCmd.PersistentFlags().String(
|
|
"server-ui-tls-certfile",
|
|
"/etc/bottin/cert.pem",
|
|
"Path to Web UI TLS certificate file",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.tls.certfile",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-tls-certfile"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// server.ui.tls.keyfile
|
|
uiCmd.PersistentFlags().String(
|
|
"server-ui-tls-keyfile",
|
|
"/etc/bottin/key.pem",
|
|
"Path to Web UI TLS private key file",
|
|
)
|
|
if err := viper.BindPFlag(
|
|
"server.ui.tls.keyfile",
|
|
uiCmd.PersistentFlags().Lookup("server-ui-tls-keyfile"),
|
|
); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
/* TODO
|
|
func Run(ctx context.Context, config Config, args []string, stdout io.Writer) error {
|
|
return fmt.Errorf("not implemented")
|
|
}
|
|
*/
|
|
|
|
// rootCmd represents the base command when called without any subcommands
|
|
var rootCmd = &cobra.Command{
|
|
Use: "bottin",
|
|
Short: "Bottin étudiant de l'AGECEM",
|
|
}
|
|
|
|
// execute adds all child commands to the root command and sets flags appropriately.
|
|
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
|
func execute() {
|
|
err := rootCmd.Execute()
|
|
if err != nil {
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
var serverCmd = &cobra.Command{
|
|
Use: "server",
|
|
Short: "Démarrer serveurs (API ou Web UI)",
|
|
}
|
|
|
|
// apiCmd represents the api command
|
|
var apiCmd = &cobra.Command{
|
|
Use: "api",
|
|
Short: "Démarrer le serveur API",
|
|
Args: cobra.ExactArgs(0),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
var cfg bottin.Config
|
|
if err := viper.Unmarshal(&cfg); err != nil {
|
|
log.Fatal("parse config:", err)
|
|
}
|
|
|
|
e := echo.New()
|
|
|
|
// Middlewares
|
|
|
|
e.Pre(middleware.AddTrailingSlash())
|
|
|
|
if cfg.Server.API.Key != "" {
|
|
e.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
|
|
return subtle.ConstantTimeCompare([]byte(key), []byte(cfg.Server.API.Key)) == 1, nil
|
|
}))
|
|
} else {
|
|
log.Println("Server started but no API key (server.api.key) was provided, using empty key (NOT RECOMMENDED FOR PRODUCTION)")
|
|
}
|
|
|
|
// DataClient
|
|
ctx := context.Background()
|
|
|
|
//prep
|
|
pool, err := pgxpool.New(
|
|
ctx,
|
|
fmt.Sprintf(
|
|
"user=%s password=%s database=%s host=%s port=%d sslmode=%s ",
|
|
cfg.Server.API.DB.User,
|
|
cfg.Server.API.DB.Password,
|
|
cfg.Server.API.DB.Database,
|
|
cfg.Server.API.DB.Host,
|
|
cfg.Server.API.DB.Port,
|
|
cfg.Server.API.DB.SSLMode,
|
|
))
|
|
if err != nil {
|
|
log.Fatal("init pgx pool:", err)
|
|
}
|
|
defer pool.Close()
|
|
|
|
db := &bottin.PostgresClient{
|
|
Ctx: ctx,
|
|
Pool: pool,
|
|
}
|
|
if err := db.Pool.Ping(ctx); err != nil {
|
|
log.Fatal("ping db:", err)
|
|
}
|
|
|
|
if err := db.CreateOrReplaceSchema(); err != nil {
|
|
log.Fatal("create or replace schema:", err)
|
|
}
|
|
|
|
if err := db.CreateOrReplaceViews(); err != nil {
|
|
log.Fatal("create or replace views:", err)
|
|
}
|
|
|
|
// Routes
|
|
if err := bottin.AddRoutes(e, db, cfg); err != nil {
|
|
log.Fatal("add routes:", err)
|
|
}
|
|
/*
|
|
h := handlers.New(client)
|
|
|
|
e.GET("/v9/health/", h.GetHealth)
|
|
|
|
e.POST("/v9/membres/", h.PostMembres)
|
|
|
|
e.GET("/v9/membres/", h.ListMembres)
|
|
|
|
e.GET("/v9/membres/:membre_id/", h.ReadMembre)
|
|
|
|
e.PUT("/v9/membres/:membre_id/prefered_name/", h.PutMembrePreferedName)
|
|
|
|
e.POST("/v9/programmes/", h.PostProgrammes)
|
|
|
|
e.POST("/v9/seed/", h.PostSeed)
|
|
*/
|
|
|
|
// Execution
|
|
switch cfg.Server.API.TLS.Enabled {
|
|
case false:
|
|
e.Logger.Fatal(
|
|
e.Start(
|
|
fmt.Sprintf("%s:%d", cfg.Server.API.Host, cfg.Server.API.Port),
|
|
),
|
|
)
|
|
case true:
|
|
if cfg.Server.API.TLS.Certfile == "" {
|
|
log.Fatal("TLS enabled for API but no certificate file provided")
|
|
}
|
|
|
|
if cfg.Server.API.TLS.Keyfile == "" {
|
|
log.Fatal("TLS enabled for UI but no private key file provided")
|
|
}
|
|
|
|
e.Logger.Fatal(
|
|
e.StartTLS(
|
|
fmt.Sprintf("%s:%d", cfg.Server.API.Host, cfg.Server.API.Port),
|
|
cfg.Server.API.TLS.Certfile,
|
|
cfg.Server.API.TLS.Keyfile,
|
|
),
|
|
)
|
|
}
|
|
},
|
|
}
|
|
|
|
// uiCmd represents the ui command
|
|
var uiCmd = &cobra.Command{
|
|
Use: "ui",
|
|
Aliases: []string{"web", "interface"},
|
|
Short: "Démarrer l'interface Web UI",
|
|
Args: cobra.ExactArgs(0),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
// Parse config
|
|
var cfg bottin.Config
|
|
if err := viper.Unmarshal(&cfg); err != nil {
|
|
log.Fatal("init config:", err)
|
|
}
|
|
|
|
e := echo.New()
|
|
|
|
// Middlewares
|
|
|
|
// Trailing slash
|
|
e.Pre(middleware.AddTrailingSlash())
|
|
|
|
// Auth
|
|
e.Use(middleware.BasicAuth(func(user, password string, c echo.Context) (bool, error) {
|
|
usersMatch := subtle.ConstantTimeCompare([]byte(user), []byte(cfg.Server.UI.User)) == 1
|
|
passwordsMatch := subtle.ConstantTimeCompare([]byte(password), []byte(cfg.Server.UI.Password)) == 1
|
|
return usersMatch && passwordsMatch, nil
|
|
}))
|
|
|
|
// Templating
|
|
e.Renderer = templates.NewTemplate()
|
|
|
|
// API Client
|
|
var httpClient = &http.Client{
|
|
Transport: &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
InsecureSkipVerify: cfg.Server.UI.API.TLS.SkipVerify,
|
|
},
|
|
},
|
|
}
|
|
apiClient := bottin.APIClient{
|
|
Voki: voki.New(
|
|
httpClient,
|
|
cfg.Server.UI.API.Host,
|
|
cfg.Server.UI.API.Key,
|
|
cfg.Server.UI.API.Port,
|
|
cfg.Server.UI.API.Protocol,
|
|
)}
|
|
defer apiClient.Voki.CloseIdleConnections()
|
|
|
|
// Routes
|
|
e.GET("/", func(c echo.Context) error {
|
|
pingResult, err := apiClient.GetHealth()
|
|
if err != nil {
|
|
return c.Render(
|
|
http.StatusOK,
|
|
"index-html",
|
|
voki.MessageResponse{Message: fmt.Sprintf("impossible d'accéder au serveur API: %s", err)},
|
|
)
|
|
}
|
|
|
|
return c.Render(
|
|
http.StatusOK,
|
|
"index-html",
|
|
voki.MessageResponse{Message: pingResult},
|
|
)
|
|
})
|
|
|
|
e.GET("/membre/", func(c echo.Context) error {
|
|
membreID := c.QueryParam("membre_id")
|
|
switch {
|
|
case membreID == "":
|
|
return c.Render(
|
|
http.StatusOK,
|
|
"index-html",
|
|
voki.MessageResponse{Message: "❗Veuillez entrer un numéro étudiant à rechercher"},
|
|
)
|
|
case !bottin.IsMembreID(membreID):
|
|
return c.Render(
|
|
http.StatusOK,
|
|
"index-html",
|
|
voki.MessageResponse{Message: fmt.Sprintf("❗Numéro étudiant '%s' invalide", membreID)},
|
|
)
|
|
}
|
|
|
|
membre, err := apiClient.GetMembreForDisplay(membreID)
|
|
if err != nil {
|
|
return c.Render(
|
|
http.StatusOK,
|
|
"index-html",
|
|
voki.MessageResponse{Message: fmt.Sprintf("❗erreur: %s", err)},
|
|
)
|
|
}
|
|
|
|
return c.Render(
|
|
http.StatusOK,
|
|
"index-html",
|
|
voki.MessageResponse{Message: fmt.Sprintf(`
|
|
Numéro étudiant: %s
|
|
Nom d'usage: %s
|
|
Programme: [%s] %s
|
|
`,
|
|
membre.ID,
|
|
membre.Name,
|
|
membre.ProgrammeID,
|
|
membre.ProgrammeName,
|
|
)},
|
|
)
|
|
})
|
|
|
|
// Execution
|
|
switch cfg.Server.UI.TLS.Enabled {
|
|
case false:
|
|
e.Logger.Fatal(e.Start(
|
|
fmt.Sprintf("%s:%d", cfg.Server.UI.Host, cfg.Server.UI.Port)))
|
|
case true:
|
|
if cfg.Server.UI.TLS.Certfile == "" {
|
|
log.Fatal("TLS enabled for UI but no certificate file provided")
|
|
}
|
|
|
|
if cfg.Server.UI.TLS.Keyfile == "" {
|
|
log.Fatal("TLS enabled for UI but no private key file provided")
|
|
}
|
|
|
|
e.Logger.Fatal(
|
|
e.StartTLS(
|
|
fmt.Sprintf("%s:%d", cfg.Server.UI.Host, cfg.Server.UI.Port),
|
|
cfg.Server.UI.TLS.Certfile,
|
|
cfg.Server.UI.TLS.Keyfile,
|
|
),
|
|
)
|
|
}
|
|
|
|
},
|
|
}
|