func AddBoard(c web.C, w http.ResponseWriter, r *http.Request) { var ( db = c.Env["db"].(*mgo.Database) user = c.Env["user"].(bson.ObjectId) payload struct { Name string `json:"name"` Description string `json:"description"` Size models.Size `json:"size"` Background string `json:"background"` } ) // read the payload if err := utils.ReadJSON(r, &payload); err != nil { utils.Error(w, err.Error(), http.StatusBadRequest) return } // create the board, with the requesting user as the creator board := models.Board{ ID: bson.NewObjectId(), CreatedBy: user, CreatedAt: time.Now(), Name: payload.Name, Size: payload.Size, Background: payload.Background, Description: payload.Description, Members: []models.Member{ { Role: "admin", UserID: user, MemberSince: time.Now(), }, }, } if err := db.C("boards").Insert(&board); err != nil { utils.Error(w, err.Error(), http.StatusInternalServerError) return } // respond with the created board utils.WriteJSON(w, http.StatusCreated, &board) return }
func UpdateBoardSize(c web.C, w http.ResponseWriter, r *http.Request) { var ( db = c.Env["db"].(*mgo.Database) user = c.Env["user"].(bson.ObjectId) boardIDHex = c.URLParams["board_id"] payload struct { Width string `json:"width"` Height string `json:"height"` } ) // read the payload if err := utils.ReadJSON(r, &payload); err != nil { utils.Error(w, err.Error(), http.StatusBadRequest) return } // update the board and return the updated board to the user board, err := updateBoard(db, user, boardIDHex, bson.M{ "size": bson.M{ "width": payload.Width, "height": payload.Height, }, }) if err != nil { utils.Error(w, err.Error(), err.HTTPStatusCode) return } utils.WriteJSON(w, http.StatusOK, &board) return }
func UpdateBoardMember(c web.C, w http.ResponseWriter, r *http.Request) { var ( db = c.Env["db"].(*mgo.Database) user = c.Env["user"].(bson.ObjectId) boardIDHex = c.URLParams["board_id"] memberIDHex = c.URLParams["member_id"] payload struct { Role string `json:"height"` } ) // read the payload if err := utils.ReadJSON(r, &payload); err != nil { utils.Error(w, err.Error(), http.StatusBadRequest) return } // make sure the 'member_id' attribute is a valid 'ObjectID' if !bson.IsObjectIdHex(memberIDHex) { utils.Error(w, "'user_id' must be a valid 'ObjectID'", http.StatusBadRequest) return } memberID := bson.ObjectIdHex(memberIDHex) // get the board and make sure the user has admin access board, err := getBoard(db, boardIDHex) if err != nil { utils.Error(w, err.Error(), err.HTTPStatusCode) return } if board.GetRole(user) != "admin" { utils.Error(w, "", http.StatusForbidden) return } // make sure the 'member_id' is an actual member member := board.GetMember(memberID) if member == nil { utils.Error(w, "Member not found on Board", http.StatusNotFound) return } // apply updates and return the newly updated board // NOTE this does not use the 'updateBoard' helper function // because this uses the positional operator to update // the embedded member document var ( boardQuery = bson.M{ "_id": board.ID, "members.user_id": member.UserID, } boardUpdate = bson.M{ "$set": bson.M{ "members.$.role": payload.Role, }, } ) if err := db.C("boards").Update(boardQuery, boardUpdate); err != nil { if err == mgo.ErrNotFound { utils.Error(w, "Board not found", http.StatusNotFound) return } utils.Error(w, err.Error(), http.StatusInternalServerError) return } member.Role = payload.Role utils.WriteJSON(w, http.StatusOK, &member) return }
func UpdateTicket(c web.C, w http.ResponseWriter, r *http.Request) { var ( db = c.Env["db"].(*mgo.Database) user = c.Env["user"].(bson.ObjectId) boardIDHex = c.URLParams["board_id"] ticketIDHex = c.URLParams["ticket_id"] payload struct { Color string `json:"color"` Heading string `json:"heading"` Content string `json:"content"` } ) // read the payload if err := utils.ReadJSON(r, &payload); err != nil { utils.Error(w, err.Error(), http.StatusBadRequest) return } // check that 'ticket_id' is a valid 'ObjectID' if !bson.IsObjectIdHex(ticketIDHex) { utils.Error(w, "'ticket_id' must be a valid 'ObjectID'", http.StatusBadRequest) return } ticketID := bson.ObjectIdHex(ticketIDHex) // get the board and make sure that the user is a member board, err := getBoard(db, boardIDHex) if err != nil { utils.Error(w, err.Error(), err.HTTPStatusCode) return } if !board.IsMember(user) { utils.Error(w, "", http.StatusForbidden) return } // apply the update and return the newly updated ticket var ( ticket = models.Ticket{} ticketQuery = db.C("tickets").FindId(ticketID) ticketUpdate = mgo.Change{ Update: bson.M{ "color": payload.Color, "heading": payload.Heading, "content": payload.Content, }, ReturnNew: true, } ) if _, err := ticketQuery.Apply(ticketUpdate, &ticket); err != nil { if err == mgo.ErrNotFound { utils.Error(w, "Ticket not found", http.StatusNotFound) return } utils.Error(w, err.Error(), http.StatusInternalServerError) return } utils.WriteJSON(w, http.StatusOK, &ticket) return }
func AddMember(c web.C, w http.ResponseWriter, r *http.Request) { var ( db = c.Env["db"].(*mgo.Database) user = c.Env["user"].(bson.ObjectId) boardIDHex = c.URLParams["board_id"] payload struct { Role string `json:"role"` UserID bson.ObjectId `json:"user_id"` } ) // read the payload if err := utils.ReadJSON(r, &payload); err != nil { utils.Error(w, err.Error(), http.StatusBadRequest) return } // validate that the 'role' in payload matches either 'admin' or 'member' if payload.Role != "admin" && payload.Role != "member" { utils.Error(w, "'role' must be either 'admin' or 'member'", http.StatusBadRequest) return } // get the requested board board, err := getBoard(db, boardIDHex) if err != nil { utils.Error(w, err.Error(), err.HTTPStatusCode) return } // make sure the user making the request is 'admin' on the board if board.GetRole(user) != "admin" { utils.Error(w, "Role 'admin' required", http.StatusForbidden) return } // make sure the user we are about to add is not already a member // and that the user actually exists if board.IsMember(payload.UserID) { utils.Error(w, "User is already a member", http.StatusConflict) return } // TODO what is the most efficient way of checking that the // document we are referencing with 'user_id' actually exists // add the user as a member newMember := models.Member{ Role: payload.Role, UserID: payload.UserID, MemberSince: time.Now(), } if err := db.C("boards").UpdateId(board.ID, bson.M{ "$push": bson.M{ "members": newMember, }, }); err != nil { utils.Error(w, err.Error(), http.StatusInternalServerError) return } // return the member we just added utils.WriteJSON(w, http.StatusCreated, &newMember) return }
func AddTicket(c web.C, w http.ResponseWriter, r *http.Request) { var ( db = c.Env["db"].(*mgo.Database) user = c.Env["user"].(bson.ObjectId) boardIDHex = c.URLParams["board_id"] payload struct { Color string `json:"color"` Heading string `json:"heading"` Content string `json:"content"` Position models.Position `json:"position"` } ) // read the payload if err := utils.ReadJSON(r, &payload); err != nil { utils.Error(w, err.Error(), http.StatusBadRequest) return } // get the required board and make sure the requesting user is a member board, err := getBoard(db, boardIDHex) if err != nil { utils.Error(w, err.Error(), err.HTTPStatusCode) return } if !board.IsMember(user) { utils.Error(w, "User must be a board member", http.StatusForbidden) return } // insert a new 'Ticket' into 'tickets' newTicket := models.Ticket{ ID: bson.NewObjectId(), BoardID: board.ID, Color: payload.Color, Heading: payload.Heading, Content: payload.Content, Position: payload.Position, CreatedBy: user, CreatedAt: time.Now(), } if err := db.C("tickets").Insert(&newTicket); err != nil { utils.Error(w, err.Error(), http.StatusInternalServerError) return } // return the added ticket utils.WriteJSON(w, http.StatusCreated, &newTicket) return }