From 3b320469b592c142335665cbf8cda28471e12dfd Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 16 Dec 2016 00:51:56 +0100 Subject: [PATCH] Use github.com/julienschmidt/httprouter instead of gorilla --- admin/api/certificate.go | 21 +++++----- admin/api/events.go | 6 ++- admin/api/exercice.go | 30 +++++++------- admin/api/file.go | 2 +- admin/api/handlers.go | 85 +++++++++++++++++++++++++-------------- admin/api/router.go | 11 ++--- admin/api/team.go | 87 ++++++++++++++++++---------------------- admin/api/theme.go | 73 ++++++++++++++++----------------- admin/api/version.go | 8 ++-- admin/fill_exercices.sh | 4 +- admin/main.go | 11 ++++- admin/static.go | 44 +++++++++++++++----- admin/static/js/app.js | 16 ++++---- 13 files changed, 226 insertions(+), 172 deletions(-) diff --git a/admin/api/certificate.go b/admin/api/certificate.go index eb9de979..a98a755f 100644 --- a/admin/api/certificate.go +++ b/admin/api/certificate.go @@ -5,25 +5,26 @@ import ( "os" "srs.epita.fr/fic-server/libfic" + + "github.com/julienschmidt/httprouter" ) func init() { - router.Path("/ca").Methods("GET").HandlerFunc(apiHandler(genCA)) + router.GET("/api/ca", apiHandler(genCA)) - rt := router.PathPrefix("/teams/{tid}/certificate").Subrouter() - rt.Path("/").Methods("GET").HandlerFunc(apiHandler(teamHandler(GetTeamCertificate))) - rt.Path("/generate").Methods("GET").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { return team.GenerateCert(), nil }))) - rt.Path("/revoke").Methods("GET").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { return team.RevokeCert(), nil }))) + router.GET("/api/teams/:tid/certificate/", apiHandler(teamHandler(GetTeamCertificate))) + router.GET("/api/teams/:tid/certificate/generate", apiHandler(teamHandler( + func(team fic.Team, _ []byte) (interface{}, error) { return team.GenerateCert(), nil }))) + router.GET("/api/teams/:tid/certificate/revoke", apiHandler(teamHandler( + func(team fic.Team, _ []byte) (interface{}, error) { return team.RevokeCert(), nil }))) } -func genCA(args map[string]string, body []byte) (interface{}, error) { +func genCA(_ httprouter.Params, body []byte) (interface{}, error) { return fic.GenerateCA(), nil } -func GetTeamCertificate(team fic.Team, args map[string]string, body []byte) (interface{}, error) { -if fd, err := os.Open("../PKI/pkcs/" + team.Name + ".p12"); err == nil { +func GetTeamCertificate(team fic.Team, body []byte) (interface{}, error) { + if fd, err := os.Open("../PKI/pkcs/" + team.Name + ".p12"); err == nil { return ioutil.ReadAll(fd) } else { return nil, err diff --git a/admin/api/events.go b/admin/api/events.go index 0a12d588..22972ec0 100644 --- a/admin/api/events.go +++ b/admin/api/events.go @@ -2,13 +2,15 @@ package api import ( "srs.epita.fr/fic-server/libfic" + + "github.com/julienschmidt/httprouter" ) func init() { - router.Path("/events/").Methods("GET").HandlerFunc(apiHandler(getEvents)) + router.GET("/api/events/", apiHandler(getEvents)) } -func getEvents(args map[string]string, body []byte) (interface{}, error) { +func getEvents(_ httprouter.Params, _ []byte) (interface{}, error) { if evts, err := fic.GetEvents(); err != nil { return nil, err } else { diff --git a/admin/api/exercice.go b/admin/api/exercice.go index c4eeba7d..7065f47d 100644 --- a/admin/api/exercice.go +++ b/admin/api/exercice.go @@ -6,27 +6,29 @@ import ( "strconv" "srs.epita.fr/fic-server/libfic" + + "github.com/julienschmidt/httprouter" ) func init() { - router.Path("/exercices/").Methods("GET").HandlerFunc(apiHandler(listExercices)) - re := router.Path("/exercices/{eid:[0-9]+}").Subrouter() - re.Methods("GET").HandlerFunc(apiHandler(exerciceHandler(showExercice))) - re.Methods("PUT").HandlerFunc(apiHandler(updateExercice)) - re.Methods("DELETE").HandlerFunc(apiHandler(deleteExercice)) + router.GET("/api/exercices/", apiHandler(listExercices)) + + router.GET("/api/exercices/:eid", apiHandler(exerciceHandler(showExercice))) + router.PUT("/api/exercices/:eid", apiHandler(updateExercice)) + router.DELETE("/api/exercices/:eid", apiHandler(deleteExercice)) } -func listExercices(args map[string]string, body []byte) (interface{}, error) { +func listExercices(_ httprouter.Params, body []byte) (interface{}, error) { // List all exercices return fic.GetExercices() } -func showExercice(exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func showExercice(exercice fic.Exercice, body []byte) (interface{}, error) { return exercice, nil } -func deleteExercice(args map[string]string, body []byte) (interface{}, error) { - if eid, err := strconv.Atoi(args["eid"]); err != nil { +func deleteExercice(ps httprouter.Params, body []byte) (interface{}, error) { + if eid, err := strconv.Atoi(ps.ByName("eid")); err != nil { return nil, err } else if exercice, err := fic.GetExercice(int64(eid)); err != nil { return nil, err @@ -43,8 +45,8 @@ type uploadedExercice struct { VideoURI string } -func updateExercice(args map[string]string, body []byte) (interface{}, error) { - if eid, err := strconv.Atoi(args["eid"]); err != nil { +func updateExercice(ps httprouter.Params, body []byte) (interface{}, error) { + if eid, err := strconv.Atoi(ps.ByName("eid")); err != nil { return nil, err } else if exercice, err := fic.GetExercice(int64(eid)); err != nil { return nil, err @@ -75,7 +77,7 @@ func updateExercice(args map[string]string, body []byte) (interface{}, error) { } } -func createExercice(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) { +func createExercice(theme fic.Theme, body []byte) (interface{}, error) { // Create a new exercice var ue uploadedExercice if err := json.Unmarshal(body, &ue); err != nil { @@ -103,7 +105,7 @@ type uploadedKey struct { Key string } -func createExerciceKey(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func createExerciceKey(theme fic.Theme, exercice fic.Exercice, body []byte) (interface{}, error) { var uk uploadedKey if err := json.Unmarshal(body, &uk); err != nil { return nil, err @@ -122,7 +124,7 @@ type uploadedHint struct { Cost int64 } -func createExerciceHint(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func createExerciceHint(theme fic.Theme, exercice fic.Exercice, body []byte) (interface{}, error) { var uh uploadedHint if err := json.Unmarshal(body, &uh); err != nil { return nil, err diff --git a/admin/api/file.go b/admin/api/file.go index 34eb8f44..272b3fe3 100644 --- a/admin/api/file.go +++ b/admin/api/file.go @@ -27,7 +27,7 @@ type uploadedFile struct { Parts []string } -func createExerciceFile(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func createExerciceFile(theme fic.Theme, exercice fic.Exercice, body []byte) (interface{}, error) { var uf uploadedFile if err := json.Unmarshal(body, &uf); err != nil { return nil, err diff --git a/admin/api/handlers.go b/admin/api/handlers.go index 649c5b32..70dfe1ee 100644 --- a/admin/api/handlers.go +++ b/admin/api/handlers.go @@ -10,14 +10,14 @@ import ( "srs.epita.fr/fic-server/libfic" - "github.com/gorilla/mux" + "github.com/julienschmidt/httprouter" ) -type DispatchFunction func([]string, []byte) (interface{}, error) +type DispatchFunction func(httprouter.Params, []byte) (interface{}, error) -func apiHandler(f func (map[string]string,[]byte) (interface{}, error)) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { +func apiHandler(f DispatchFunction) func(http.ResponseWriter, *http.Request, httprouter.Params) { + return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { log.Printf("Handling %s request from %s: %s [%s]\n", r.Method, r.RemoteAddr, r.URL.Path, r.UserAgent()) w.Header().Set("Content-Type", "application/json") @@ -44,7 +44,7 @@ func apiHandler(f func (map[string]string,[]byte) (interface{}, error)) func(htt } } - ret, err = f(mux.Vars(r), body) + ret, err = f(ps, body) // Format response resStatus := http.StatusOK @@ -74,58 +74,83 @@ func apiHandler(f func (map[string]string,[]byte) (interface{}, error)) func(htt } } -func teamHandler(f func(fic.Team,map[string]string,[]byte) (interface{}, error)) func (map[string]string,[]byte) (interface{}, error) { - return func (args map[string]string, body []byte) (interface{}, error) { - if tid, err := strconv.Atoi(string(args["tid"])); err != nil { - if team, err := fic.GetTeamByInitialName(args["tid"]); err != nil { +func teamPublicHandler(f func(*fic.Team,[]byte) (interface{}, error)) func (httprouter.Params,[]byte) (interface{}, error) { + return func (ps httprouter.Params, body []byte) (interface{}, error) { + if tid, err := strconv.Atoi(string(ps.ByName("tid"))); err != nil { + if team, err := fic.GetTeamByInitialName(ps.ByName("tid")); err != nil { return nil, err } else { - return f(team, args, body) + return f(&team, body) + } + } else if tid == 0 { + return f(nil, body) + } else if team, err := fic.GetTeam(tid); err != nil { + return nil, err + } else { + return f(&team, body) + } + } +} + +func teamHandler(f func(fic.Team,[]byte) (interface{}, error)) func (httprouter.Params,[]byte) (interface{}, error) { + return func (ps httprouter.Params, body []byte) (interface{}, error) { + if tid, err := strconv.Atoi(string(ps.ByName("tid"))); err != nil { + if team, err := fic.GetTeamByInitialName(ps.ByName("tid")); err != nil { + return nil, err + } else { + return f(team, body) } } else if team, err := fic.GetTeam(tid); err != nil { return nil, err } else { - return f(team, args, body) + return f(team, body) } } } -func themeHandler(f func(fic.Theme,map[string]string,[]byte) (interface{}, error)) func (map[string]string,[]byte) (interface{}, error) { - return func (args map[string]string, body []byte) (interface{}, error) { - if tid, err := strconv.Atoi(string(args["tid"])); err != nil { +func themeHandler(f func(fic.Theme,[]byte) (interface{}, error)) func (httprouter.Params,[]byte) (interface{}, error) { + return func (ps httprouter.Params, body []byte) (interface{}, error) { + if thid, err := strconv.Atoi(string(ps.ByName("thid"))); err != nil { return nil, err - } else if theme, err := fic.GetTheme(tid); err != nil { + } else if theme, err := fic.GetTheme(thid); err != nil { return nil, err } else { - return f(theme, args, body) + return f(theme, body) } } } -func exerciceHandler(f func(fic.Exercice,map[string]string,[]byte) (interface{}, error)) func (map[string]string,[]byte) (interface{}, error) { - return func (args map[string]string, body []byte) (interface{}, error) { - if eid, err := strconv.Atoi(string(args["eid"])); err != nil { +func exerciceHandler(f func(fic.Exercice,[]byte) (interface{}, error)) func (httprouter.Params,[]byte) (interface{}, error) { + return func (ps httprouter.Params, body []byte) (interface{}, error) { + if eid, err := strconv.Atoi(string(ps.ByName("eid"))); err != nil { return nil, err } else if exercice, err := fic.GetExercice(int64(eid)); err != nil { return nil, err } else { - return f(exercice, args, body) + return f(exercice, body) } } } -func themedExerciceHandler(f func(fic.Theme,fic.Exercice,map[string]string,[]byte) (interface{}, error)) func (fic.Theme,map[string]string,[]byte) (interface{}, error) { - return func (theme fic.Theme, args map[string]string, body []byte) (interface{}, error) { - if eid, err := strconv.Atoi(string(args["eid"])); err != nil { - return nil, err - } else if exercice, err := fic.GetExercice(int64(eid)); err != nil { - return nil, err - } else { - return f(theme, exercice, args, body) - } +func themedExerciceHandler(f func(fic.Theme,fic.Exercice,[]byte) (interface{}, error)) func (httprouter.Params,[]byte) (interface{}, error) { + return func (ps httprouter.Params, body []byte) (interface{}, error) { + var theme fic.Theme + var exercice fic.Exercice + + themeHandler(func (th fic.Theme, _[]byte) (interface{}, error) { + theme = th + return nil,nil + })(ps, body) + + exerciceHandler(func (ex fic.Exercice, _[]byte) (interface{}, error) { + exercice = ex + return nil,nil + })(ps, body) + + return f(theme, exercice, body) } } -func notFound(args map[string]string, body []byte) (interface{}, error) { +func notFound(ps httprouter.Params, _ []byte) (interface{}, error) { return nil, nil } diff --git a/admin/api/router.go b/admin/api/router.go index 3c6be0ec..a6bd873b 100644 --- a/admin/api/router.go +++ b/admin/api/router.go @@ -1,14 +1,11 @@ package api import ( - "github.com/gorilla/mux" + "github.com/julienschmidt/httprouter" ) -var api_router = mux.NewRouter().StrictSlash(true) +var router = httprouter.New() -var router = api_router.PathPrefix("/api/").Subrouter() - - -func Router() *mux.Router { - return api_router +func Router() *httprouter.Router { + return router } diff --git a/admin/api/team.go b/admin/api/team.go index 4671f6ec..733fdab7 100644 --- a/admin/api/team.go +++ b/admin/api/team.go @@ -6,66 +6,59 @@ import ( "strings" "srs.epita.fr/fic-server/libfic" + + "github.com/julienschmidt/httprouter" ) func init() { - rts := router.PathPrefix("/teams").Subrouter() - router.Path("/teams.json").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { + router.GET("/api/teams.json", apiHandler( + func(httprouter.Params,[]byte) (interface{}, error) { return fic.ExportTeams() })) - rts.Path("/").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { - return fic.GetTeams() })) - rts.Path("/binding").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { + router.GET("/api/teams-binding", apiHandler( + func(httprouter.Params,[]byte) (interface{}, error) { return bindingTeams() })) - rts.Path("/nginx").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { + router.GET("/api/teams-nginx", apiHandler( + func(httprouter.Params,[]byte) (interface{}, error) { return nginxGenTeam() })) - rts.Path("/nginx-members").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { + router.GET("/api/teams-nginx-members", apiHandler( + func(httprouter.Params,[]byte) (interface{}, error) { return nginxGenMember() })) - rts.Path("/binding").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { + router.GET("/api/teams-tries.json", apiHandler( + func(httprouter.Params,[]byte) (interface{}, error) { return fic.GetTries(nil, nil) })) - rts.Path("/0/my.json").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { - return fic.MyJSONTeam(nil, true) })) - rts.Path("/0/wait.json").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { - return fic.MyJSONTeam(nil, false) })) - rts.Path("/0/stats.json").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { - return fic.GetTeamsStats(nil) })) - rts.Path("/0/tries").Methods("GET").HandlerFunc(apiHandler( - func(map[string]string,[]byte) (interface{}, error) { - return fic.GetTries(nil, nil) })) + router.GET("/api/teams/", apiHandler( + func(httprouter.Params,[]byte) (interface{}, error) { + return fic.GetTeams() })) - rt := rts.PathPrefix("/{tid}").Subrouter() - rt.Path("/").Methods("GET").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { + router.GET("/api/teams/:tid/", apiHandler(teamHandler( + func(team fic.Team, _ []byte) (interface{}, error) { return team, nil }))) - rt.Path("/").Methods("DELETE").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { + router.DELETE("/api/teams/:tid/", apiHandler(teamHandler( + func(team fic.Team, _ []byte) (interface{}, error) { return team.Delete() }))) - rt.Path("/my.json").Methods("GET").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { - return fic.MyJSONTeam(&team, true) }))) - rt.Path("/wait.json").Methods("GET").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { - return fic.MyJSONTeam(&team, false) }))) - rt.Path("/stats.json").Methods("GET").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { - return team.GetStats() }))) - rt.Path("/tries").Methods("GET").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { - return fic.GetTries(&team, nil) }))) - rt.Path("/members").Methods("GET").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { + router.GET("/api/teams/:tid/my.json", apiHandler(teamPublicHandler( + func(team *fic.Team, _ []byte) (interface{}, error) { + return fic.MyJSONTeam(team, true) }))) + router.GET("/api/teams/:tid/wait.json", apiHandler(teamPublicHandler( + func(team *fic.Team, _ []byte) (interface{}, error) { + return fic.MyJSONTeam(team, false) }))) + router.GET("/api/teams/:tid/stats.json", apiHandler(teamPublicHandler( + func(team *fic.Team, _ []byte) (interface{}, error) { + if team != nil { + return team.GetStats() + } else { + return fic.GetTeamsStats(nil) + } + }))) + router.GET("/api/teams/:tid/tries", apiHandler(teamPublicHandler( + func(team *fic.Team, _ []byte) (interface{}, error) { + return fic.GetTries(team, nil) }))) + router.GET("/api/teams/:tid/members", apiHandler(teamHandler( + func(team fic.Team, _ []byte) (interface{}, error) { return team.GetMembers() }))) - rt.Path("/name").Methods("GET").HandlerFunc(apiHandler(teamHandler( - func(team fic.Team, args map[string]string, body []byte) (interface{}, error) { + router.GET("/api/teams/:tid/name", apiHandler(teamHandler( + func(team fic.Team, _ []byte) (interface{}, error) { return team.Name, nil }))) } diff --git a/admin/api/theme.go b/admin/api/theme.go index 7223861f..4720efa5 100644 --- a/admin/api/theme.go +++ b/admin/api/theme.go @@ -7,42 +7,39 @@ import ( "strconv" "srs.epita.fr/fic-server/libfic" + + "github.com/julienschmidt/httprouter" ) func init() { - router.Path("/themes/").Methods("GET").HandlerFunc(apiHandler(listThemes)) - router.Path("/themes/").Methods("POST").HandlerFunc(apiHandler(createTheme)) - router.Path("/themes.json").Methods("GET").HandlerFunc(apiHandler(exportThemes)) - router.Path("/themes/files-bindings").Methods("GET").HandlerFunc(apiHandler(bindingFiles)) + router.GET("/api/themes", apiHandler(listThemes)) + router.POST("/api/themes", apiHandler(createTheme)) + router.GET("/api/themes.json", apiHandler(exportThemes)) + router.GET("/api/files-bindings", apiHandler(bindingFiles)) - rt := router.PathPrefix("/themes/{tid:[0-9]+}").Subrouter() - rt.Path("/").Methods("GET").HandlerFunc(apiHandler(themeHandler(showTheme))) - rt.Path("/").Methods("PUT").HandlerFunc(apiHandler(themeHandler(updateTheme))) - rt.Path("/").Methods("DELETE").HandlerFunc(apiHandler(themeHandler(deleteTheme))) + router.GET("/api/themes/:thid", apiHandler(themeHandler(showTheme))) + router.PUT("/api/themes/:thid", apiHandler(themeHandler(updateTheme))) + router.DELETE("/api/themes/:thid", apiHandler(themeHandler(deleteTheme))) - rtes := rt.PathPrefix("/exercices").Subrouter() - rtes.Path("/").Methods("GET").HandlerFunc(apiHandler(themeHandler(listThemedExercices))) - rtes.Path("/").Methods("POST").HandlerFunc(apiHandler(themeHandler(createExercice))) + router.GET("/api/themes/:thid/exercices", apiHandler(themeHandler(listThemedExercices))) + router.POST("/api/themes/:thid/exercices", apiHandler(themeHandler(createExercice))) - rte := rtes.PathPrefix("/{eid:[0-9]+}").Subrouter() - rte.Path("/").Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(showThemedExercice)))) - rte.Path("/").Methods("PUT").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(updateThemedExercice)))) - rte.Path("/").Methods("DELETE").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(deleteThemedExercice)))) + router.GET("/api/themes/:thid/exercices/:eid", apiHandler(themedExerciceHandler(showThemedExercice))) + router.PUT("/api/themes/:thid/exercices/:eid", apiHandler(themedExerciceHandler(updateThemedExercice))) + router.DELETE("/api/themes/:thid/exercices/:eid", apiHandler(themedExerciceHandler(deleteThemedExercice))) - rtef := rte.Path("/files").Subrouter() - rtef.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceFiles)))) - rtef.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceFile)))) - rteh := rte.Path("/hints").Subrouter() - rteh.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceHints)))) - rteh.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceHint)))) + router.GET("/api/themes/:thid/exercices/:eid/files", apiHandler(themedExerciceHandler(listThemedExerciceFiles))) + router.POST("/api/themes/:thid/exercices/:eid/files", apiHandler(themedExerciceHandler(createExerciceFile))) - rtek := rte.Path("/keys").Subrouter() - rtek.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceKeys)))) - rtek.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceKey)))) + router.GET("/api/themes/:thid/exercices/:eid/hints", apiHandler(themedExerciceHandler(listThemedExerciceHints))) + router.POST("/api/themes/:thid/exercices/:eid/hints", apiHandler(themedExerciceHandler(createExerciceHint))) + + router.GET("/api/themes/:thid/exercices/:eid/keys", apiHandler(themedExerciceHandler(listThemedExerciceKeys))) + router.POST("/api/themes/:thid/exercices/:eid/keys", apiHandler(themedExerciceHandler(createExerciceKey))) } -func bindingFiles(args map[string]string, body []byte) (interface{}, error) { +func bindingFiles(_ httprouter.Params, body []byte) (interface{}, error) { if files, err := fic.GetFiles(); err != nil { return "", err } else { @@ -66,35 +63,35 @@ func getExercice(args []string) (fic.Exercice, error) { } } -func listThemes(args map[string]string, body []byte) (interface{}, error) { +func listThemes(_ httprouter.Params, _ []byte) (interface{}, error) { return fic.GetThemes() } -func exportThemes(args map[string]string, body []byte) (interface{}, error) { +func exportThemes(_ httprouter.Params, _ []byte) (interface{}, error) { return fic.ExportThemes() } -func showTheme(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) { +func showTheme(theme fic.Theme, _ []byte) (interface{}, error) { return theme, nil } -func listThemedExercices(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) { +func listThemedExercices(theme fic.Theme, _ []byte) (interface{}, error) { return theme.GetExercices() } -func showThemedExercice(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func showThemedExercice(theme fic.Theme, exercice fic.Exercice, body []byte) (interface{}, error) { return exercice, nil } -func listThemedExerciceFiles(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func listThemedExerciceFiles(theme fic.Theme, exercice fic.Exercice, body []byte) (interface{}, error) { return exercice.GetFiles() } -func listThemedExerciceHints(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func listThemedExerciceHints(theme fic.Theme, exercice fic.Exercice, body []byte) (interface{}, error) { return exercice.GetHints() } -func listThemedExerciceKeys(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func listThemedExerciceKeys(theme fic.Theme, exercice fic.Exercice, body []byte) (interface{}, error) { return exercice.GetKeys() } @@ -104,7 +101,7 @@ type uploadedTheme struct { Authors string } -func createTheme(args map[string]string, body []byte) (interface{}, error) { +func createTheme(_ httprouter.Params, body []byte) (interface{}, error) { var ut uploadedTheme if err := json.Unmarshal(body, &ut); err != nil { return nil, err @@ -117,7 +114,7 @@ func createTheme(args map[string]string, body []byte) (interface{}, error) { return fic.CreateTheme(ut.Name, ut.Authors) } -func updateTheme(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) { +func updateTheme(theme fic.Theme, body []byte) (interface{}, error) { var ut fic.Theme if err := json.Unmarshal(body, &ut); err != nil { return nil, err @@ -132,7 +129,7 @@ func updateTheme(theme fic.Theme, args map[string]string, body []byte) (interfac return ut.Update() } -func updateThemedExercice(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func updateThemedExercice(theme fic.Theme, exercice fic.Exercice, body []byte) (interface{}, error) { // Update an exercice var ue fic.Exercice if err := json.Unmarshal(body, &ue); err != nil { @@ -152,10 +149,10 @@ func updateThemedExercice(theme fic.Theme, exercice fic.Exercice, args map[strin return ue, nil } -func deleteTheme(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) { +func deleteTheme(theme fic.Theme, _ []byte) (interface{}, error) { return theme.Delete() } -func deleteThemedExercice(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) { +func deleteThemedExercice(_ fic.Theme, exercice fic.Exercice, _ []byte) (interface{}, error) { return exercice.Delete() } diff --git a/admin/api/version.go b/admin/api/version.go index eb5a883a..1386a964 100644 --- a/admin/api/version.go +++ b/admin/api/version.go @@ -1,11 +1,13 @@ package api -import () +import ( + "github.com/julienschmidt/httprouter" +) func init() { - router.Path("/version").Methods("GET").HandlerFunc(apiHandler(showVersion)) + router.GET("/api/version", apiHandler(showVersion)) } -func showVersion(args map[string]string, body []byte) (interface{}, error) { +func showVersion(_ httprouter.Params, body []byte) (interface{}, error) { return map[string]interface{}{"version": 0.1}, nil } diff --git a/admin/fill_exercices.sh b/admin/fill_exercices.sh index 443d10a7..054e47b1 100755 --- a/admin/fill_exercices.sh +++ b/admin/fill_exercices.sh @@ -8,7 +8,7 @@ CLOUDPASS=fic:'f>t\nV33R|(+?$i*' new_theme() { NAME=`echo $1 | sed 's/"/\\\\"/g'` AUTHORS=`echo $2 | sed 's/"/\\\\"/g'` - curl -f -s -d "{\"name\": \"$NAME\", \"authors\": \"$AUTHORS\"}" "${BASEURL}/api/themes/" | + curl -f -s -d "{\"name\": \"$NAME\", \"authors\": \"$AUTHORS\"}" "${BASEURL}/api/themes" | grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+" } @@ -20,7 +20,7 @@ new_exercice() { GAIN="$5" VIDEO="$6" - curl -f -s -d "{\"title\": \"$TITLE\", \"statement\": \"$STATEMENT\", \"depend\": $DEPEND, \"gain\": $GAIN, \"videoURI\": \"$VIDEO\"}" "${BASEURL}/api/themes/$THEME/exercices/" | + curl -f -s -d "{\"title\": \"$TITLE\", \"statement\": \"$STATEMENT\", \"depend\": $DEPEND, \"gain\": $GAIN, \"videoURI\": \"$VIDEO\"}" "${BASEURL}/api/themes/$THEME/exercices" | grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+" } diff --git a/admin/main.go b/admin/main.go index 8e7c47ef..273bb65d 100644 --- a/admin/main.go +++ b/admin/main.go @@ -51,6 +51,13 @@ func main() { if fic.FilesDir, err = filepath.Abs(fic.FilesDir); err != nil { log.Fatal(err) } + if *baseURL != "/" { + tmp := path.Clean(*baseURL) + baseURL = &tmp + } else { + tmp := "" + baseURL = &tmp + } log.Println("Opening database...") if err := fic.DBInit(fmt.Sprintf("%s?parseTime=true", *dsn)); err != nil { @@ -63,12 +70,12 @@ func main() { log.Fatal("Cannot create database: ", err) } - log.Println("Changing base url...") + log.Println("Changing base URL to", *baseURL,"...") if file, err := os.OpenFile(path.Join(StaticDir, "index.html"), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0644)); err != nil { log.Println("Unable to open index.html: ", err) } else if indexTmpl, err := template.New("index").Parse(indextpl); err != nil { log.Println("Cannot create template: ", err) - } else if err := indexTmpl.Execute(file, map[string]string{"urlbase": path.Clean(path.Join(baseURL + "/", "nuke"))[:len(path.Clean(path.Join(baseURL + "/", "nuke"))) - 4]}); err != nil { + } else if err := indexTmpl.Execute(file, map[string]string{"urlbase": path.Clean(path.Join(*baseURL + "/", "nuke"))[:len(path.Clean(path.Join(*baseURL + "/", "nuke"))) - 4]}); err != nil { log.Println("An error occurs during template execution: ", err) } diff --git a/admin/static.go b/admin/static.go index 6c7b7cc6..10fe5417 100644 --- a/admin/static.go +++ b/admin/static.go @@ -3,16 +3,42 @@ package main import ( "net/http" "path" + + "srs.epita.fr/fic-server/admin/api" + + "github.com/julienschmidt/httprouter" ) -type staticRouting struct { - StaticDir string -} +func init() { + api.Router().GET("/", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, "index.html")) + }) + api.Router().GET("/exercices/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, "index.html")) + }) + api.Router().GET("/events/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, "index.html")) + }) + api.Router().GET("/teams/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, "index.html")) + }) + api.Router().GET("/themes/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, "index.html")) + }) -func StaticHandler(staticDir string) http.Handler { - return staticRouting{staticDir} -} - -func (a staticRouting) ServeHTTP(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, path.Join(a.StaticDir, "index.html")) + api.Router().GET("/css/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, r.URL.Path)) + }) + api.Router().GET("/fonts/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, r.URL.Path)) + }) + api.Router().GET("/img/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, r.URL.Path)) + }) + api.Router().GET("/js/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, r.URL.Path)) + }) + api.Router().GET("/views/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + http.ServeFile(w, r, path.Join(StaticDir, r.URL.Path)) + }) } diff --git a/admin/static/js/app.js b/admin/static/js/app.js index f1d0301a..8c4efd27 100644 --- a/admin/static/js/app.js +++ b/admin/static/js/app.js @@ -37,7 +37,7 @@ angular.module("FICApp") }) .factory("Team", function($resource) { return $resource("/api/teams/:teamId", { teamId: '@id' }, { - 'save': {method: 'PATCH'}, + 'update': {method: 'PUT'}, }) }) .factory("TeamMember", function($resource) { @@ -47,7 +47,7 @@ angular.module("FICApp") return $resource("/api/teams/:teamId/my.json", { teamId: '@id' }) }) .factory("Teams", function($resource) { - return $resource("/api/teams/teams.json") + return $resource("/api/teams.json") }) .factory("TeamStats", function($resource) { return $resource("/api/teams/:teamId/stats.json", { teamId: '@id' }) @@ -56,17 +56,19 @@ angular.module("FICApp") return $resource("/api/teams/:teamId/tries", { teamId: '@id' }) }) .factory("Theme", function($resource) { - return $resource("/api/themes/:themeId", null, { - 'save': {method: 'PATCH'}, - }) + return $resource("/api/themes/:themeId", { themeId: '@id' }, { + update: {method: 'PUT'} + }); }) .factory("Themes", function($resource) { - return $resource("/api/themes/themes.json", null, { + return $resource("/api/themes.json", null, { 'get': {method: 'GET'}, }) }) .factory("Exercice", function($resource) { - return $resource("/api/exercices/:exerciceId") + return $resource("/api/exercices/:exerciceId", { exerciceId: '@id' }, { + update: {method: 'PUT'} + }) }); String.prototype.capitalize = function() {