admin: Use gin-gonic as router
This commit is contained in:
parent
83468ad723
commit
8b3fbdb64a
32 changed files with 2785 additions and 1635 deletions
|
@ -1,171 +1,75 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"srs.epita.fr/fic-server/admin/sync"
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
"srs.epita.fr/fic-server/settings"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func init() {
|
||||
router.GET("/api/themes", apiHandler(listThemes))
|
||||
router.POST("/api/themes", apiHandler(createTheme))
|
||||
router.GET("/api/themes.json", apiHandler(exportThemes))
|
||||
router.GET("/api/session-forensic.yaml", apiHandler(func(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
func declareThemesRoutes(router *gin.RouterGroup) {
|
||||
router.GET("/themes", listThemes)
|
||||
router.POST("/themes", createTheme)
|
||||
router.GET("/themes.json", exportThemes)
|
||||
router.GET("/session-forensic.yaml", func(c *gin.Context) {
|
||||
if s, err := settings.ReadSettings(path.Join(settings.SettingsDir, settings.SettingsFile)); err != nil {
|
||||
return nil, err
|
||||
} else if c, err := settings.ReadChallengeInfo(path.Join(settings.SettingsDir, settings.ChallengeFile)); err != nil {
|
||||
return nil, err
|
||||
log.Printf("Unable to ReadSettings: %s", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during settings reading."})
|
||||
return
|
||||
} else if ch, err := settings.ReadChallengeInfo(path.Join(settings.SettingsDir, settings.ChallengeFile)); err != nil {
|
||||
log.Printf("Unable to ReadChallengeInfo: %s", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during challenge info reading."})
|
||||
return
|
||||
} else if sf, err := fic.GenZQDSSessionFile(ch, s); err != nil {
|
||||
log.Printf("Unable to GenZQDSSessionFile: %s", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during session file generation."})
|
||||
return
|
||||
} else {
|
||||
return fic.GenZQDSSessionFile(c, s)
|
||||
c.JSON(http.StatusOK, sf)
|
||||
}
|
||||
}))
|
||||
router.GET("/api/files-bindings", apiHandler(bindingFiles))
|
||||
})
|
||||
router.GET("/files-bindings", bindingFiles)
|
||||
|
||||
router.GET("/api/themes/:thid", apiHandler(themeHandler(showTheme)))
|
||||
router.PUT("/api/themes/:thid", apiHandler(themeHandler(updateTheme)))
|
||||
router.DELETE("/api/themes/:thid", apiHandler(themeHandler(deleteTheme)))
|
||||
apiThemesRoutes := router.Group("/themes/:thid")
|
||||
apiThemesRoutes.Use(ThemeHandler)
|
||||
apiThemesRoutes.GET("", showTheme)
|
||||
apiThemesRoutes.PUT("", updateTheme)
|
||||
apiThemesRoutes.DELETE("", deleteTheme)
|
||||
|
||||
router.GET("/api/themes/:thid/exercices", apiHandler(themeHandler(listThemedExercices)))
|
||||
router.POST("/api/themes/:thid/exercices", apiHandler(themeHandler(createExercice)))
|
||||
|
||||
router.GET("/api/themes/:thid/exercices_stats.json", apiHandler(themeHandler(getThemedExercicesStats)))
|
||||
|
||||
router.GET("/api/themes/:thid/exercices/:eid", apiHandler(exerciceHandler(showExercice)))
|
||||
router.PUT("/api/themes/:thid/exercices/:eid", apiHandler(exerciceHandler(updateExercice)))
|
||||
router.DELETE("/api/themes/:thid/exercices/:eid", apiHandler(exerciceHandler(deleteExercice)))
|
||||
|
||||
router.GET("/api/themes/:thid/exercices/:eid/files", apiHandler(exerciceHandler(listExerciceFiles)))
|
||||
router.POST("/api/themes/:thid/exercices/:eid/files", apiHandler(exerciceHandler(createExerciceFile)))
|
||||
|
||||
router.GET("/api/themes/:thid/exercices/:eid/hints", apiHandler(exerciceHandler(listExerciceHints)))
|
||||
router.POST("/api/themes/:thid/exercices/:eid/hints", apiHandler(exerciceHandler(createExerciceHint)))
|
||||
|
||||
router.GET("/api/themes/:thid/exercices/:eid/keys", apiHandler(exerciceHandler(listExerciceFlags)))
|
||||
router.POST("/api/themes/:thid/exercices/:eid/keys", apiHandler(exerciceHandler(createExerciceFlag)))
|
||||
declareExercicesRoutes(apiThemesRoutes)
|
||||
|
||||
// Remote
|
||||
router.GET("/api/remote/themes", apiHandler(sync.ApiListRemoteThemes))
|
||||
router.GET("/api/remote/themes/:thid", apiHandler(sync.ApiGetRemoteTheme))
|
||||
router.GET("/api/remote/themes/:thid/exercices", apiHandler(sync.ApiListRemoteExercices))
|
||||
|
||||
// Synchronize
|
||||
router.GET("/api/sync/deep", apiHandler(
|
||||
func(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
if sync.DeepSyncProgress == 0 {
|
||||
return nil, errors.New("Pas de synchronisation en cours")
|
||||
} else {
|
||||
return map[string]interface{}{"progress": sync.DeepSyncProgress}, nil
|
||||
}
|
||||
}))
|
||||
router.POST("/api/sync/base", apiHandler(
|
||||
func(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
err := sync.GlobalImporter.Sync()
|
||||
return true, err
|
||||
}))
|
||||
router.POST("/api/sync/speed", apiHandler(
|
||||
func(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
st := sync.SpeedySyncDeep(sync.GlobalImporter)
|
||||
sync.EditDeepReport(st, false)
|
||||
return st, nil
|
||||
}))
|
||||
router.POST("/api/sync/deep", apiHandler(
|
||||
func(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
return sync.SyncDeep(sync.GlobalImporter), nil
|
||||
}))
|
||||
router.POST("/api/sync/deep/:thid", apiHandler(themeHandler(
|
||||
func(theme *fic.Theme, _ []byte) (interface{}, error) {
|
||||
st := sync.SyncThemeDeep(sync.GlobalImporter, theme, 0, 250)
|
||||
sync.EditDeepReport(map[string][]string{theme.Name: st}, false)
|
||||
sync.DeepSyncProgress = 255
|
||||
return st, nil
|
||||
})))
|
||||
router.POST("/api/sync/auto/*p", apiHandler(
|
||||
func(ps httprouter.Params, _ []byte) (interface{}, error) {
|
||||
p := strings.TrimPrefix(ps.ByName("p"), "/")
|
||||
|
||||
themes, err := fic.GetThemes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if p == "" {
|
||||
if !IsProductionEnv {
|
||||
for _, theme := range themes {
|
||||
theme.DeleteDeep()
|
||||
}
|
||||
}
|
||||
|
||||
st := sync.SyncDeep(sync.GlobalImporter)
|
||||
return st, nil
|
||||
}
|
||||
|
||||
for _, theme := range themes {
|
||||
if theme.Path == p {
|
||||
if !IsProductionEnv {
|
||||
exercices, err := theme.GetExercices()
|
||||
if err == nil {
|
||||
for _, exercice := range exercices {
|
||||
exercice.DeleteDeep()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
st := sync.SyncThemeDeep(sync.GlobalImporter, theme, 0, 250)
|
||||
sync.EditDeepReport(map[string][]string{theme.Name: st}, false)
|
||||
sync.DeepSyncProgress = 255
|
||||
|
||||
settings.ForceRegeneration()
|
||||
|
||||
return st, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Theme not found %q", p)
|
||||
}))
|
||||
router.POST("/api/sync/themes", apiHandler(
|
||||
func(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
return sync.SyncThemes(sync.GlobalImporter), nil
|
||||
}))
|
||||
router.POST("/api/sync/themes/:thid/exercices", apiHandler(themeHandler(
|
||||
func(theme *fic.Theme, _ []byte) (interface{}, error) {
|
||||
return sync.SyncExercices(sync.GlobalImporter, theme), nil
|
||||
})))
|
||||
router.POST("/api/sync/themes/:thid/exercices/:eid/files", apiHandler(exerciceHandler(
|
||||
func(exercice *fic.Exercice, _ []byte) (interface{}, error) {
|
||||
return sync.SyncExerciceFiles(sync.GlobalImporter, exercice), nil
|
||||
})))
|
||||
router.POST("/api/sync/themes/:thid/exercices/:eid/hints", apiHandler(exerciceHandler(
|
||||
func(exercice *fic.Exercice, _ []byte) (interface{}, error) {
|
||||
_, errs := sync.SyncExerciceHints(sync.GlobalImporter, exercice, sync.ExerciceFlagsMap(sync.GlobalImporter, exercice))
|
||||
return errs, nil
|
||||
})))
|
||||
router.POST("/api/sync/themes/:thid/exercices/:eid/keys", apiHandler(exerciceHandler(
|
||||
func(exercice *fic.Exercice, _ []byte) (interface{}, error) {
|
||||
_, errs := sync.SyncExerciceFlags(sync.GlobalImporter, exercice)
|
||||
_, herrs := sync.SyncExerciceHints(sync.GlobalImporter, exercice, sync.ExerciceFlagsMap(sync.GlobalImporter, exercice))
|
||||
return append(errs, herrs...), nil
|
||||
})))
|
||||
|
||||
router.POST("/api/sync/themes/:thid/fixurlid", apiHandler(themeHandler(
|
||||
func(theme *fic.Theme, _ []byte) (interface{}, error) {
|
||||
if theme.FixURLId() {
|
||||
return theme.Update()
|
||||
}
|
||||
return 0, nil
|
||||
})))
|
||||
router.POST("/api/sync/fixurlids", apiHandler(fixAllURLIds))
|
||||
router.GET("/remote/themes", sync.ApiListRemoteThemes)
|
||||
router.GET("/remote/themes/:thid", sync.ApiGetRemoteTheme)
|
||||
router.GET("/remote/themes/:thid/exercices", sync.ApiListRemoteExercices)
|
||||
}
|
||||
|
||||
func fixAllURLIds(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
func ThemeHandler(c *gin.Context) {
|
||||
thid, err := strconv.ParseInt(string(c.Params.ByName("thid")), 10, 64)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Invalid theme identifier"})
|
||||
return
|
||||
}
|
||||
|
||||
theme, err := fic.GetTheme(thid)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Theme not found"})
|
||||
return
|
||||
}
|
||||
|
||||
c.Set("theme", theme)
|
||||
|
||||
c.Next()
|
||||
}
|
||||
|
||||
func fixAllURLIds(c *gin.Context) {
|
||||
nbFix := 0
|
||||
if themes, err := fic.GetThemes(); err == nil {
|
||||
for _, theme := range themes {
|
||||
|
@ -185,19 +89,22 @@ func fixAllURLIds(_ httprouter.Params, _ []byte) (interface{}, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return nbFix, nil
|
||||
c.JSON(http.StatusOK, nbFix)
|
||||
}
|
||||
|
||||
func bindingFiles(_ httprouter.Params, body []byte) (interface{}, error) {
|
||||
if files, err := fic.GetFiles(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
ret := ""
|
||||
for _, file := range files {
|
||||
ret += fmt.Sprintf("%s;%s\n", file.GetOrigin(), file.Path)
|
||||
}
|
||||
return ret, nil
|
||||
func bindingFiles(c *gin.Context) {
|
||||
files, err := fic.GetFiles()
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
ret := ""
|
||||
for _, file := range files {
|
||||
ret += fmt.Sprintf("%s;%s\n", file.GetOrigin(), file.Path)
|
||||
}
|
||||
|
||||
c.String(http.StatusOK, ret)
|
||||
}
|
||||
|
||||
func getExercice(args []string) (*fic.Exercice, error) {
|
||||
|
@ -212,60 +119,92 @@ func getExercice(args []string) (*fic.Exercice, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func listThemes(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
return fic.GetThemes()
|
||||
func listThemes(c *gin.Context) {
|
||||
themes, err := fic.GetThemes()
|
||||
if err != nil {
|
||||
log.Println("Unable to listThemes:", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when trying to list themes."})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, themes)
|
||||
}
|
||||
|
||||
func exportThemes(_ httprouter.Params, _ []byte) (interface{}, error) {
|
||||
return fic.ExportThemes()
|
||||
func exportThemes(c *gin.Context) {
|
||||
themes, err := fic.ExportThemes()
|
||||
if err != nil {
|
||||
log.Println("Unable to exportthemes:", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when trying to export themes."})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, themes)
|
||||
}
|
||||
|
||||
func showTheme(theme *fic.Theme, _ []byte) (interface{}, error) {
|
||||
return theme, nil
|
||||
func showTheme(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, c.MustGet("theme").(*fic.Theme))
|
||||
}
|
||||
|
||||
func listThemedExercices(theme *fic.Theme, _ []byte) (interface{}, error) {
|
||||
return theme.GetExercices()
|
||||
}
|
||||
|
||||
func showThemedExercice(theme *fic.Theme, exercice fic.Exercice, body []byte) (interface{}, error) {
|
||||
return exercice, nil
|
||||
}
|
||||
|
||||
func createTheme(_ httprouter.Params, body []byte) (interface{}, error) {
|
||||
func createTheme(c *gin.Context) {
|
||||
var ut fic.Theme
|
||||
if err := json.Unmarshal(body, &ut); err != nil {
|
||||
return nil, err
|
||||
err := c.ShouldBindJSON(&ut)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if len(ut.Name) == 0 {
|
||||
return nil, errors.New("Theme's name not filled")
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Theme's name not filled"})
|
||||
return
|
||||
}
|
||||
|
||||
return fic.CreateTheme(&ut)
|
||||
th, err := fic.CreateTheme(&ut)
|
||||
if err != nil {
|
||||
log.Println("Unable to createTheme:", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during theme creation."})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, th)
|
||||
}
|
||||
|
||||
func updateTheme(theme *fic.Theme, body []byte) (interface{}, error) {
|
||||
func updateTheme(c *gin.Context) {
|
||||
theme := c.MustGet("theme").(*fic.Theme)
|
||||
|
||||
var ut fic.Theme
|
||||
if err := json.Unmarshal(body, &ut); err != nil {
|
||||
return nil, err
|
||||
err := c.ShouldBindJSON(&ut)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
ut.Id = theme.Id
|
||||
|
||||
if len(ut.Name) == 0 {
|
||||
return nil, errors.New("Theme's name not filled")
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Theme's name not filled"})
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := ut.Update(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return ut, nil
|
||||
log.Println("Unable to updateTheme:", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "An error occurs during theme update."})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, ut)
|
||||
}
|
||||
|
||||
func deleteTheme(theme *fic.Theme, _ []byte) (interface{}, error) {
|
||||
return theme.Delete()
|
||||
func deleteTheme(c *gin.Context) {
|
||||
theme := c.MustGet("theme").(*fic.Theme)
|
||||
|
||||
_, err := theme.Delete()
|
||||
if err != nil {
|
||||
log.Println("Unable to deleteTheme:", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "An error occurs during theme deletion."})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, true)
|
||||
}
|
||||
|
||||
func getThemedExercicesStats(theme *fic.Theme, body []byte) (interface{}, error) {
|
||||
|
|
Reference in a new issue