diff --git a/internal/models/desk.go b/internal/models/desk.go new file mode 100644 index 0000000000000000000000000000000000000000..fb314d5f5ae9a4891c933a604edda068cf7be11a --- /dev/null +++ b/internal/models/desk.go @@ -0,0 +1,121 @@ +package models + +import ( + "encoding/json" + "net/http" + "strconv" + "strings" + + "forge.grandlyon.com/apoyen/elections/internal/auth" +) + +func (d *DataHandler) HandleDesk(w http.ResponseWriter, r *http.Request) { + id, _ := strconv.Atoi(strings.TrimPrefix(r.URL.Path, "/api/Desk/")) + switch method := r.Method; method { + case "GET": + switch auth.GetLoggedUserTechnical(w, r).Role { + case "ADMIN", "CAPTURER", "VISUALIZER": + d.getDesk(w, r, id) + default: + http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) + } + case "POST": + switch auth.GetLoggedUserTechnical(w, r).Role { + case "ADMIN": + d.postDesk(w, r) + case "CAPTURER", "VISUALIZER": + http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) + default: + http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) + } + + case "PUT": + switch auth.GetLoggedUserTechnical(w, r).Role { + case "ADMIN": + d.putDesk(w, r, id) + case "CAPTURER", "VISUALIZER": + http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) + default: + http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) + } + case "DELETE": + switch auth.GetLoggedUserTechnical(w, r).Role { + case "ADMIN": + d.deleteDesk(w, r, id) + case "CAPTURER", "VISUALIZER": + http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) + default: + http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) + } + default: + http.Error(w, "method not allowed", 400) + } +} + +func (d *DataHandler) getDesk(w http.ResponseWriter, r *http.Request, id int) { + if id != 0 { + var o Desk + if err := d.db.First(&o, id).Error; err != nil { + http.Error(w, ErrorIDIsMissing, http.StatusNotFound) + return + } + json.NewEncoder(w).Encode(o) + } else { + var o []Desk + d.db.Find(&o) + json.NewEncoder(w).Encode(o) + } +} + +func (d *DataHandler) postDesk(w http.ResponseWriter, r *http.Request) { + var o Desk + err := json.NewDecoder(r.Body).Decode(&o) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + // Check that SectionID exist + var section Section + if err := d.db.First(§ion, o.SectionID).Error; err != nil { + http.Error(w, ErrorParentNotFound, http.StatusInternalServerError) + return + } + + d.db.Create(&o) + d.db.Last(&o) + json.NewEncoder(w).Encode(o) + +} + +func (d *DataHandler) putDesk(w http.ResponseWriter, r *http.Request, id int) { + var o Desk + if err := d.db.First(&o, id).Error; err != nil { + http.Error(w, ErrorIDIsMissing, http.StatusNotFound) + return + } + var desk Desk + err := json.NewDecoder(r.Body).Decode(&desk) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + o.Name = desk.Name + o.WitnessDesk = desk.WitnessDesk + o.Subscribed = desk.Subscribed + d.db.Save(&o) + json.NewEncoder(w).Encode(o) + +} + +func (d *DataHandler) deleteDesk(w http.ResponseWriter, r *http.Request, id int) { + if id != 0 { + var o Desk + if err := d.db.First(&o, id).Error; err != nil { + http.Error(w, ErrorIDIsMissing, http.StatusNotFound) + return + } + d.db.Delete(&o) + } else { + http.Error(w, ErrorIDIsMissing, http.StatusNotFound) + } +} diff --git a/internal/models/models.go b/internal/models/models.go index c5e20768f717a4283c81a2a906123bf125de2489..9fea419465b07c1c59709a4b7cef4a4f27b34c4d 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -80,8 +80,8 @@ type Desk struct { DeletedAt *time.Time `json:"-"` SectionID uint Name string - Subscribed uint WitnessDesk bool + Subscribed uint } // Party @@ -224,6 +224,8 @@ func (d *DataHandler) ProcessAPI(w http.ResponseWriter, r *http.Request) { d.HandleArea(w, r) case "Section": d.HandleSection(w, r) + case "Desk": + d.HandleDesk(w, r) } } diff --git a/internal/models/section.go b/internal/models/section.go index debe567e6a41bf693d5e1a0179dd13753d5eb563..fb6356d868808013e50ed66d771e1aabf1072e6f 100644 --- a/internal/models/section.go +++ b/internal/models/section.go @@ -41,7 +41,7 @@ func (d *DataHandler) HandleSection(w http.ResponseWriter, r *http.Request) { case "DELETE": switch auth.GetLoggedUserTechnical(w, r).Role { case "ADMIN": - d.deleteAreaAdmin(w, r, id) + d.deleteSection(w, r, id) case "CAPTURER", "VISUALIZER": http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) default: diff --git a/internal/rootmux/admin_test.go b/internal/rootmux/admin_test.go index 242760e1de9f6999a7ad126f698825f97deed6bf..a18624e1607c260db95199ddba59812cf20397dc 100644 --- a/internal/rootmux/admin_test.go +++ b/internal/rootmux/admin_test.go @@ -60,6 +60,17 @@ func AdminTests(t *testing.T) { // Update a section do("PUT", "/api/Section/1", xsrfHeader, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"5"}`, 200, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"5","Desks":[]}`) + // Create a Desk + do("POST", "/api/Desk", xsrfHeader, `{"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}`, 200, `{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}`) + // Get the desk + do("GET", "/api/Desk/1", xsrfHeader, ``, 200, `{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}`) + // Get all the desks + do("GET", "/api/Desk/", xsrfHeader, ``, 200, `[{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}]`) + // Update a desk + do("PUT", "/api/Desk/1", xsrfHeader, `{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":false,"Subscribed":3587}`, 200, `{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":false,"Subscribed":3587}`) + + // Delete a desk + do("DELETE", "/api/Desk/1", xsrfHeader, ``, 200, ``) // Delete a section do("DELETE", "/api/Section/1", xsrfHeader, ``, 200, ``) // Delete an area diff --git a/internal/rootmux/capturer_test.go b/internal/rootmux/capturer_test.go index c77549f44974af67d3014b4d9b8a36b82976b2d9..1bd6e863198cbe3695cfb0a708dd22d2eec97064 100644 --- a/internal/rootmux/capturer_test.go +++ b/internal/rootmux/capturer_test.go @@ -60,14 +60,25 @@ func CapturerTests(t *testing.T) { // Create a section should fail with 405 do("POST", "/api/Section", xsrfHeader, `{"AreaID":1,"Name":"Section 1","MapID":"1"}`, 405, `You're not authorize to execute this method on this ressource.`) // Get a section - do("GET", "/api/Section/1", xsrfHeader, "", 200, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":[]}`) + do("GET", "/api/Section/1", xsrfHeader, "", 200, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":[{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}]}`) // Get all the sections - do("GET", "/api/Section/", xsrfHeader, "", 200, `[{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":[]}]`) + do("GET", "/api/Section/", xsrfHeader, "", 200, `[{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":[{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}]}]`) // Update a section should fail with 405 do("PUT", "/api/Section/1", xsrfHeader, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1"}`, 405, `You're not authorize to execute this method on this ressource.`) // Delete a section should fail with 405 do("DELETE", "/api/Section/1", xsrfHeader, ``, 405, `You're not authorize to execute this method on this ressource.`) + // Create a desk should fail with 405 + do("POST", "/api/Desk", xsrfHeader, `{"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}`, 405, `You're not authorize to execute this method on this ressource.`) + // Get a desk + do("GET", "/api/Desk/1", xsrfHeader, "", 200, `{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}`) + // Get all the desks + do("GET", "/api/Desk/", xsrfHeader, "", 200, `[{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}]`) + // Update a desk should fail with 405 + do("PUT", "/api/Desk/1", xsrfHeader, `{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":false,"Subscribed":3587}`, 405, `You're not authorize to execute this method on this ressource.`) + // Delete a desk should fail with 405 + do("DELETE", "/api/Desk/1", xsrfHeader, ``, 405, `You're not authorize to execute this method on this ressource.`) + } // Do a in memory login with an known admin do("POST", "/Login", noH, `{"login": "capturer","password": "password"}`, 200, "") diff --git a/internal/rootmux/rootmux_test.go b/internal/rootmux/rootmux_test.go index 61d6a2f31e745e9912808b7ee78c006e0f9f93d5..c98e56807570f073af224f38e7f393fbc4a11eee 100644 --- a/internal/rootmux/rootmux_test.go +++ b/internal/rootmux/rootmux_test.go @@ -141,9 +141,11 @@ func resetDataWithData(t *testing.T) { // Create a capturer do("POST", "/api/Capturer", xsrfHeader, `{"UserID":2,"Name":"Capturer"}`, 200, `{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":null}`) do("POST", "/api/Capturer", xsrfHeader, `{"UserID":3,"Name":"Capturer"}`, 200, `{"ID":2,"UserID":3,"Name":"Capturer","DeskRounds":null}`) + do("POST", "/api/Election", xsrfHeader, `{"Name":"Grand Lyon 2020","BallotType":"metropolitan-direct"}`, 200, `{"ID":1,"Name":"Grand Lyon 2020","BallotType":"metropolitan-direct","Areas":null,"Rounds":null}`) do("POST", "/api/Area", xsrfHeader, `{"ElectionID":1,"Name":"Area 1","SeatNumber":9,"MapID":"1"}`, 200, `{"ID":1,"ElectionID":1,"Name":"Area 1","SeatNumber":9,"MapID":"1","Sections":null}`) do("POST", "/api/Section", xsrfHeader, `{"AreaID":1,"Name":"Section 1","MapID":"1"}`, 200, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":null}`) + do("POST", "/api/Desk", xsrfHeader, `{"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}`, 200, `{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}`) } do("POST", "/Login", noH, `{"login": "admin","password": "password"}`, 200, "") diff --git a/internal/rootmux/visualizer_test.go b/internal/rootmux/visualizer_test.go index 8f436112f549077295cb4a0e9b03fce70498cdff..f7c3289ca925b9c0651802147ed36d6b59ac6c2c 100644 --- a/internal/rootmux/visualizer_test.go +++ b/internal/rootmux/visualizer_test.go @@ -58,9 +58,9 @@ func VisualizerTests(t *testing.T) { // Create a section should fail with 405 do("POST", "/api/Section", xsrfHeader, `{"AreaID":1,"Name":"Section 1","MapID":"1"}`, 405, `You're not authorize to execute this method on this ressource.`) // Get a section - do("GET", "/api/Section/1", xsrfHeader, "", 200, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":[]}`) + do("GET", "/api/Section/1", xsrfHeader, "", 200, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":[{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}]}`) // Get all the sections - do("GET", "/api/Section/", xsrfHeader, "", 200, `[{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":[]}]`) + do("GET", "/api/Section/", xsrfHeader, "", 200, `[{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1","Desks":[{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587}]}]`) // Update a section should fail with 405 do("PUT", "/api/Section/1", xsrfHeader, `{"ID":1,"AreaID":1,"Name":"Section 1","MapID":"1"}`, 405, `You're not authorize to execute this method on this ressource.`) // Delete a section should fail with 405