// Package apihandler provides handlers for API routes package apihandler import ( "fmt" "net/http" "git.agecem.com/agecem/bottin-ag/apiresponse" "git.agecem.com/agecem/bottin-ag/dbclient" "git.agecem.com/agecem/bottin-ag/dbstruct" bottindata "git.agecem.com/agecem/bottin/v5/data" "github.com/labstack/echo/v4" ) // DeclareRoutes declares the API server endpoints for the specified Group func DeclareRoutes(e *echo.Group, h *APIHandler) { e.GET("/health/", h.HealthGET) e.GET("/scan/:membre_id/", h.ScanGET) e.POST("/scan/:membre_id/", h.ScanPOST) e.GET("/decompte/", h.DecompteGET) e.GET("/presences/", h.PresencesGET) } /* New retourne un nouveau APIHandler contenant des pointers vers les clients nécessaires à l'exécution du API server */ func New(bottinAPIClient *bottindata.ApiClient, dbClient *dbclient.DBClient) APIHandler { return APIHandler{ BottinAPIClient: bottinAPIClient, DBClient: dbClient, } } /* APIHandler is the struct that implements the actual logic for the API server routes */ type APIHandler struct { BottinAPIClient *bottindata.ApiClient DBClient *dbclient.DBClient } // HealthGET is the handler for `GET /v:version/health/ http/1.1` func (a *APIHandler) HealthGET(c echo.Context) error { var r apiresponse.HealthGET r.Message = "not ok" bottinStatus, err := a.BottinAPIClient.GetHealth() if err != nil { r.StatusCode = http.StatusInternalServerError r.Data.BottinStatus = err.Error() } else { r.Data.BottinStatus = bottinStatus } switch r.Data.BottinStatus { case "Bottin API v5 is ready": r.Message = "ok" r.StatusCode = http.StatusOK default: r.StatusCode = http.StatusInternalServerError } return c.JSON(r.StatusCode, r) } /* ScanGET is the handler for `GET /v{version}/scan/{membre_id}/ http/1.1` It returns the scanned status of a membre, without affecting the database. */ func (a *APIHandler) ScanGET(c echo.Context) error { var r apiresponse.ScanGET r.StatusCode = http.StatusOK membreID := c.Param("membre_id") membre, err := a.BottinAPIClient.GetMembre(membreID) if err != nil { switch err.Error() { case "Ce numéro étudiant ne correspond à aucunE membre": r.Message = fmt.Sprintf("%s n'est pas membre de l'AGECEM", membreID) r.StatusCode = http.StatusNotFound case "Veuillez fournir un numéro étudiant à rechercher": r.Error = "membre_id ne peut pas être vide" r.StatusCode = http.StatusBadRequest r.Message = err.Error() default: r.Error = err.Error() r.Message = "Erreur lors de BottinAPIClient.GetMembre" r.StatusCode = http.StatusInternalServerError return c.JSON(r.StatusCode, r) } } if membre.ID == membreID && membre.ID != "" { r.Message = fmt.Sprintf("%s est membre de l'AGECEM", membreID) } //TODO remplir r.Data.IsScanned return c.JSON(r.StatusCode, r) } // ScanPOST is the handler for `POST /v{version}/scan/{membre_id}/ http/1.1` func (a *APIHandler) ScanPOST(c echo.Context) error { var r apiresponse.ScanPOST membreID := c.Param("membre_id") membre, err := a.BottinAPIClient.GetMembre(membreID) if err != nil { switch err.Error() { case "Ce numéro étudiant ne correspond à aucunE membre": r.Message = fmt.Sprintf("👎 %s n'est pas membre de l'AGECEM", membreID) r.Error = err.Error() r.StatusCode = http.StatusNotFound return c.JSON(r.StatusCode, r) case "Veuillez fournir un numéro étudiant à rechercher": r.Error = "membre_id ne peut pas être vide" r.StatusCode = http.StatusBadRequest r.Message = err.Error() return c.JSON(r.StatusCode, r) default: r.Error = err.Error() r.Message = "Erreur lors de BottinAPIClient.GetMembre" r.StatusCode = http.StatusInternalServerError return c.JSON(r.StatusCode, r) } } var presence dbstruct.Presence presence.ID = membre.ID presence.ProgrammeID = membre.ProgrammeID switch membre.PreferedName != "" { case true: presence.Name = membre.PreferedName case false: presence.Name = fmt.Sprintf("%s, %s", membre.LastName, membre.FirstName) } insertedPresence, err := a.DBClient.InsertPresence(presence) if err != nil { r.Error = err.Error() r.Message = "👎 Erreur lors de DBClient.InsertPresence" r.StatusCode = http.StatusInternalServerError return c.JSON(r.StatusCode, r) } if insertedPresence.ID == "" { r.Error = "Membre déjà enregistré·e" r.Message = fmt.Sprintf("👎 Membre '%s' (%s) déjà enregistré·e.", presence.Name, presence.ID) r.StatusCode = http.StatusBadRequest return c.JSON(r.StatusCode, r) } r.StatusCode = http.StatusOK r.Message = fmt.Sprintf("👍 Membre '%s' (%s) enregistré·e avec succès, veuillez lui donner son carton de vote. Bonne assemblée!", insertedPresence.Name, insertedPresence.ID) return c.JSON(r.StatusCode, r) } // DecompteGET is the handler for `GET /v:version/decompte/ http/1.1` func (a *APIHandler) DecompteGET(c echo.Context) error { var r apiresponse.DecompteGET r.Message = "not ok" decompte, err := a.DBClient.GetDecompte() if err != nil { r.Error = err.Error() r.StatusCode = http.StatusInternalServerError r.Message = "Error during a.DBClient.GetDecompte" return c.JSON(r.StatusCode, r) } r.Data.Decompte = decompte r.StatusCode = http.StatusOK r.Message = "ok" return c.JSON(r.StatusCode, r) } // PresencesGET is the handler for `GET /v:version/presences/ http/1.1` func (a *APIHandler) PresencesGET(c echo.Context) error { var r apiresponse.PresencesGET presences, err := a.DBClient.GetPresences() if err != nil { r.Error = err.Error() r.StatusCode = http.StatusInternalServerError r.Message = "Error during a.DBClient.GetPresences" return c.JSON(r.StatusCode, r) } r.Data.Presences = presences r.StatusCode = http.StatusOK r.Message = "ok" return c.JSON(r.StatusCode, r) }