admin/api: use gorilla/mux instead of Go router
This commit is contained in:
parent
e2593e5f24
commit
972503292d
102
admin/api.go
102
admin/api.go
|
@ -1,102 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DispatchFunction func([]string, []byte) (interface{}, error)
|
||||
|
||||
var apiRoutes = map[string]*(map[string]DispatchFunction){
|
||||
"version": &ApiVersionRouting,
|
||||
"ca": &ApiCARouting,
|
||||
"events": &ApiEventsRouting,
|
||||
"exercices": &ApiExercicesRouting,
|
||||
"themes": &ApiThemesRouting,
|
||||
"teams": &ApiTeamsRouting,
|
||||
}
|
||||
|
||||
type apiRouting struct{}
|
||||
|
||||
func ApiHandler() http.Handler {
|
||||
return apiRouting{}
|
||||
}
|
||||
|
||||
func (a apiRouting) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("Handling %s request from %s: %s [%s]\n", r.Method, r.RemoteAddr, r.URL.Path, r.UserAgent())
|
||||
|
||||
// Extract URL arguments
|
||||
var sURL = strings.Split(r.URL.Path, "/")[1:]
|
||||
if len(sURL) > 1 && sURL[len(sURL)-1] == "" {
|
||||
// Remove trailing /
|
||||
sURL = sURL[:len(sURL)-1]
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
var ret interface{}
|
||||
var err error = nil
|
||||
|
||||
// Read the body
|
||||
if r.ContentLength < 0 || r.ContentLength > 6553600 {
|
||||
http.Error(w, fmt.Sprintf("{errmsg:\"Request too large or request size unknown\"}", err), http.StatusRequestEntityTooLarge)
|
||||
return
|
||||
}
|
||||
var body []byte
|
||||
if r.ContentLength > 0 {
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
n, err := r.Body.Read(tmp)
|
||||
for j := 0; j < n; j++ {
|
||||
body = append(body, tmp[j])
|
||||
}
|
||||
if err != nil || n <= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Route request
|
||||
if len(sURL) > 0 {
|
||||
if h, ok := apiRoutes[sURL[0]]; ok {
|
||||
if f, ok := (*h)[r.Method]; ok {
|
||||
ret, err = f(sURL[1:], body)
|
||||
} else {
|
||||
err = errors.New(fmt.Sprintf("Invalid action (%s) provided for %s.", r.Method, sURL[0]))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = errors.New("No action provided.")
|
||||
}
|
||||
|
||||
// Format response
|
||||
resStatus := http.StatusOK
|
||||
if err != nil {
|
||||
ret = map[string]string{"errmsg": err.Error()}
|
||||
resStatus = http.StatusBadRequest
|
||||
log.Println(r.RemoteAddr, resStatus, err.Error())
|
||||
}
|
||||
|
||||
if ret == nil {
|
||||
ret = map[string]string{"errmsg": "Page not found"}
|
||||
resStatus = http.StatusNotFound
|
||||
}
|
||||
|
||||
if str, found := ret.(string); found {
|
||||
w.WriteHeader(resStatus)
|
||||
io.WriteString(w, str)
|
||||
} else if bts, found := ret.([]byte); found {
|
||||
w.WriteHeader(resStatus)
|
||||
w.Write(bts)
|
||||
} else if j, err := json.Marshal(ret); err != nil {
|
||||
http.Error(w, fmt.Sprintf("{\"errmsg\":\"%q\"}", err), http.StatusInternalServerError)
|
||||
} else {
|
||||
w.WriteHeader(resStatus)
|
||||
w.Write(j)
|
||||
}
|
||||
}
|
31
admin/api/certificate.go
Normal file
31
admin/api/certificate.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
router.Path("/ca").Methods("GET").HandlerFunc(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 })))
|
||||
}
|
||||
|
||||
func genCA(args map[string]string, 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 {
|
||||
return ioutil.ReadAll(fd)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
17
admin/api/events.go
Normal file
17
admin/api/events.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
router.Path("/events/").Methods("GET").HandlerFunc(apiHandler(getEvents))
|
||||
}
|
||||
|
||||
func getEvents(args map[string]string, body []byte) (interface{}, error) {
|
||||
if evts, err := fic.GetEvents(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return evts, nil
|
||||
}
|
||||
}
|
117
admin/api/exercice.go
Normal file
117
admin/api/exercice.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
func listExercices(args map[string]string, body []byte) (interface{}, error) {
|
||||
// List all exercices
|
||||
return fic.GetExercices()
|
||||
}
|
||||
|
||||
func showExercice(exercice fic.Exercice, args map[string]string, 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 {
|
||||
return nil, err
|
||||
} else if exercice, err := fic.GetExercice(int64(eid)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return exercice.Delete()
|
||||
}
|
||||
}
|
||||
|
||||
type uploadedExercice struct {
|
||||
Title string
|
||||
Statement string
|
||||
Depend *int64
|
||||
Gain int
|
||||
VideoURI string
|
||||
}
|
||||
|
||||
func updateExercice(args map[string]string, body []byte) (interface{}, error) {
|
||||
if eid, err := strconv.Atoi(args["eid"]); err != nil {
|
||||
return nil, err
|
||||
} else if exercice, err := fic.GetExercice(int64(eid)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
// Update an exercice
|
||||
var ue uploadedExercice
|
||||
if err := json.Unmarshal(body, &ue); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ue.Title) == 0 {
|
||||
return nil, errors.New("Exercice's title not filled")
|
||||
}
|
||||
|
||||
if ue.Depend != nil {
|
||||
if _, err := fic.GetExercice(*ue.Depend); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
exercice.Title = ue.Title
|
||||
exercice.Statement = ue.Statement
|
||||
exercice.Depend = ue.Depend
|
||||
exercice.Gain = int64(ue.Gain)
|
||||
exercice.VideoURI = ue.VideoURI
|
||||
|
||||
return exercice.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func createExercice(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) {
|
||||
// Create a new exercice
|
||||
var ue uploadedExercice
|
||||
if err := json.Unmarshal(body, &ue); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ue.Title) == 0 {
|
||||
return nil, errors.New("Title not filled")
|
||||
}
|
||||
|
||||
var depend *fic.Exercice = nil
|
||||
if ue.Depend != nil {
|
||||
if d, err := fic.GetExercice(*ue.Depend); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
depend = &d
|
||||
}
|
||||
}
|
||||
|
||||
return theme.AddExercice(ue.Title, ue.Statement, depend, ue.Gain, ue.VideoURI)
|
||||
}
|
||||
|
||||
type uploadedKey struct {
|
||||
Name string
|
||||
Key string
|
||||
}
|
||||
|
||||
func createExerciceKey(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||
var uk uploadedKey
|
||||
if err := json.Unmarshal(body, &uk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(uk.Key) == 0 {
|
||||
return nil, errors.New("Key not filled")
|
||||
}
|
||||
|
||||
return exercice.AddRawKey(uk.Name, uk.Key)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -15,7 +15,11 @@ import (
|
|||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
func createExerciceFile(theme fic.Theme, exercice fic.Exercice, args []string, body []byte) (interface{}, error) {
|
||||
var CloudDAVBase string
|
||||
var CloudUsername string
|
||||
var CloudPassword string
|
||||
|
||||
func createExerciceFile(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||
var uf map[string]string
|
||||
if err := json.Unmarshal(body, &uf); err != nil {
|
||||
return nil, err
|
131
admin/api/handlers.go
Normal file
131
admin/api/handlers.go
Normal file
|
@ -0,0 +1,131 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
|
||||
type DispatchFunction func([]string, []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) {
|
||||
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")
|
||||
|
||||
var ret interface{}
|
||||
var err error = nil
|
||||
|
||||
// Read the body
|
||||
if r.ContentLength < 0 || r.ContentLength > 6553600 {
|
||||
http.Error(w, fmt.Sprintf("{errmsg:\"Request too large or request size unknown\"}", err), http.StatusRequestEntityTooLarge)
|
||||
return
|
||||
}
|
||||
var body []byte
|
||||
if r.ContentLength > 0 {
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
n, err := r.Body.Read(tmp)
|
||||
for j := 0; j < n; j++ {
|
||||
body = append(body, tmp[j])
|
||||
}
|
||||
if err != nil || n <= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret, err = f(mux.Vars(r), body)
|
||||
|
||||
// Format response
|
||||
resStatus := http.StatusOK
|
||||
if err != nil {
|
||||
ret = map[string]string{"errmsg": err.Error()}
|
||||
resStatus = http.StatusBadRequest
|
||||
log.Println(r.RemoteAddr, resStatus, err.Error())
|
||||
}
|
||||
|
||||
if ret == nil {
|
||||
ret = map[string]string{"errmsg": "Page not found"}
|
||||
resStatus = http.StatusNotFound
|
||||
}
|
||||
|
||||
if str, found := ret.(string); found {
|
||||
w.WriteHeader(resStatus)
|
||||
io.WriteString(w, str)
|
||||
} else if bts, found := ret.([]byte); found {
|
||||
w.WriteHeader(resStatus)
|
||||
w.Write(bts)
|
||||
} else if j, err := json.Marshal(ret); err != nil {
|
||||
http.Error(w, fmt.Sprintf("{\"errmsg\":\"%q\"}", err), http.StatusInternalServerError)
|
||||
} else {
|
||||
w.WriteHeader(resStatus)
|
||||
w.Write(j)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
} else {
|
||||
return f(team, args, body)
|
||||
}
|
||||
} else if team, err := fic.GetTeam(tid); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return f(team, args, 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 {
|
||||
return nil, err
|
||||
} else if theme, err := fic.GetTheme(tid); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return f(theme, args, 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 {
|
||||
return nil, err
|
||||
} else if exercice, err := fic.GetExercice(int64(eid)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return f(exercice, args, 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 notFound(args map[string]string, body []byte) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
14
admin/api/router.go
Normal file
14
admin/api/router.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var api_router = mux.NewRouter().StrictSlash(true)
|
||||
|
||||
var router = api_router.PathPrefix("/api/").Subrouter()
|
||||
|
||||
|
||||
func Router() *mux.Router {
|
||||
return api_router
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
156
admin/api/team.go
Normal file
156
admin/api/team.go
Normal file
|
@ -0,0 +1,156 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rts := router.PathPrefix("/teams").Subrouter()
|
||||
router.Path("/teams.json").Methods("GET").HandlerFunc(apiHandler(
|
||||
func(map[string]string,[]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) {
|
||||
return bindingTeams() }))
|
||||
rts.Path("/nginx").Methods("GET").HandlerFunc(apiHandler(
|
||||
func(map[string]string,[]byte) (interface{}, error) {
|
||||
return nginxGenTeam() }))
|
||||
rts.Path("/nginx-members").Methods("GET").HandlerFunc(apiHandler(
|
||||
func(map[string]string,[]byte) (interface{}, error) {
|
||||
return nginxGenMember() }))
|
||||
rts.Path("/binding").Methods("GET").HandlerFunc(apiHandler(
|
||||
func(map[string]string,[]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) }))
|
||||
|
||||
rt := rts.PathPrefix("/{tid}").Subrouter()
|
||||
rt.Path("/").Methods("GET").HandlerFunc(apiHandler(teamHandler(
|
||||
func(team fic.Team, args map[string]string, body []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) {
|
||||
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) {
|
||||
return team.GetMembers() })))
|
||||
rt.Path("/name").Methods("GET").HandlerFunc(apiHandler(teamHandler(
|
||||
func(team fic.Team, args map[string]string, body []byte) (interface{}, error) {
|
||||
return team.Name, nil })))
|
||||
}
|
||||
|
||||
func nginxGenMember() (string, error) {
|
||||
if teams, err := fic.GetTeams(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
ret := ""
|
||||
for _, team := range teams {
|
||||
if members, err := team.GetMembers(); err == nil {
|
||||
for _, member := range members {
|
||||
ret += fmt.Sprintf(" if ($remote_user = \"%s\") { set $team \"%s\"; }\n", member.Nickname, team.InitialName)
|
||||
}
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
func nginxGenTeam() (string, error) {
|
||||
if teams, err := fic.GetTeams(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
ret := ""
|
||||
for _, team := range teams {
|
||||
ret += fmt.Sprintf(" if ($ssl_client_s_dn ~ \"/C=FR/ST=France/O=Epita/OU=SRS/CN=%s\") { set $team \"%s\"; }\n", team.InitialName, team.InitialName)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
func bindingTeams() (string, error) {
|
||||
if teams, err := fic.GetTeams(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
ret := ""
|
||||
for _, team := range teams {
|
||||
if members, err := team.GetMembers(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
var mbs []string
|
||||
for _, member := range members {
|
||||
mbs = append(mbs, fmt.Sprintf("%s %s", member.Firstname, member.Lastname))
|
||||
}
|
||||
ret += fmt.Sprintf("%d;%s;%s\n", team.Id, team.Name, strings.Join(mbs, ";"))
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
type uploadedTeam struct {
|
||||
Name string
|
||||
Color uint32
|
||||
}
|
||||
|
||||
type uploadedMember struct {
|
||||
Firstname string
|
||||
Lastname string
|
||||
Nickname string
|
||||
Company string
|
||||
}
|
||||
|
||||
func createTeam(args map[string]string, body []byte) (interface{}, error) {
|
||||
var ut uploadedTeam
|
||||
if err := json.Unmarshal(body, &ut); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return fic.CreateTeam(ut.Name, ut.Color)
|
||||
}
|
||||
|
||||
func addTeamMember(team fic.Team, args map[string]string, body []byte) (interface{}, error) {
|
||||
var members []uploadedMember
|
||||
if err := json.Unmarshal(body, &members); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, member := range members {
|
||||
team.AddMember(member.Firstname, member.Lastname, member.Nickname, member.Company)
|
||||
}
|
||||
|
||||
return team.GetMembers()
|
||||
}
|
153
admin/api/theme.go
Normal file
153
admin/api/theme.go
Normal file
|
@ -0,0 +1,153 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
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))
|
||||
|
||||
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)))
|
||||
|
||||
rtes := rt.PathPrefix("/exercices").Subrouter()
|
||||
rtes.Path("/").Methods("GET").HandlerFunc(apiHandler(themeHandler(listThemedExercices)))
|
||||
rtes.Path("/").Methods("POST").HandlerFunc(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))))
|
||||
|
||||
rtef := rte.Path("/files").Subrouter()
|
||||
rtef.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceFiles))))
|
||||
rtef.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceFile))))
|
||||
|
||||
rtek := rte.Path("/keys").Subrouter()
|
||||
rtek.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceKeys))))
|
||||
rtek.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceKey))))
|
||||
}
|
||||
|
||||
func bindingFiles(args map[string]string, 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 getExercice(args []string) (fic.Exercice, error) {
|
||||
if tid, err := strconv.Atoi(string(args[0])); err != nil {
|
||||
return fic.Exercice{}, err
|
||||
} else if theme, err := fic.GetTheme(tid); err != nil {
|
||||
return fic.Exercice{}, err
|
||||
} else if eid, err := strconv.Atoi(string(args[1])); err != nil {
|
||||
return fic.Exercice{}, err
|
||||
} else {
|
||||
return theme.GetExercice(eid)
|
||||
}
|
||||
}
|
||||
|
||||
func listThemes(args map[string]string, body []byte) (interface{}, error) {
|
||||
return fic.GetThemes()
|
||||
}
|
||||
|
||||
func exportThemes(args map[string]string, body []byte) (interface{}, error) {
|
||||
return fic.ExportThemes()
|
||||
}
|
||||
|
||||
func showTheme(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) {
|
||||
return theme, nil
|
||||
}
|
||||
|
||||
func listThemedExercices(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) {
|
||||
return theme.GetExercices()
|
||||
}
|
||||
|
||||
func showThemedExercice(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||
return exercice, nil
|
||||
}
|
||||
|
||||
func listThemedExerciceFiles(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||
return exercice.GetFiles()
|
||||
}
|
||||
|
||||
func listThemedExerciceKeys(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||
return exercice.GetKeys()
|
||||
}
|
||||
|
||||
|
||||
type uploadedTheme struct {
|
||||
Name string
|
||||
Authors string
|
||||
}
|
||||
|
||||
func createTheme(args map[string]string, body []byte) (interface{}, error) {
|
||||
var ut uploadedTheme
|
||||
if err := json.Unmarshal(body, &ut); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ut.Name) == 0 {
|
||||
return nil, errors.New("Theme's name not filled")
|
||||
}
|
||||
|
||||
return fic.CreateTheme(ut.Name, ut.Authors)
|
||||
}
|
||||
|
||||
func updateTheme(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) {
|
||||
var ut fic.Theme
|
||||
if err := json.Unmarshal(body, &ut); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ut.Id = theme.Id
|
||||
|
||||
if len(ut.Name) == 0 {
|
||||
return nil, errors.New("Theme's name not filled")
|
||||
}
|
||||
|
||||
return ut.Update()
|
||||
}
|
||||
|
||||
func updateThemedExercice(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||
// Update an exercice
|
||||
var ue fic.Exercice
|
||||
if err := json.Unmarshal(body, &ue); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ue.Id = exercice.Id
|
||||
|
||||
if len(ue.Title) == 0 {
|
||||
return nil, errors.New("Exercice's title not filled")
|
||||
}
|
||||
|
||||
if _, err := ue.Update(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ue, nil
|
||||
}
|
||||
|
||||
func deleteTheme(theme fic.Theme, args map[string]string, body []byte) (interface{}, error) {
|
||||
return theme.Delete()
|
||||
}
|
||||
|
||||
func deleteThemedExercice(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||
return exercice.Delete()
|
||||
}
|
11
admin/api/version.go
Normal file
11
admin/api/version.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package api
|
||||
|
||||
import ()
|
||||
|
||||
func init() {
|
||||
router.Path("/version").Methods("GET").HandlerFunc(apiHandler(showVersion))
|
||||
}
|
||||
|
||||
func showVersion(args map[string]string, body []byte) (interface{}, error) {
|
||||
return map[string]interface{}{"version": 0.1}, nil
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
func CertificateAPI(team fic.Team, args []string) (interface{}, error) {
|
||||
if len(args) == 1 {
|
||||
if args[0] == "generate" {
|
||||
return team.GenerateCert(), nil
|
||||
} else if args[0] == "revoke" {
|
||||
return team.RevokeCert(), nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
} else if fd, err := os.Open("../PKI/pkcs/" + team.Name + ".p12"); err == nil {
|
||||
return ioutil.ReadAll(fd)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var ApiCARouting = map[string]DispatchFunction{
|
||||
"GET": genCA,
|
||||
}
|
||||
|
||||
func genCA(args []string, body []byte) (interface{}, error) {
|
||||
return fic.GenerateCA(), nil
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
var ApiEventsRouting = map[string]DispatchFunction{
|
||||
"GET": getEvents,
|
||||
}
|
||||
|
||||
func getEvents(args []string, body []byte) (interface{}, error) {
|
||||
if evts, err := fic.GetEvents(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return evts, nil
|
||||
}
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
var ApiExercicesRouting = map[string]DispatchFunction{
|
||||
"GET": listExercice,
|
||||
"PATCH": updateExercice,
|
||||
"DELETE": deletionExercice,
|
||||
}
|
||||
|
||||
func listExercice(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) == 1 {
|
||||
if eid, err := strconv.Atoi(string(args[0])); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return fic.GetExercice(int64(eid))
|
||||
}
|
||||
} else {
|
||||
// List all exercices
|
||||
return fic.GetExercices()
|
||||
}
|
||||
}
|
||||
|
||||
func deletionExercice(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) == 1 {
|
||||
if eid, err := strconv.Atoi(string(args[0])); err != nil {
|
||||
return nil, err
|
||||
} else if exercice, err := fic.GetExercice(int64(eid)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return exercice.Delete()
|
||||
}
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
type uploadedExercice struct {
|
||||
Title string
|
||||
Statement string
|
||||
Hint string
|
||||
Depend *int64
|
||||
Gain int
|
||||
VideoURI string
|
||||
}
|
||||
|
||||
func updateExercice(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) == 1 {
|
||||
if eid, err := strconv.Atoi(string(args[0])); err != nil {
|
||||
return nil, err
|
||||
} else if exercice, err := fic.GetExercice(int64(eid)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
// Update an exercice
|
||||
var ue uploadedExercice
|
||||
if err := json.Unmarshal(body, &ue); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ue.Title) == 0 {
|
||||
return nil, errors.New("Exercice's title not filled")
|
||||
}
|
||||
|
||||
if ue.Depend != nil {
|
||||
if _, err := fic.GetExercice(*ue.Depend); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
exercice.Title = ue.Title
|
||||
exercice.Statement = ue.Statement
|
||||
exercice.Hint = ue.Hint
|
||||
exercice.Depend = ue.Depend
|
||||
exercice.Gain = int64(ue.Gain)
|
||||
exercice.VideoURI = ue.VideoURI
|
||||
|
||||
return exercice.Update()
|
||||
}
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func createExercice(theme fic.Theme, args []string, body []byte) (interface{}, error) {
|
||||
if len(args) >= 1 {
|
||||
if eid, err := strconv.Atoi(args[0]); err != nil {
|
||||
return nil, err
|
||||
} else if exercice, err := theme.GetExercice(eid); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if args[1] == "files" {
|
||||
return createExerciceFile(theme, exercice, args[2:], body)
|
||||
} else if args[1] == "keys" {
|
||||
return createExerciceKey(theme, exercice, args[2:], body)
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
} else {
|
||||
// Create a new exercice
|
||||
var ue uploadedExercice
|
||||
if err := json.Unmarshal(body, &ue); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ue.Title) == 0 {
|
||||
return nil, errors.New("Title not filled")
|
||||
}
|
||||
|
||||
var depend *fic.Exercice = nil
|
||||
if ue.Depend != nil {
|
||||
if d, err := fic.GetExercice(*ue.Depend); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
depend = &d
|
||||
}
|
||||
}
|
||||
|
||||
return theme.AddExercice(ue.Title, ue.Statement, ue.Hint, depend, ue.Gain, ue.VideoURI)
|
||||
}
|
||||
}
|
||||
|
||||
type uploadedKey struct {
|
||||
Name string
|
||||
Key string
|
||||
}
|
||||
|
||||
func createExerciceKey(theme fic.Theme, exercice fic.Exercice, args []string, body []byte) (interface{}, error) {
|
||||
var uk uploadedKey
|
||||
if err := json.Unmarshal(body, &uk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(uk.Key) == 0 {
|
||||
return nil, errors.New("Key not filled")
|
||||
}
|
||||
|
||||
return exercice.AddRawKey(uk.Name, uk.Key)
|
||||
}
|
|
@ -1,231 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
var ApiTeamsRouting = map[string]DispatchFunction{
|
||||
"GET": listTeam,
|
||||
"PUT": creationTeamMembers,
|
||||
"POST": creationTeam,
|
||||
"DELETE": deletionTeam,
|
||||
}
|
||||
|
||||
func nginxGenMember() (string, error) {
|
||||
if teams, err := fic.GetTeams(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
ret := ""
|
||||
for _, team := range teams {
|
||||
if members, err := team.GetMembers(); err == nil {
|
||||
for _, member := range members {
|
||||
ret += fmt.Sprintf(" if ($remote_user = \"%s\") { set $team \"%s\"; }\n", member.Nickname, team.InitialName)
|
||||
}
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
func nginxGenTeam() (string, error) {
|
||||
if teams, err := fic.GetTeams(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
ret := ""
|
||||
for _, team := range teams {
|
||||
ret += fmt.Sprintf(" if ($ssl_client_s_dn ~ \"/C=FR/ST=France/O=Epita/OU=SRS/CN=%s\") { set $team \"%s\"; }\n", team.InitialName, team.InitialName)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
func bindingTeams() (string, error) {
|
||||
if teams, err := fic.GetTeams(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
ret := ""
|
||||
for _, team := range teams {
|
||||
if members, err := team.GetMembers(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
var mbs []string
|
||||
for _, member := range members {
|
||||
mbs = append(mbs, fmt.Sprintf("%s %s", member.Firstname, member.Lastname))
|
||||
}
|
||||
ret += fmt.Sprintf("%d;%s;%s\n", team.Id, team.Name, strings.Join(mbs, ";"))
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
type uploadedTeam struct {
|
||||
Name string
|
||||
Color uint32
|
||||
}
|
||||
|
||||
type uploadedMember struct {
|
||||
Firstname string
|
||||
Lastname string
|
||||
Nickname string
|
||||
Company string
|
||||
}
|
||||
|
||||
func listTeam(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) >= 2 {
|
||||
var team *fic.Team
|
||||
if tid, err := strconv.Atoi(args[0]); err != nil {
|
||||
if t, err := fic.GetTeamByInitialName(args[0]); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
team = &t
|
||||
}
|
||||
} else {
|
||||
if tid == 0 {
|
||||
team = nil
|
||||
} else if t, err := fic.GetTeam(tid); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
team = &t
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if args[1] == "my.json" {
|
||||
return fic.MyJSONTeam(team, true)
|
||||
} else if args[1] == "wait.json" {
|
||||
return fic.MyJSONTeam(team, false)
|
||||
} else if args[1] == "stats.json" {
|
||||
if team != nil {
|
||||
return team.GetStats()
|
||||
} else {
|
||||
return fic.GetTeamsStats(nil)
|
||||
}
|
||||
} else if args[1] == "tries" {
|
||||
return fic.GetTries(team, nil)
|
||||
} else if team != nil && args[1] == "members" {
|
||||
return team.GetMembers()
|
||||
} else if args[1] == "certificate" && team != nil {
|
||||
return CertificateAPI(*team, args[2:])
|
||||
} else if team != nil && args[1] == "name" {
|
||||
return team.Name, nil
|
||||
}
|
||||
} else if len(args) == 1 {
|
||||
if args[0] == "teams.json" {
|
||||
return fic.ExportTeams()
|
||||
} else if args[0] == "tries" {
|
||||
return fic.GetTries(nil, nil)
|
||||
} else if args[0] == "nginx" {
|
||||
return nginxGenTeam()
|
||||
} else if args[0] == "nginx-members" {
|
||||
return nginxGenMember()
|
||||
} else if args[0] == "binding" {
|
||||
return bindingTeams()
|
||||
} else if tid, err := strconv.Atoi(string(args[0])); err != nil {
|
||||
return fic.GetTeamByInitialName(args[0])
|
||||
} else if team, err := fic.GetTeam(tid); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return team, nil
|
||||
}
|
||||
} else if len(args) == 0 {
|
||||
// List all teams
|
||||
return fic.GetTeams()
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func creationTeam(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) == 1 {
|
||||
// List given team
|
||||
if tid, err := strconv.Atoi(string(args[0])); err != nil {
|
||||
return nil, err
|
||||
} else if team, err := fic.GetTeam(tid); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
var members []uploadedMember
|
||||
if err := json.Unmarshal(body, &members); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, member := range members {
|
||||
team.AddMember(member.Firstname, member.Lastname, member.Nickname, member.Company)
|
||||
}
|
||||
|
||||
return team.GetMembers()
|
||||
}
|
||||
} else if len(args) == 0 {
|
||||
// Create a new team
|
||||
var ut uploadedTeam
|
||||
if err := json.Unmarshal(body, &ut); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return fic.CreateTeam(ut.Name, ut.Color)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func creationTeamMembers(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) == 1 {
|
||||
// List given team
|
||||
if tid, err := strconv.Atoi(string(args[0])); err != nil {
|
||||
return nil, err
|
||||
} else if team, err := fic.GetTeam(tid); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
var member uploadedMember
|
||||
if err := json.Unmarshal(body, &member); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
team.AddMember(member.Firstname, member.Lastname, member.Nickname, member.Company)
|
||||
|
||||
return team.GetMembers()
|
||||
}
|
||||
} else if len(args) == 0 {
|
||||
// Create a new team
|
||||
var members []uploadedMember
|
||||
if err := json.Unmarshal(body, &members); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if team, err := fic.CreateTeam("", 0); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
for _, member := range members {
|
||||
if _, err := team.AddMember(member.Firstname, member.Lastname, member.Nickname, member.Company); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return team, nil
|
||||
}
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func deletionTeam(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) == 1 {
|
||||
if tid, err := strconv.Atoi(string(args[0])); err != nil {
|
||||
return nil, err
|
||||
} else if team, err := fic.GetTeam(tid); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return team.Delete()
|
||||
}
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
|
@ -1,164 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
var ApiThemesRouting = map[string]DispatchFunction{
|
||||
"GET": listTheme,
|
||||
"PATCH": updateTheme,
|
||||
"POST": creationTheme,
|
||||
"DELETE": deletionTheme,
|
||||
}
|
||||
|
||||
func bindingFiles() (string, 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 getTheme(args []string) (fic.Theme, error) {
|
||||
if tid, err := strconv.Atoi(string(args[0])); err != nil {
|
||||
return fic.Theme{}, err
|
||||
} else {
|
||||
return fic.GetTheme(tid)
|
||||
}
|
||||
}
|
||||
|
||||
func getExercice(args []string) (fic.Exercice, error) {
|
||||
if theme, err := getTheme(args); err != nil {
|
||||
return fic.Exercice{}, err
|
||||
} else if eid, err := strconv.Atoi(string(args[1])); err != nil {
|
||||
return fic.Exercice{}, err
|
||||
} else {
|
||||
return theme.GetExercice(eid)
|
||||
}
|
||||
}
|
||||
|
||||
func listTheme(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) == 3 {
|
||||
if e, err := getExercice(args); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if args[2] == "files" {
|
||||
return e.GetFiles()
|
||||
} else if args[2] == "keys" {
|
||||
return e.GetKeys()
|
||||
}
|
||||
}
|
||||
} else if len(args) == 2 {
|
||||
if args[1] == "exercices" {
|
||||
if theme, err := getTheme(args); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return theme.GetExercices()
|
||||
}
|
||||
} else {
|
||||
return getExercice(args)
|
||||
}
|
||||
} else if len(args) == 1 {
|
||||
if args[0] == "files-bindings" {
|
||||
return bindingFiles()
|
||||
} else if args[0] == "themes.json" {
|
||||
return fic.ExportThemes()
|
||||
} else {
|
||||
return getTheme(args)
|
||||
}
|
||||
} else if len(args) == 0 {
|
||||
// List all themes
|
||||
return fic.GetThemes()
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type uploadedTheme struct {
|
||||
Name string
|
||||
Authors string
|
||||
}
|
||||
|
||||
func creationTheme(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) >= 1 {
|
||||
if theme, err := getTheme(args); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return createExercice(theme, args[1:], body)
|
||||
}
|
||||
} else if len(args) == 0 {
|
||||
// Create a new theme
|
||||
var ut uploadedTheme
|
||||
if err := json.Unmarshal(body, &ut); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ut.Name) == 0 {
|
||||
return nil, errors.New("Theme's name not filled")
|
||||
}
|
||||
|
||||
return fic.CreateTheme(ut.Name, ut.Authors)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func updateTheme(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) == 2 {
|
||||
// Update an exercice
|
||||
var ue fic.Exercice
|
||||
if err := json.Unmarshal(body, &ue); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ue.Title) == 0 {
|
||||
return nil, errors.New("Exercice's title not filled")
|
||||
}
|
||||
|
||||
if _, err := ue.Update(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ue, nil
|
||||
} else if len(args) == 1 {
|
||||
// Update a theme
|
||||
var ut fic.Theme
|
||||
if err := json.Unmarshal(body, &ut); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ut.Name) == 0 {
|
||||
return nil, errors.New("Theme's name not filled")
|
||||
}
|
||||
|
||||
return ut.Update()
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func deletionTheme(args []string, body []byte) (interface{}, error) {
|
||||
if len(args) == 2 {
|
||||
if exercice, err := getExercice(args); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return exercice.Delete()
|
||||
}
|
||||
} else if len(args) == 1 {
|
||||
if theme, err := getTheme(args); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return theme.Delete()
|
||||
}
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package main
|
||||
|
||||
import ()
|
||||
|
||||
var ApiVersionRouting = map[string]DispatchFunction{
|
||||
"GET": showVersion,
|
||||
}
|
||||
|
||||
func showVersion(args []string, body []byte) (interface{}, error) {
|
||||
return map[string]interface{}{"version": 0.1}, nil
|
||||
}
|
|
@ -10,28 +10,25 @@ import (
|
|||
"path/filepath"
|
||||
"text/template"
|
||||
|
||||
"srs.epita.fr/fic-server/admin/api"
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
var PKIDir string
|
||||
var SubmissionDir string
|
||||
var BaseURL string
|
||||
var CloudDAVBase string
|
||||
var CloudUsername string
|
||||
var CloudPassword string
|
||||
|
||||
func main() {
|
||||
var staticDir string
|
||||
var bind = flag.String("bind", "127.0.0.1:8081", "Bind port/socket")
|
||||
var dsn = flag.String("dsn", "fic:fic@/fic", "DSN to connect to the MySQL server")
|
||||
flag.StringVar(&BaseURL, "baseurl", "/", "URL prepended to each URL")
|
||||
var baseURL = flag.String("baseurl", "/", "URL prepended to each URL")
|
||||
flag.StringVar(&SubmissionDir, "submission", "./submissions/", "Base directory where save submissions")
|
||||
flag.StringVar(&PKIDir, "pki", "./pki/", "Base directory where found PKI scripts")
|
||||
flag.StringVar(&fic.FilesDir, "files", "./FILES/", "Base directory where found challenges files, local part")
|
||||
flag.StringVar(&CloudDAVBase, "clouddav", "https://srs.epita.fr/owncloud/remote.php/webdav/FIC 2016",
|
||||
flag.StringVar(&api.CloudDAVBase, "clouddav", "https://srs.epita.fr/owncloud/remote.php/webdav/FIC 2016",
|
||||
"Base directory where found challenges files, cloud part")
|
||||
flag.StringVar(&CloudUsername, "clouduser", "fic", "Username used to sync")
|
||||
flag.StringVar(&CloudPassword, "cloudpass", "", "Password used to sync")
|
||||
flag.StringVar(&api.CloudUsername, "clouduser", "fic", "Username used to sync")
|
||||
flag.StringVar(&api.CloudPassword, "cloudpass", "", "Password used to sync")
|
||||
flag.Parse()
|
||||
|
||||
log.SetPrefix("[admin] ")
|
||||
|
@ -70,22 +67,15 @@ func main() {
|
|||
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)
|
||||
}
|
||||
|
||||
|
||||
os.Chdir(PKIDir)
|
||||
|
||||
log.Println("Registering handlers...")
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle(path.Join(BaseURL, "api") + "/", http.StripPrefix(path.Join(BaseURL, "api"), ApiHandler()))
|
||||
mux.Handle(path.Join(BaseURL, "teams") + "/", http.StripPrefix(BaseURL, StaticHandler(staticDir)))
|
||||
mux.Handle(path.Join(BaseURL, "themes") + "/", http.StripPrefix(BaseURL, StaticHandler(staticDir)))
|
||||
mux.Handle(BaseURL, http.StripPrefix(BaseURL, http.FileServer(http.Dir(staticDir))))
|
||||
|
||||
log.Println(fmt.Sprintf("Ready, listening on %s", *bind))
|
||||
if err := http.ListenAndServe(*bind, mux); err != nil {
|
||||
if err := http.ListenAndServe(*bind, http.StripPrefix(*baseURL, api.Router())); err != nil {
|
||||
log.Fatal("Unable to listen and serve: ", err)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user