bottin/bottin/bottin.go

179 lines
4.5 KiB
Go

package bottin
import (
"crypto/subtle"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"git.agecem.com/agecem/bottin/data"
"git.agecem.com/agecem/bottin/embed"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/spf13/viper"
)
var (
login_username, login_password string
server_port int
db_host, db_user, db_password, db_name string
db_port int
db_type, db_path string
json_insert_path string
insert_batch_size int
html string
)
// Funcs
func init() {
html = embed.ReadHtml()
}
// JSON to []*data.Membre
func obtenirUnmarshalJSON(path string) ([]*data.Membre, error) {
content, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
var membres_insert []*data.Membre
err_json := json.Unmarshal([]byte(content), &membres_insert)
if err_json != nil {
return nil, err_json
}
return membres_insert, nil
}
func membreToJson(membre *data.Membre) ([]byte, error) {
membreJson, err := json.Marshal(membre)
return membreJson, err
}
// Import flags from viper
func UpdateFlags() {
db_type = viper.GetString("db.type")
db_path = viper.GetString("db.sqlite.path")
server_port = viper.GetInt("server.port")
login_username = viper.GetString("login.username")
login_password = viper.GetString("login.password")
insert_batch_size = viper.GetInt("import.insert_batch_size")
}
// Batch insert par json passé par argument
func InsertJson(json_insert_path string) {
if json_insert_path != "" {
log.Printf("Trying to import json: %s", json_insert_path)
newMembres, err_insert := obtenirUnmarshalJSON(json_insert_path)
if newMembres != nil {
log.Printf("Membres found, importing...")
data.InsertMembres(newMembres, insert_batch_size)
log.Printf("Success?")
}
if err_insert != nil {
log.Fatal(err_insert)
}
}
}
// Run echo webserver
func RunServer() {
// Echo instance and group
e := echo.New()
g := e.Group("")
// Middlewares
// Compatibilité
e.Pre(middleware.Rewrite(map[string]string{
"/membre/?num_etud=*": "/membre/$1",
}))
e.Pre(middleware.RemoveTrailingSlash())
// Authentification de base
g.Use(middleware.BasicAuth(basicAuther))
// Logger - Choose one
// Verbose logger
//g.Use(middleware.Logger())
// Less verbose logger
g.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
Format: "${time_rfc3339_nano} method=${method}, uri=${uri}, status=${status}" + "\n",
}))
// Routes
registerRoutes(g)
registerRoutesv1(g)
// Start server
e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", server_port)))
}
// Handlers
func basicAuther(username, password string, context echo.Context) (bool, error) {
if subtle.ConstantTimeCompare([]byte(username), []byte(login_username)) == 1 &&
subtle.ConstantTimeCompare([]byte(password), []byte(login_password)) == 1 {
return true, nil
}
return false, nil
}
func registerRoutesv1(g *echo.Group) {
g.GET("/v1", showAPISpecs)
g.GET("/v1/membre/:num_etud", showMembreJson)
}
func showMembreJson(c echo.Context) error {
num_etud := c.Param("num_etud")
var membre data.Membre = data.ReadMembre(num_etud)
return c.JSON(http.StatusOK, membre)
}
func showAPISpecs(c echo.Context) error {
apispec := fmt.Sprintln(`agecem/bottin
API Specifications
-----
'/v1' | GET | Afficher spécifications API
'/v1/membre/:num_etud' | GET | Afficher membre avec le numéro étudiant :num_etud, en JSON
'/membre/:num_etud' | GET | Afficher membre avec le numéro étudiant :num_etud
'/' | GET | Afficher bottin web
'/membre' | GET | Afficher bottin web
'/static' | GET | DEPRECATED Répertoire des fichiers statics
-----`)
return c.String(http.StatusOK, apispec)
}
func registerRoutes(g *echo.Group) {
g.GET("/", func(c echo.Context) error {
return c.HTML(http.StatusOK, html)
})
// Doublon de l'autre le temps que j'figure out les shits
g.GET("/membre", func(c echo.Context) error {
return c.HTML(http.StatusOK, html)
})
// Get specific membre
g.GET("/membre/:num_etud", func(c echo.Context) error {
num_etud := c.Param("num_etud")
var membre data.Membre = data.ReadMembre(num_etud)
msgNumEtud := fmt.Sprintf("<p>Numéro d'étudiantE: %s</p>", num_etud)
msgNom := fmt.Sprintf("<p>Nom: %s</p>", membre.Nom)
msg := fmt.Sprintf("%s%s%s", html, msgNumEtud, msgNom)
return c.HTML(http.StatusOK, fmt.Sprintf(msg))
})
}