package api import ( "encoding/json" "fmt" "math/rand" "strings" "time" "srs.epita.fr/fic-server/admin/pki" "srs.epita.fr/fic-server/libfic" "github.com/julienschmidt/httprouter" ) func init() { router.GET("/api/teams.json", apiHandler( func(httprouter.Params, []byte) (interface{}, error) { return fic.ExportTeams(false) })) router.GET("/api/teams-members.json", apiHandler( func(httprouter.Params, []byte) (interface{}, error) { return fic.ExportTeams(true) })) router.GET("/api/teams-binding", apiHandler( func(httprouter.Params, []byte) (interface{}, error) { return bindingTeams() })) router.GET("/api/teams-nginx", apiHandler( func(httprouter.Params, []byte) (interface{}, error) { return nginxGenTeams() })) router.POST("/api/disableinactiveteams", apiHandler(disableInactiveTeams)) router.POST("/api/enableallteams", apiHandler(enableAllTeams)) router.GET("/api/teams-members-nginx", apiHandler( func(httprouter.Params, []byte) (interface{}, error) { return nginxGenMember() })) router.GET("/api/teams-tries.json", apiHandler( func(httprouter.Params, []byte) (interface{}, error) { return fic.GetTries(nil, nil) })) router.GET("/api/teams/", apiHandler( func(httprouter.Params, []byte) (interface{}, error) { return fic.GetTeams() })) router.POST("/api/teams/", apiHandler(createTeam)) router.GET("/api/teams/:tid/", apiHandler(teamHandler( func(team *fic.Team, _ []byte) (interface{}, error) { return team, nil }))) router.PUT("/api/teams/:tid/", apiHandler(teamHandler(updateTeam))) router.POST("/api/teams/:tid/", apiHandler(teamHandler(addTeamMember))) router.DELETE("/api/teams/:tid/", apiHandler(teamHandler(deleteTeam))) router.GET("/api/teams/:tid/score-grid.json", apiHandler(teamHandler( func(team *fic.Team, _ []byte) (interface{}, error) { return team.ScoreGrid() }))) 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/history.json", apiHandler(teamPublicHandler( func(team *fic.Team, _ []byte) (interface{}, error) { if team != nil { return team.GetHistory() } else { return fic.GetTeamsStats(nil) } }))) router.DELETE("/api/teams/:tid/history.json", apiHandler(teamPublicHandler(delHistory))) 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() }))) router.POST("/api/teams/:tid/members", apiHandler(teamHandler(addTeamMember))) router.PUT("/api/teams/:tid/members", apiHandler(teamHandler(setTeamMember))) } func nginxGenTeams() (string, error) { if teams, err := fic.GetTeams(); err != nil { return "", err } else { ret := "" for _, team := range teams { ret += fmt.Sprintf(" if ($remote_user = \"%s\") { set $team \"%d\"; }\n", strings.ToLower(team.Name), team.Id) } return ret, 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 \"%d\"; }\n", member.Nickname, team.Id) } } else { return "", err } } 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 } } func createTeam(_ httprouter.Params, body []byte) (interface{}, error) { var ut fic.Team if err := json.Unmarshal(body, &ut); err != nil { return nil, err } if ut.Color == 0 { ut.Color = fic.HSL{rand.Float64(), 1, 0.5}.ToRGB() } return fic.CreateTeam(strings.TrimSpace(ut.Name), ut.Color, ut.ExternalId) } func updateTeam(team *fic.Team, body []byte) (interface{}, error) { var ut fic.Team if err := json.Unmarshal(body, &ut); err != nil { return nil, err } ut.Id = team.Id if ut.Password != nil && *ut.Password == "" { ut.Password = nil } if _, err := ut.Update(); err != nil { return nil, err } return ut, nil } func disableInactiveTeams(_ httprouter.Params, _ []byte) (interface{}, error) { if teams, err := fic.GetTeams(); err != nil { return nil, err } else { for _, team := range teams { var serials []uint64 serials, err = pki.GetTeamSerials(TeamsDir, team.Id) if err != nil { return nil, err } var assocs []string assocs, err = pki.GetTeamAssociations(TeamsDir, team.Id) if err != nil { return nil, err } if len(serials) == 0 && len(assocs) == 0 { if team.Active { team.Active = false team.Update() } } else if !team.Active { team.Active = true team.Update() } } return true, nil } } func enableAllTeams(_ httprouter.Params, _ []byte) (interface{}, error) { if teams, err := fic.GetTeams(); err != nil { return nil, err } else { for _, team := range teams { if !team.Active { team.Active = true team.Update() } } return true, nil } } func deleteTeam(team *fic.Team, _ []byte) (interface{}, error) { assocs, err := pki.GetTeamAssociations(TeamsDir, team.Id) if err != nil { return nil, err } for _, assoc := range assocs { err = pki.DeleteTeamAssociation(TeamsDir, assoc) } if err != nil { return nil, err } return team.Delete() } func addTeamMember(team *fic.Team, body []byte) (interface{}, error) { var members []fic.Member if err := json.Unmarshal(body, &members); err != nil { return nil, err } for _, member := range members { team.AddMember(strings.TrimSpace(member.Firstname), strings.TrimSpace(member.Lastname), strings.TrimSpace(member.Nickname), strings.TrimSpace(member.Company)) } return team.GetMembers() } func setTeamMember(team *fic.Team, body []byte) (interface{}, error) { var members []fic.Member if err := json.Unmarshal(body, &members); err != nil { return nil, err } team.ClearMembers() for _, member := range members { team.AddMember(strings.TrimSpace(member.Firstname), strings.TrimSpace(member.Lastname), strings.TrimSpace(member.Nickname), strings.TrimSpace(member.Company)) } return team.GetMembers() } type uploadedHistory struct { Kind string Time time.Time Primary *int64 Secondary *int64 Coefficient float32 } func updateHistory(team *fic.Team, body []byte) (interface{}, error) { var uh uploadedHistory if err := json.Unmarshal(body, &uh); err != nil { return nil, err } var givenId int64 if uh.Secondary != nil { givenId = *uh.Secondary } else if uh.Primary != nil { givenId = *uh.Primary } return team.UpdateHistoryCoeff(uh.Kind, uh.Time, givenId, uh.Coefficient) } func delHistory(team *fic.Team, body []byte) (interface{}, error) { var uh uploadedHistory if err := json.Unmarshal(body, &uh); err != nil { return nil, err } return team.DelHistoryItem(uh.Kind, uh.Time, uh.Primary, uh.Secondary) }