2018-01-17 00:21:32 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2020-01-20 09:41:21 +00:00
|
|
|
"errors"
|
2020-01-23 15:03:31 +00:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"path"
|
2018-01-17 00:21:32 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"srs.epita.fr/fic-server/libfic"
|
|
|
|
|
|
|
|
"github.com/julienschmidt/httprouter"
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2020-01-23 15:03:31 +00:00
|
|
|
router.GET("/api/teams/:tid/issue.json", apiHandler(teamHandler(
|
|
|
|
func(team fic.Team, _ []byte) (interface{}, error) {
|
|
|
|
return team.MyIssueFile()
|
|
|
|
})))
|
|
|
|
|
2018-01-17 00:21:32 +00:00
|
|
|
// Tasks
|
2020-01-20 09:41:21 +00:00
|
|
|
router.GET("/api/claims", apiHandler(getClaims))
|
|
|
|
router.POST("/api/claims", apiHandler(newClaim))
|
|
|
|
router.DELETE("/api/claims", apiHandler(clearClaims))
|
|
|
|
router.GET("/api/teams/:tid/claims", apiHandler(teamHandler(getTeamClaims)))
|
|
|
|
router.GET("/api/exercices/:eid/claims", apiHandler(exerciceHandler(getExerciceClaims)))
|
|
|
|
router.GET("/api/themes/:thid/exercices/:eid/claims", apiHandler(exerciceHandler(getExerciceClaims)))
|
2018-01-17 00:21:32 +00:00
|
|
|
|
|
|
|
router.GET("/api/claims/:cid", apiHandler(claimHandler(showClaim)))
|
|
|
|
router.PUT("/api/claims/:cid", apiHandler(claimHandler(updateClaim)))
|
|
|
|
router.POST("/api/claims/:cid", apiHandler(claimHandler(addClaimDescription)))
|
|
|
|
router.DELETE("/api/claims/:cid", apiHandler(claimHandler(deleteClaim)))
|
|
|
|
|
2020-01-24 17:24:20 +00:00
|
|
|
router.GET("/api/claims/:cid/last_update", apiHandler(claimHandler(getClaimLastUpdate)))
|
2020-01-23 15:03:31 +00:00
|
|
|
router.PUT("/api/claims/:cid/descriptions", apiHandler(claimHandler(updateClaimDescription)))
|
|
|
|
|
2018-01-17 00:21:32 +00:00
|
|
|
// Assignees
|
2020-01-20 09:41:21 +00:00
|
|
|
router.GET("/api/claims-assignees", apiHandler(getAssignees))
|
|
|
|
router.POST("/api/claims-assignees", apiHandler(newAssignee))
|
2018-01-17 00:21:32 +00:00
|
|
|
|
|
|
|
router.GET("/api/claims-assignees/:aid", apiHandler(claimAssigneeHandler(showClaimAssignee)))
|
|
|
|
router.PUT("/api/claims-assignees/:aid", apiHandler(claimAssigneeHandler(updateClaimAssignee)))
|
|
|
|
router.DELETE("/api/claims-assignees/:aid", apiHandler(claimAssigneeHandler(deleteClaimAssignee)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func getClaims(_ httprouter.Params, _ []byte) (interface{}, error) {
|
|
|
|
return fic.GetClaims()
|
|
|
|
}
|
|
|
|
|
2020-01-20 09:41:21 +00:00
|
|
|
func getTeamClaims(team fic.Team, _ []byte) (interface{}, error) {
|
|
|
|
return team.GetClaims()
|
|
|
|
}
|
|
|
|
|
|
|
|
func getExerciceClaims(exercice fic.Exercice, _ []byte) (interface{}, error) {
|
|
|
|
return exercice.GetClaims()
|
|
|
|
}
|
|
|
|
|
2020-01-24 17:24:20 +00:00
|
|
|
func getClaimLastUpdate(claim fic.Claim, _ []byte) (interface{}, error) {
|
|
|
|
return claim.GetLastUpdate()
|
|
|
|
}
|
|
|
|
|
2018-01-17 00:21:32 +00:00
|
|
|
type ClaimExported struct {
|
|
|
|
Id int64 `json:"id"`
|
|
|
|
Subject string `json:"subject"`
|
|
|
|
IdTeam *int64 `json:"id_team"`
|
|
|
|
Team *fic.Team `json:"team"`
|
2020-01-20 08:24:24 +00:00
|
|
|
IdExercice *int64 `json:"id_exercice"`
|
|
|
|
Exercice *fic.Exercice `json:"exercice"`
|
2018-01-17 00:21:32 +00:00
|
|
|
IdAssignee *int64 `json:"id_assignee"`
|
|
|
|
Assignee *fic.ClaimAssignee `json:"assignee"`
|
|
|
|
Creation time.Time `json:"creation"`
|
|
|
|
LastUpdate time.Time `json:"last_update"`
|
|
|
|
State string `json:"state"`
|
|
|
|
Priority string `json:"priority"`
|
|
|
|
Descriptions []fic.ClaimDescription `json:"descriptions"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func showClaim(claim fic.Claim, _ []byte) (interface{}, error) {
|
|
|
|
var e ClaimExported
|
|
|
|
var err error
|
|
|
|
if e.Team, err = claim.GetTeam(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-01-20 08:24:24 +00:00
|
|
|
if e.Exercice, err = claim.GetExercice(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-01-17 00:21:32 +00:00
|
|
|
if e.Assignee, err = claim.GetAssignee(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if e.Descriptions, err = claim.GetDescriptions(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
e.LastUpdate = e.Creation
|
|
|
|
for _, d := range e.Descriptions {
|
|
|
|
if d.Date.After(e.LastUpdate) {
|
|
|
|
e.LastUpdate = d.Date
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
e.Id = claim.Id
|
|
|
|
e.IdAssignee = claim.IdAssignee
|
|
|
|
e.IdTeam = claim.IdTeam
|
2020-01-20 08:24:24 +00:00
|
|
|
e.IdExercice = claim.IdExercice
|
2018-01-17 00:21:32 +00:00
|
|
|
e.Subject = claim.Subject
|
|
|
|
e.Creation = claim.Creation
|
|
|
|
e.State = claim.State
|
|
|
|
e.Priority = claim.Priority
|
|
|
|
return e, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type ClaimUploaded struct {
|
2020-01-24 17:23:06 +00:00
|
|
|
fic.Claim
|
|
|
|
Whoami *int64 `json:"whoami"`
|
2018-01-17 00:21:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func newClaim(_ httprouter.Params, body []byte) (interface{}, error) {
|
|
|
|
var uc ClaimUploaded
|
|
|
|
if err := json.Unmarshal(body, &uc); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-01-20 09:41:21 +00:00
|
|
|
if uc.Subject == "" {
|
|
|
|
return nil, errors.New("Claim's subject cannot be empty.")
|
|
|
|
}
|
|
|
|
|
2018-01-17 00:21:32 +00:00
|
|
|
var t *fic.Team
|
2020-01-24 17:23:06 +00:00
|
|
|
if uc.IdTeam != nil {
|
|
|
|
if team, err := fic.GetTeam(*uc.IdTeam); err != nil {
|
2018-01-17 00:21:32 +00:00
|
|
|
return nil, err
|
|
|
|
} else {
|
|
|
|
t = &team
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t = nil
|
|
|
|
}
|
|
|
|
|
2020-01-20 08:24:24 +00:00
|
|
|
var e *fic.Exercice
|
2020-01-24 17:23:06 +00:00
|
|
|
if uc.IdExercice != nil {
|
|
|
|
if exercice, err := fic.GetExercice(*uc.IdExercice); err != nil {
|
2020-01-20 08:24:24 +00:00
|
|
|
return nil, err
|
|
|
|
} else {
|
|
|
|
e = &exercice
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
e = nil
|
|
|
|
}
|
|
|
|
|
2018-01-17 00:21:32 +00:00
|
|
|
var a *fic.ClaimAssignee
|
2020-01-24 17:23:06 +00:00
|
|
|
if uc.IdAssignee != nil {
|
|
|
|
if assignee, err := fic.GetAssignee(*uc.IdAssignee); err != nil {
|
2018-01-17 00:21:32 +00:00
|
|
|
return nil, err
|
|
|
|
} else {
|
|
|
|
a = &assignee
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
a = nil
|
|
|
|
}
|
|
|
|
|
2020-01-20 09:41:21 +00:00
|
|
|
if uc.Priority == "" {
|
|
|
|
uc.Priority = "medium"
|
|
|
|
}
|
|
|
|
|
2020-01-20 08:24:24 +00:00
|
|
|
return fic.NewClaim(uc.Subject, t, e, a, uc.Priority)
|
2018-01-17 00:21:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func clearClaims(_ httprouter.Params, _ []byte) (interface{}, error) {
|
|
|
|
return fic.ClearClaims()
|
|
|
|
}
|
|
|
|
|
2020-01-23 15:03:31 +00:00
|
|
|
func generateTeamIssuesFile(team fic.Team) error {
|
|
|
|
if my, err := team.MyIssueFile(); err != nil {
|
|
|
|
return err
|
|
|
|
} else if j, err := json.Marshal(my); err != nil {
|
|
|
|
return err
|
|
|
|
} else if err = ioutil.WriteFile(path.Join(TeamsDir, fmt.Sprintf("%d", team.Id), "issues.json"), j, 0644); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-01-17 00:21:32 +00:00
|
|
|
func addClaimDescription(claim fic.Claim, body []byte) (interface{}, error) {
|
|
|
|
var ud fic.ClaimDescription
|
|
|
|
if err := json.Unmarshal(body, &ud); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if assignee, err := fic.GetAssignee(ud.IdAssignee); err != nil {
|
|
|
|
return nil, err
|
2020-01-23 15:03:31 +00:00
|
|
|
} else if description, err := claim.AddDescription(ud.Content, assignee, ud.Publish); err != nil {
|
|
|
|
return nil, err
|
|
|
|
} else {
|
|
|
|
if team, _ := claim.GetTeam(); team != nil {
|
|
|
|
err = generateTeamIssuesFile(*team)
|
|
|
|
}
|
|
|
|
|
|
|
|
return description, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateClaimDescription(claim fic.Claim, body []byte) (interface{}, error) {
|
|
|
|
var ud fic.ClaimDescription
|
|
|
|
if err := json.Unmarshal(body, &ud); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := ud.Update(); err != nil {
|
|
|
|
return nil, err
|
2018-01-17 00:21:32 +00:00
|
|
|
} else {
|
2020-01-23 15:03:31 +00:00
|
|
|
if team, _ := claim.GetTeam(); team != nil {
|
|
|
|
err = generateTeamIssuesFile(*team)
|
|
|
|
}
|
|
|
|
|
|
|
|
return ud, err
|
2018-01-17 00:21:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateClaim(claim fic.Claim, body []byte) (interface{}, error) {
|
2020-01-24 17:23:06 +00:00
|
|
|
var uc ClaimUploaded
|
2018-01-17 00:21:32 +00:00
|
|
|
if err := json.Unmarshal(body, &uc); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
uc.Id = claim.Id
|
|
|
|
|
|
|
|
if _, err := uc.Update(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
} else {
|
2020-01-24 17:23:06 +00:00
|
|
|
if claim.State != uc.State {
|
|
|
|
if uc.Whoami != nil {
|
|
|
|
if assignee, err := fic.GetAssignee(*uc.Whoami); err == nil {
|
|
|
|
claim.AddDescription(fmt.Sprintf("%s a changé l'état de la tâche vers %q (était %q).", assignee.Name, uc.State, claim.State), assignee, true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if claim.IdAssignee != uc.IdAssignee {
|
|
|
|
if uc.Whoami != nil {
|
|
|
|
if whoami, err := fic.GetAssignee(*uc.Whoami); err == nil {
|
|
|
|
if uc.IdAssignee != nil {
|
|
|
|
if assignee, err := fic.GetAssignee(*uc.IdAssignee); err == nil {
|
|
|
|
if assignee.Id != whoami.Id {
|
|
|
|
claim.AddDescription(fmt.Sprintf("%s a assigné la tâche à %s.", whoami.Name, assignee.Name), whoami, false)
|
|
|
|
} else {
|
|
|
|
claim.AddDescription(fmt.Sprintf("%s s'est assigné la tâche.", assignee.Name), whoami, false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
claim.AddDescription(fmt.Sprintf("%s a retiré l'attribution de la tâche.", whoami.Name), whoami, false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-23 15:03:31 +00:00
|
|
|
if team, _ := claim.GetTeam(); team != nil {
|
|
|
|
err = generateTeamIssuesFile(*team)
|
|
|
|
}
|
|
|
|
|
|
|
|
return uc, err
|
2018-01-17 00:21:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteClaim(claim fic.Claim, _ []byte) (interface{}, error) {
|
|
|
|
return claim.Delete()
|
|
|
|
}
|
|
|
|
|
|
|
|
func getAssignees(_ httprouter.Params, _ []byte) (interface{}, error) {
|
|
|
|
return fic.GetAssignees()
|
|
|
|
}
|
|
|
|
|
|
|
|
func showClaimAssignee(assignee fic.ClaimAssignee, _ []byte) (interface{}, error) {
|
|
|
|
return assignee, nil
|
|
|
|
}
|
|
|
|
func newAssignee(_ httprouter.Params, body []byte) (interface{}, error) {
|
|
|
|
var ua fic.ClaimAssignee
|
|
|
|
if err := json.Unmarshal(body, &ua); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return fic.NewClaimAssignee(ua.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateClaimAssignee(assignee fic.ClaimAssignee, body []byte) (interface{}, error) {
|
|
|
|
var ua fic.ClaimAssignee
|
|
|
|
if err := json.Unmarshal(body, &ua); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
ua.Id = assignee.Id
|
|
|
|
|
|
|
|
if _, err := ua.Update(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
} else {
|
|
|
|
return ua, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteClaimAssignee(assignee fic.ClaimAssignee, _ []byte) (interface{}, error) {
|
|
|
|
return assignee.Delete()
|
|
|
|
}
|