[WIP] Add web client
Ignore .swp files Rename serverCmd to apiCmd (the web client is technically a server too) Add webCmd for html routes hosting Add embedding and templating for web client Add webhandlers Fix some variables not being filled automatically by viper Change flags and reorganize config structure
This commit is contained in:
parent
3e37e8ffef
commit
3aa7faa2f6
7 changed files with 201 additions and 32 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -25,3 +25,6 @@
|
||||||
|
|
||||||
# env
|
# env
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
# .swp
|
||||||
|
*.swp
|
||||||
|
|
|
@ -18,11 +18,22 @@ var (
|
||||||
apiKey string
|
apiKey string
|
||||||
)
|
)
|
||||||
|
|
||||||
// serverCmd represents the server command
|
// apiCmd represents the api command
|
||||||
var serverCmd = &cobra.Command{
|
var apiCmd = &cobra.Command{
|
||||||
Use: "server",
|
Use: "api",
|
||||||
Short: "Démarrer le serveur API",
|
Short: "Démarrer le serveur API",
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
apiKey = viper.GetString("api.key")
|
||||||
|
apiPort = viper.GetInt("api.port")
|
||||||
|
|
||||||
|
connection := data.PostgresConnection{
|
||||||
|
User: viper.GetString("db.user"),
|
||||||
|
Password: viper.GetString("db.password"),
|
||||||
|
Host: viper.GetString("db.host"),
|
||||||
|
Database: viper.GetString("db.database"),
|
||||||
|
Port: viper.GetInt("db.port"),
|
||||||
|
}
|
||||||
|
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
|
|
||||||
|
@ -52,14 +63,6 @@ var serverCmd = &cobra.Command{
|
||||||
|
|
||||||
// Execution
|
// Execution
|
||||||
|
|
||||||
connection := data.PostgresConnection{
|
|
||||||
User: viper.GetString("db.user"),
|
|
||||||
Password: viper.GetString("db.password"),
|
|
||||||
Host: viper.GetString("db.host"),
|
|
||||||
Database: viper.GetString("db.database"),
|
|
||||||
Port: viper.GetInt("db.port"),
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := data.NewDataClient(connection)
|
client, err := data.NewDataClient(connection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Could not establish database connection.\n Error: %s\n", err)
|
log.Fatalf("Could not establish database connection.\n Error: %s\n", err)
|
||||||
|
@ -72,40 +75,45 @@ var serverCmd = &cobra.Command{
|
||||||
|
|
||||||
client.DB.Close()
|
client.DB.Close()
|
||||||
|
|
||||||
|
log.Println("apiPort: ", apiPort)
|
||||||
|
log.Println("apiKey: ", apiKey)
|
||||||
|
|
||||||
e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", apiPort)))
|
e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", apiPort)))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(serverCmd)
|
rootCmd.AddCommand(apiCmd)
|
||||||
|
|
||||||
// api.key
|
// api.key
|
||||||
serverCmd.Flags().StringVar(
|
apiCmd.Flags().String(
|
||||||
&apiKey, "api-key", "bottin",
|
"api-key", "bottin",
|
||||||
"API server key. Leave empty for no key auth. (config: 'api.key')")
|
"API server key. Leave empty for no key auth. (config: 'api.key')")
|
||||||
|
viper.BindPFlag("api.key", apiCmd.Flags().Lookup("api-key"))
|
||||||
|
|
||||||
// api.port
|
// api.port
|
||||||
serverCmd.Flags().IntVar(
|
apiCmd.Flags().Int(
|
||||||
&apiPort, "api-port", 1312,
|
"api-port", 1312,
|
||||||
"API server port (config:'api.port')")
|
"API server port (config:'api.port')")
|
||||||
|
viper.BindPFlag("api.port", apiCmd.Flags().Lookup("api-port"))
|
||||||
|
|
||||||
// db.database
|
// db.database
|
||||||
serverCmd.Flags().String("db-database", "bottin", "Postgres database (config:'db.database')")
|
apiCmd.Flags().String("db-database", "bottin", "Postgres database (config:'db.database')")
|
||||||
viper.BindPFlag("db.database", serverCmd.Flags().Lookup("db-database"))
|
viper.BindPFlag("db.database", apiCmd.Flags().Lookup("db-database"))
|
||||||
|
|
||||||
// db.host
|
// db.host
|
||||||
serverCmd.Flags().String("db-host", "postgres", "Postgres host (config:'db.host')")
|
apiCmd.Flags().String("db-host", "db", "Postgres host (config:'db.host')")
|
||||||
viper.BindPFlag("db.host", serverCmd.Flags().Lookup("db-host"))
|
viper.BindPFlag("db.host", apiCmd.Flags().Lookup("db-host"))
|
||||||
|
|
||||||
// db.password
|
// db.password
|
||||||
serverCmd.Flags().String("db-password", "bottin", "Postgres password (config:'db.password')")
|
apiCmd.Flags().String("db-password", "bottin", "Postgres password (config:'db.password')")
|
||||||
viper.BindPFlag("db.password", serverCmd.Flags().Lookup("db-password"))
|
viper.BindPFlag("db.password", apiCmd.Flags().Lookup("db-password"))
|
||||||
|
|
||||||
// db.port
|
// db.port
|
||||||
serverCmd.Flags().Int("db-port", 5432, "Postgres port (config:'db.port')")
|
apiCmd.Flags().Int("db-port", 5432, "Postgres port (config:'db.port')")
|
||||||
viper.BindPFlag("db.port", serverCmd.Flags().Lookup("db-port"))
|
viper.BindPFlag("db.port", apiCmd.Flags().Lookup("db-port"))
|
||||||
|
|
||||||
// db.user
|
// db.user
|
||||||
serverCmd.Flags().String("db-user", "bottin", "Postgres user (config:'db.user')")
|
apiCmd.Flags().String("db-user", "bottin", "Postgres user (config:'db.user')")
|
||||||
viper.BindPFlag("db.user", serverCmd.Flags().Lookup("db-user"))
|
viper.BindPFlag("db.user", apiCmd.Flags().Lookup("db-user"))
|
||||||
}
|
}
|
111
v4/cmd/web.go
111
v4/cmd/web.go
|
@ -1,20 +1,129 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"git.agecem.com/agecem/bottin/v4/web"
|
||||||
|
"git.agecem.com/agecem/bottin/v4/web/webhandlers"
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
"github.com/labstack/echo/v4/middleware"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
webUser string
|
||||||
|
webPassword string
|
||||||
|
webPort int
|
||||||
|
webApiHost string
|
||||||
|
webApiKey string
|
||||||
|
webApiPort int
|
||||||
|
)
|
||||||
|
|
||||||
|
var templatesFS embed.FS
|
||||||
|
|
||||||
|
type Template struct {
|
||||||
|
templates *template.Template
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
||||||
|
return t.templates.ExecuteTemplate(w, name, data)
|
||||||
|
}
|
||||||
|
|
||||||
// webCmd represents the web command
|
// webCmd represents the web command
|
||||||
var webCmd = &cobra.Command{
|
var webCmd = &cobra.Command{
|
||||||
Use: "web",
|
Use: "web",
|
||||||
Short: "Démarrer le client web",
|
Short: "Démarrer le client web",
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("web called")
|
webApiHost = viper.GetString("web.api.host")
|
||||||
|
webApiKey = viper.GetString("web.api.key")
|
||||||
|
webApiPort = viper.GetInt("web.api.port")
|
||||||
|
webPassword = viper.GetString("web.password")
|
||||||
|
webPort = viper.GetInt("web.port")
|
||||||
|
webUser = viper.GetString("web.user")
|
||||||
|
|
||||||
|
e := echo.New()
|
||||||
|
|
||||||
|
// Middlewares
|
||||||
|
|
||||||
|
e.Pre(middleware.AddTrailingSlash())
|
||||||
|
|
||||||
|
e.Use(middleware.BasicAuth(func(user, password string, c echo.Context) (bool, error) {
|
||||||
|
usersMatch := subtle.ConstantTimeCompare([]byte(user), []byte(webUser)) == 1
|
||||||
|
passwordsMatch := subtle.ConstantTimeCompare([]byte(password), []byte(webPassword)) == 1
|
||||||
|
return usersMatch && passwordsMatch, nil
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Template
|
||||||
|
|
||||||
|
t := &Template{
|
||||||
|
templates: template.Must(template.ParseFS(templatesFS, "templates/*.html")),
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Renderer = t
|
||||||
|
|
||||||
|
// Routes
|
||||||
|
|
||||||
|
e.GET("/", webhandlers.GetIndex)
|
||||||
|
|
||||||
|
// Execution
|
||||||
|
|
||||||
|
fmt.Println("webPort: ", webPort)
|
||||||
|
fmt.Println("web.port: ", viper.GetInt("web.port"))
|
||||||
|
webPortFlag, err := cmd.Flags().GetInt("web-port")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println("web-port: ", webPortFlag)
|
||||||
|
|
||||||
|
e.Logger.Fatal(e.Start(
|
||||||
|
fmt.Sprintf(":%d", webPort)))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(webCmd)
|
rootCmd.AddCommand(webCmd)
|
||||||
|
templatesFS = web.GetTemplates()
|
||||||
|
|
||||||
|
// web.api.host
|
||||||
|
webCmd.Flags().String(
|
||||||
|
"web-api-host", "api",
|
||||||
|
"Remote API server host (config:'web.api.host')")
|
||||||
|
viper.BindPFlag("web.api.host", webCmd.Flags().Lookup("web-api-host"))
|
||||||
|
|
||||||
|
// web.api.key
|
||||||
|
webCmd.Flags().String(
|
||||||
|
"web-api-key", "bottin",
|
||||||
|
"Remote API server key (config:'web.api.key')")
|
||||||
|
viper.BindPFlag("web.api.key", webCmd.Flags().Lookup("web-api-key"))
|
||||||
|
|
||||||
|
// web.api.port
|
||||||
|
webCmd.Flags().Int(
|
||||||
|
"web-api-port", 1312,
|
||||||
|
"Remote API server port (config:'web.api.port')")
|
||||||
|
viper.BindPFlag("web.api.port", webCmd.Flags().Lookup("web-api-port"))
|
||||||
|
|
||||||
|
// web.password
|
||||||
|
webCmd.Flags().String(
|
||||||
|
"web-password", "bottin",
|
||||||
|
"Web client password (config:'web.password')")
|
||||||
|
viper.BindPFlag("web.password", webCmd.Flags().Lookup("web-password"))
|
||||||
|
|
||||||
|
// web.port
|
||||||
|
webCmd.Flags().Int(
|
||||||
|
"web-port", 2312,
|
||||||
|
"Web client port (config:'web.port')")
|
||||||
|
viper.BindPFlag("web.port", webCmd.Flags().Lookup("web-port"))
|
||||||
|
|
||||||
|
// web.user
|
||||||
|
webCmd.Flags().String(
|
||||||
|
"web-user", "bottin",
|
||||||
|
"Web client user (config:'web.user')")
|
||||||
|
viper.BindPFlag("web.user", webCmd.Flags().Lookup("web-user"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
services:
|
services:
|
||||||
|
|
||||||
postgres:
|
db:
|
||||||
image: postgres:latest
|
image: postgres:latest
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DATABASE: "${BOTTIN_POSTGRES_DATABASE}"
|
POSTGRES_DATABASE: "${BOTTIN_POSTGRES_DATABASE}"
|
||||||
|
@ -11,11 +11,19 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- 'pgdata:/var/lib/postgresql/data'
|
- 'pgdata:/var/lib/postgresql/data'
|
||||||
|
|
||||||
|
#api:
|
||||||
|
# depends_on: db
|
||||||
|
|
||||||
|
#web:
|
||||||
|
# depends_on: api
|
||||||
|
|
||||||
adminer:
|
adminer:
|
||||||
image: adminer
|
image: adminer
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- 8088:8080
|
- 8088:8080
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pgdata:
|
pgdata:
|
||||||
|
|
|
@ -2,9 +2,9 @@ package web
|
||||||
|
|
||||||
import "embed"
|
import "embed"
|
||||||
|
|
||||||
//go:embed templates
|
//go:embed templates/*
|
||||||
var templates embed.FS
|
var templatesFS embed.FS
|
||||||
|
|
||||||
func GetTemplates() embed.FS {
|
func GetTemplates() embed.FS {
|
||||||
return templates
|
return templatesFS
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,31 @@
|
||||||
Hello world from bottin
|
{{ define "index-html" }}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>
|
||||||
|
AGECEM | Bottin
|
||||||
|
</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h2>
|
||||||
|
Bottin des membres de l'AGECEM
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Scannez la carte étudiante d'unE membre<br>
|
||||||
|
-ou-<br>
|
||||||
|
Entrez manuellement le code à 7 chiffres
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<form action="/membre/">
|
||||||
|
<label>#
|
||||||
|
<input type="text" name="num_etud" id="num_etud" autofocus>
|
||||||
|
</label>
|
||||||
|
<button formmethod="get" type="submit">Valider</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
{{ end }}
|
||||||
|
|
11
v4/web/webhandlers/handlers.go
Normal file
11
v4/web/webhandlers/handlers.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package webhandlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetIndex(c echo.Context) error {
|
||||||
|
return c.Render(http.StatusOK, "index-html", nil)
|
||||||
|
}
|
Loading…
Reference in a new issue