From b11f88851f0764c70b42a457497ae898a3fc83ff Mon Sep 17 00:00:00 2001 From: Gisle Aune Date: Sat, 2 Mar 2019 12:03:51 +0100 Subject: [PATCH] GroupController: Added PATCH /api/group/permission/:id and DELETE /api/group/:id --- controllers/group-controller.go | 121 ++++++++++++++++++++++++++++ database/sqlite/group-repository.go | 2 +- 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/controllers/group-controller.go b/controllers/group-controller.go index 45aa908..c8be545 100644 --- a/controllers/group-controller.go +++ b/controllers/group-controller.go @@ -201,6 +201,125 @@ func (c *GroupController) updateGroup(w http.ResponseWriter, r *http.Request) { respond.Data(w, group) } +// updateGroupPermission (`PUT/PATCH /:group_id/permission/:user_id`): Update a user's permission on a group. +func (c *GroupController) updateGroupPermission(w http.ResponseWriter, r *http.Request) { + user := models.UserFromContext(r.Context()) + + groupIDStr := mux.Vars(r)["group_id"] + groupID, err := strconv.ParseInt(groupIDStr, 10, 32) + if err != nil { + respond.Error(w, http.StatusBadRequest, "invalid_id", "The group id "+groupIDStr+" is not valid.") + return + } + + userIDStr := mux.Vars(r)["user_id"] + userID, err := strconv.ParseInt(userIDStr, 10, 32) + if err != nil { + respond.Error(w, http.StatusBadRequest, "invalid_id", "The user id "+userIDStr+" is not valid.") + return + } + + putData := struct { + Read *bool `json:"read"` + Write *bool `json:"write"` + Create *bool `json:"create"` + Delete *bool `json:"delete"` + Manage *bool `json:"manage"` + }{} + if err := json.NewDecoder(r.Body).Decode(&putData); err != nil { + respond.Error(w, http.StatusBadRequest, "invalid_json", "Input is not valid JSON.") + return + } + if putData.Manage != nil { + respond.Error(w, http.StatusBadRequest, "cannot_change_manage", "You cannot change the manage permission.") + return + } + + group, err := c.groups.FindByID(r.Context(), int(groupID)) + if err != nil { + respond.Error(w, http.StatusNotFound, "group_not_found", "The group could not be found.") + return + } else if !group.Permission(user.ID).Manage { + respond.Error(w, http.StatusForbidden, "permission_denied", "This transgression has been dispatched to the North Pole for review.") + return + } + + user2, err := c.users.FindByID(r.Context(), int(userID)) + if err == sql.ErrNoRows { + respond.Error(w, http.StatusNotFound, "user_not_Found", "The user could not be found.") + return + } else if err != nil { + httperr.Respond(w, err) + return + } + + permissions := group.Permission(user2.ID) + if putData.Read != nil { + permissions.Read = *putData.Read + } + if putData.Write != nil { + permissions.Write = *putData.Write + } + if putData.Create != nil { + permissions.Create = *putData.Create + } + if putData.Delete != nil { + permissions.Delete = *putData.Delete + } + + err = c.groups.UpdatePermissions(r.Context(), permissions) + if err != nil { + httperr.Respond(w, err) + return + } + + respond.Data(w, permissions) +} + +// deleteGroup (`DELETE /:group_id`): Delete a group. +func (c *GroupController) deleteGroup(w http.ResponseWriter, r *http.Request) { + user := models.UserFromContext(r.Context()) + + groupIDStr := mux.Vars(r)["group_id"] + groupID, err := strconv.ParseInt(groupIDStr, 10, 32) + if err != nil { + respond.Error(w, http.StatusBadRequest, "invalid_id", "The group id "+groupIDStr+" is not valid.") + return + } + + group, err := c.groups.FindByID(r.Context(), int(groupID)) + if err != nil { + respond.Error(w, http.StatusNotFound, "group_not_found", "The group cannot be found.") + return + } else if !group.Permission(user.ID).Manage { + respond.Error(w, http.StatusNotFound, "permission_denied", "Your transgression will be remembered.") + return + } + + lights, err := c.lights.ListByGroup(r.Context(), group) + if err != nil && err != sql.ErrNoRows { + httperr.Respond(w, err) + return + } + + for _, light := range lights { + light.GroupID = 0 + err := c.lights.Update(r.Context(), light) + if err != nil { + httperr.Respond(w, err) + return + } + } + + err = c.groups.Remove(r.Context(), group) + if err != nil { + httperr.Respond(w, err) + return + } + + respond.Data(w, group) +} + // Mount mounts the controller func (c *GroupController) Mount(router *mux.Router, prefix string) { sub := router.PathPrefix(prefix).Subrouter() @@ -209,6 +328,8 @@ func (c *GroupController) Mount(router *mux.Router, prefix string) { sub.HandleFunc("/", c.postGroup).Methods("POST") sub.HandleFunc("/{group_id}", c.getGroup).Methods("GET") sub.HandleFunc("/{group_id}", c.updateGroup).Methods("PUT", "PATCH") + sub.HandleFunc("/{group_id}", c.deleteGroup).Methods("DELETE") + sub.HandleFunc("/{group_id}/permission/{user_id}", c.updateGroupPermission).Methods("PUT", "PATCH") sub.HandleFunc("/{group_id}/light/", c.getGroupLights).Methods("GET") sub.HandleFunc("/{group_id}/light/{light_id}", c.getGroupLight).Methods("GET") } diff --git a/database/sqlite/group-repository.go b/database/sqlite/group-repository.go index ee75f80..1505bcd 100644 --- a/database/sqlite/group-repository.go +++ b/database/sqlite/group-repository.go @@ -135,7 +135,7 @@ func (r *groupRepository) UpdatePermissions(ctx context.Context, permission mode } func (r *groupRepository) Remove(ctx context.Context, group models.Group) error { - _, err := db.NamedExecContext(ctx, "DELETE FROM `group` WHERE id=:id LIMIT 1", group) + _, err := db.NamedExecContext(ctx, "DELETE FROM `group` WHERE id=:id", group) return err }