2024-09-27 20:25:12 -04:00
package agecemorg
2024-08-23 13:54:20 -04:00
import (
"crypto/subtle"
"fmt"
"log"
"net/http"
"codeberg.org/vlbeaudoin/pave/v2"
2024-09-27 20:25:12 -04:00
"git.agecem.com/agecem/agecem-org/v3/ui"
"git.agecem.com/agecem/agecem-org/v3/ui/public"
2024-08-23 13:54:20 -04:00
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
2024-09-27 20:25:12 -04:00
func RunServer ( cfg Config ) {
2024-08-23 13:54:20 -04:00
e := echo . New ( )
2024-09-27 20:25:12 -04:00
e . Renderer = ui . NewRenderer ( )
2024-08-23 13:54:20 -04:00
e . Pre ( middleware . RemoveTrailingSlash ( ) )
groupStatic := e . Group ( "/public/*" )
groupStatic . Use ( middleware . StaticWithConfig ( middleware . StaticConfig {
Root : "/" ,
2024-09-27 20:25:12 -04:00
Filesystem : http . FS ( public . GetPublicFS ( ) ) ,
2024-08-23 13:54:20 -04:00
//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("/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 )
2024-08-23 14:21:43 -04:00
e . GET ( "/proces-verbaux" , HandlePageProcesVerbaux ( ) )
2024-08-23 13:54:20 -04:00
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 )
e . Logger . Fatal ( e . Start (
fmt . Sprintf ( ":%d" , cfg . Server . Port ) ) )
}