Si on suit les considérations du domain-driven design, le fait qu'on réfère toustes à cette partie du code comme `le frontend` me pousse à renommer le package pour mieux réflèter notre utilisation. Ça devrait rendre plus évident où les fichiers sources du frontend sont situés.
193 lines
5.9 KiB
Go
193 lines
5.9 KiB
Go
package agecemorg
|
|
|
|
import (
|
|
"crypto/subtle"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
|
|
"codeberg.org/vlbeaudoin/pave/v2"
|
|
"git.agecem.com/agecem/agecem-org/v3/frontend"
|
|
"git.agecem.com/agecem/agecem-org/v3/frontend/public"
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/labstack/echo/v4/middleware"
|
|
)
|
|
|
|
func RunServer(cfg Config) {
|
|
e := echo.New()
|
|
|
|
e.Renderer = frontend.NewRenderer()
|
|
|
|
e.Pre(middleware.RemoveTrailingSlash())
|
|
|
|
groupStatic := e.Group("/public/*")
|
|
groupStatic.Use(middleware.StaticWithConfig(middleware.StaticConfig{
|
|
Root: "/",
|
|
Filesystem: http.FS(public.GetPublicFS()),
|
|
//TODO
|
|
//Browse: true,
|
|
}))
|
|
|
|
groupV1 := e.Group("/v1")
|
|
|
|
groupV1.Use(middleware.AddTrailingSlash())
|
|
|
|
if cfg.Server.Api.Auth {
|
|
if len(cfg.Server.Api.Key) < 10 {
|
|
log.Fatal("server.api.auth is enabled, but server.api.key is too small (needs at least 10 characters)")
|
|
}
|
|
|
|
groupV1.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
|
|
return subtle.ConstantTimeCompare([]byte(key), []byte(cfg.Server.Api.Key)) == 1, nil
|
|
}))
|
|
|
|
log.Println("Key auth for /v1 activated")
|
|
}
|
|
|
|
groupAdmin := e.Group("/admin")
|
|
|
|
groupAdmin.Use(middleware.AddTrailingSlash())
|
|
|
|
if cfg.Server.Admin.Auth {
|
|
if len(cfg.Server.Admin.Username) < 5 {
|
|
log.Fatal("server.admin.auth is enabled, but server.admin.username is too small (needs at least 5 characters)")
|
|
}
|
|
|
|
if len(cfg.Server.Admin.Password) < 10 {
|
|
log.Fatal("server.admin.auth is enabled, but server.admin.password is too small (needs at least 10 characters)")
|
|
}
|
|
|
|
groupAdmin.Use(middleware.BasicAuth(func(username_entered, password_entered string, c echo.Context) (bool, error) {
|
|
// Be careful to use constant time comparison to prevent timing attacks
|
|
if subtle.ConstantTimeCompare([]byte(username_entered), []byte(cfg.Server.Admin.Username)) == 1 &&
|
|
subtle.ConstantTimeCompare([]byte(password_entered), []byte(cfg.Server.Admin.Password)) == 1 {
|
|
return true, nil
|
|
}
|
|
return false, nil
|
|
}))
|
|
|
|
log.Println("Basic auth for /admin activated")
|
|
}
|
|
|
|
// API Routes
|
|
mediaClient, err := NewMediaClientFromViper()
|
|
if err != nil {
|
|
log.Fatal("Error during NewMediaClientFromViper for API handlers")
|
|
}
|
|
|
|
p := pave.New()
|
|
|
|
v1Handler := V1Handler{
|
|
Config: cfg,
|
|
MediaClient: mediaClient,
|
|
Pave: &p,
|
|
}
|
|
|
|
groupV1.GET("", v1Handler.ListRoutes)
|
|
|
|
if err := pave.EchoRegister[
|
|
ExecuteSeedRequest,
|
|
ExecuteSeedResponse](groupV1, &p, "/v1", http.MethodPost, "/seed", "Créer buckets manquants définis dans `server.documents.buckets`", "ExecuteSeed", v1Handler.ExecuteSeed); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if err := pave.EchoRegister[
|
|
UpdateDocumentKeyRequest,
|
|
UpdateDocumentKeyResponse](groupV1, &p, "/v1", http.MethodPut, "/bucket/:bucket/:document/key", "Renommer un document", "UpdateDocumentKey", v1Handler.UpdateDocumentKey); err != nil {
|
|
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if err := pave.EchoRegister[
|
|
ReadSpecRequest,
|
|
ReadSpecResponse](groupV1, &p, "/v1", http.MethodGet, "/spec", DescriptionV1SpecGET, "SpecRead", v1Handler.ReadSpec); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if err := pave.EchoRegister[
|
|
ListBucketsRequest,
|
|
ListBucketsResponse](groupV1, &p, "/v1", http.MethodGet, "/bucket", "List buckets", "ListBuckets", v1Handler.ListBuckets); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if err := pave.EchoRegister[
|
|
ReadBucketRequest,
|
|
ReadBucketResponse](groupV1, &p, "/v1", http.MethodGet, "/bucket/:bucket", "Read bucket content", "ReadBucket", v1Handler.ReadBucket); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if err := pave.EchoRegister[
|
|
CreateDocumentsRequest,
|
|
CreateDocumentsResponse](groupV1, &p, "/v1", http.MethodPost, "/bucket/:bucket/many", "Upload documents to specified bucket", "CreateDocuments", v1Handler.CreateDocuments); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if err := pave.EchoRegister[
|
|
CreateDocumentRequest,
|
|
CreateDocumentResponse](groupV1, &p, "/v1", http.MethodPost, "/bucket/:bucket", "Upload document to specified bucket", "CreateDocument", v1Handler.CreateDocument); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Do not move to pave, uses echo.Stream instead of echo.JSON
|
|
groupV1.GET("/bucket/:bucket/:document", v1Handler.ReadDocument)
|
|
|
|
if err := pave.EchoRegister[
|
|
DeleteDocumentRequest,
|
|
DeleteDocumentResponse](groupV1, &p, "/v1", http.MethodDelete, "/bucket/:bucket/:document", "Delete document in specified bucket", "DeleteDocument", v1Handler.DeleteDocument); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// HTML Routes
|
|
client := http.DefaultClient
|
|
defer client.CloseIdleConnections()
|
|
|
|
apiClient, err := NewAPIClientFromViper(client)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
webHandler := WebHandler{
|
|
ApiClient: apiClient,
|
|
}
|
|
|
|
e.GET("/", HandleIndex)
|
|
|
|
e.GET("/nothing", HandleNothing())
|
|
|
|
//e.GET("/a-propos", HandleAPropos)
|
|
|
|
//e.GET("/actualite", HandleActualite)
|
|
|
|
//e.GET("/actualite/:article", HandleActualiteArticle)
|
|
|
|
e.GET("/vie-etudiante", HandleVieEtudiante)
|
|
|
|
e.GET("/vie-etudiante/:organisme", HandleVieEtudianteOrganisme)
|
|
|
|
e.GET("/documentation", webHandler.HandleDocumentation)
|
|
|
|
e.GET("/proces-verbaux", HandlePageProcesVerbaux())
|
|
|
|
e.GET("/formulaires", HandleFormulaires)
|
|
|
|
// Public Routes
|
|
|
|
e.GET("/public/documentation/:bucket/:document", webHandler.HandlePublicDocumentation)
|
|
|
|
// Admin Routes
|
|
|
|
groupAdmin.GET("", HandleAdmin)
|
|
|
|
groupAdmin.GET("/documents/upload", webHandler.HandleAdminDocumentsUpload)
|
|
|
|
groupAdmin.POST("/documents/upload", webHandler.HandleAdminDocumentsUploadPOST)
|
|
|
|
groupAdmin.GET("/documents/edit", HandleAdminDocumentsEdit(webHandler.ApiClient))
|
|
groupAdmin.GET("/documents/edit/:bucket/:document/delete", HandleAdminDocumentsEditDelete(webHandler.ApiClient))
|
|
groupAdmin.DELETE("/documents/edit/:bucket/:document", HandleAdminDocumentsEditDelete(webHandler.ApiClient))
|
|
groupAdmin.GET("/documents/edit/:bucket/:document/key", HandleAdminDocumentsEditKey(webHandler.ApiClient))
|
|
groupAdmin.PUT("/documents/edit/:bucket/:document/key", HandleAdminDocumentsEditKey(webHandler.ApiClient))
|
|
|
|
e.Logger.Fatal(e.Start(
|
|
fmt.Sprintf(":%d", cfg.Server.Port)))
|
|
}
|