// Read handles GET either by /site or /sites/{site_id} func (ctl *SiteController) Read(c *models.Context) { // Check whether this site is being accessed by ID siteQuery, exists := c.RouteVars["site_id"] if exists { siteID, err := strconv.ParseInt(siteQuery, 10, 64) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The supplied site ID ('%s') is not a number.", siteQuery), http.StatusBadRequest, ) return } site, status, err := models.GetSite(siteID) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("No site with ID %d found", siteID), status, ) return } c.RespondWithData(site) return } // Site already populated in context, so only fetch permissions c.Site.Meta.Permissions = models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeSite], c.Site.ID), ) c.RespondWithData(c.Site) return }
// Read handles GET func (ctl *UserController) Read(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, itemTypeID, itemID), ) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation m, status, err := models.GetUser(itemID) if err != nil { c.RespondWithErrorDetail(err, status) return } if !models.UserIsOnSite(m.ID, c.Site.ID) { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } c.RespondWithData(m) }
// Delete handles DELETE // Note: This only affects explicitly assigned roles and not roles implicitly // included by criteria func (ctl *RoleProfileController) Delete(c *models.Context) { // Validate inputs var microcosmID int64 if sid, exists := c.RouteVars["microcosm_id"]; exists { id, err := strconv.ParseInt(sid, 10, 64) if err != nil { c.RespondWithErrorMessage("microcosm_id in URL is not a number", http.StatusBadRequest) return } microcosmID = id } roleID, err := strconv.ParseInt(c.RouteVars["role_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("role_id in URL is not a number", http.StatusBadRequest) return } _, status, err := models.GetRole(c.Site.ID, microcosmID, roleID, c.Auth.ProfileID) if err != nil { c.RespondWithErrorDetail(err, status) return } profileID, err := strconv.ParseInt(c.RouteVars["profile_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("profile_id in URL is not a number", http.StatusBadRequest) return } m := models.RoleProfileType{} m.ID = profileID // Authorisation perms := models.GetPermission( models.MakeAuthorisationContext(c, microcosmID, h.ItemTypes[h.ItemTypeMicrocosm], microcosmID), ) if microcosmID > 0 { // Related to a Microcosm if !perms.IsModerator && !c.Auth.IsSiteOwner { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } } else { // Default role for the site if !c.Auth.IsSiteOwner { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } } status, err = m.Delete(roleID) if err != nil { c.RespondWithErrorDetail(err, status) return } c.RespondWithOK() }
// Read handles GET func (ctl *AttributeController) Read(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } perms := models.GetPermission(models.MakeAuthorisationContext(c, 0, itemTypeID, itemID)) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } attributeID, status, err := models.GetAttributeID(itemTypeID, itemID, c.RouteVars["key"]) if err != nil { c.RespondWithErrorDetail(err, status) return } m, status, err := models.GetAttribute(attributeID) if err != nil { c.RespondWithErrorDetail(err, status) return } c.RespondWithData(m) }
// Update handles PUT func (ctl *EventController) Update(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } // Validate inputs m, status, err := models.GetEvent(c.Site.ID, itemID, c.Auth.ProfileID) if err != nil { c.RespondWithErrorDetail(err, status) return } err = c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, itemTypeID, itemID), ) if !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation // Populate where applicable from auth and context m.Meta.EditedByNullable = sql.NullInt64{Int64: c.Auth.ProfileID, Valid: true} m.Meta.EditedNullable = pq.NullTime{Time: time.Now(), Valid: true} status, err = m.Update(c.Site.ID, c.Auth.ProfileID) if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Replace( c.Site.ID, h.ItemTypes[h.ItemTypeEvent], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithSeeOther( fmt.Sprintf( "%s/%d", h.APITypeEvent, m.ID, ), ) }
// Update handles PUT func (ctl *ProfileController) Update(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } m, status, err := models.GetProfile(c.Site.ID, itemID) if err != nil { c.RespondWithErrorDetail(err, status) return } err = c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, itemTypeID, itemID), ) if !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation // Populate site and user ID from goweb context m.SiteID = c.Site.ID status, err = m.Update() if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Replace( c.Site.ID, h.ItemTypes[h.ItemTypeProfile], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithSeeOther( fmt.Sprintf( "%s/%d", h.APITypeProfile, m.ID, ), ) }
// Update handles PUT func (ctl *AttributeController) Update(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } key := c.RouteVars["key"] // Exception from normal model is that we don't attempt to fetch before // we update. We will be doing an upsert (update or insert) rather than // a pure update. As such, the item may not exist before we update it and // we allow that to be resolved later. This works in this case as the data // structure is simple and we don't care about extended metadata m := models.AttributeType{} m.Key = key m.Number = sql.NullFloat64{Float64: math.MaxFloat64} err = c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } perms := models.GetPermission(models.MakeAuthorisationContext(c, 0, itemTypeID, itemID)) if !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } status, err = m.Update(itemTypeID, itemID) if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Replace( c.Site.ID, h.ItemTypes[h.ItemTypeAttribute], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithSeeOther( fmt.Sprintf( "%s/%s", fmt.Sprintf(h.APITypeAttribute, c.RouteVars["type"], itemID), key, ), ) }
// ReadMany handles GET // If microcosm_id is provided in request args then these are the roles for this // microcosm, otherwise this is a list of the default roles on this site func (ctl *RolesController) ReadMany(c *models.Context) { var microcosmID int64 if sid, exists := c.RouteVars["microcosm_id"]; exists { id, err := strconv.ParseInt(sid, 10, 64) if err != nil { c.RespondWithErrorMessage("microcosm_id in URL is not a number", http.StatusBadRequest) return } microcosmID = id } perms := models.GetPermission( models.MakeAuthorisationContext(c, 0, h.ItemTypes[h.ItemTypeMicrocosm], microcosmID), ) if microcosmID > 0 { // Related to a Microcosm if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } } else { // Default role for the site if !c.Auth.IsSiteOwner { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } } // Fetch query string args if any exist limit, offset, status, err := h.GetLimitAndOffset(c.Request.URL.Query()) if err != nil { c.RespondWithErrorDetail(err, status) return } ems, total, pages, status, err := models.GetRoles(c.Site.ID, microcosmID, c.Auth.ProfileID, limit, offset) if err != nil { c.RespondWithErrorDetail(err, status) return } // Construct the response m := models.RolesType{} m.Roles = h.ConstructArray( ems, h.APITypeRole, total, limit, offset, pages, c.Request.URL, ) c.RespondWithData(m) }
// Read handles GET func (ctl *PermissionController) Read(c *models.Context) { ac, status, err := GetAuthContext(c) if err != nil { c.RespondWithErrorDetail(err, status) return } m := models.GetPermission(ac) c.RespondWithData(m) }
// UpdateMany handles PUT for the collection func (ctl *HuddleParticipantsController) UpdateMany(c *models.Context) { // Validate inputs huddleID, err := strconv.ParseInt(c.RouteVars["huddle_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("huddle_id in URL is not a number", http.StatusBadRequest) return } r, status, err := models.GetHuddle(c.Site.ID, c.Auth.ProfileID, huddleID) if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeHuddle], huddleID), ) if !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } if r.IsConfidential == true { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation ems := []models.HuddleParticipantType{} err = c.Fill(&ems) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } status, err = models.UpdateManyHuddleParticipants(c.Site.ID, huddleID, ems) if err != nil { c.RespondWithErrorDetail(err, status) return } c.RespondWithSeeOther( fmt.Sprintf( "%s/%d", h.APITypeHuddle, huddleID, ), ) }
// ReadMany handles GET func (ctl *EventsController) ReadMany(c *models.Context) { // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeEvent], 0), ) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation // Fetch query string args if any exist query := c.Request.URL.Query() limit, offset, status, err := h.GetLimitAndOffset(query) if err != nil { c.RespondWithErrorDetail(err, status) return } attending, status, err := h.GetAttending(query) if err != nil { c.RespondWithErrorDetail(err, status) return } ems, total, pages, status, err := models.GetEvents(c.Site.ID, c.Auth.ProfileID, attending, limit, offset) if err != nil { c.RespondWithErrorDetail(err, status) return } // Construct the response thisLink := h.GetLinkToThisPage(*c.Request.URL, offset, limit, total) m := models.EventsType{} m.Events = h.ConstructArray( ems, h.APITypeEvent, total, limit, offset, pages, c.Request.URL, ) m.Meta.Links = []h.LinkType{ h.LinkType{Rel: "self", Href: thisLink.String()}, } m.Meta.Permissions = perms c.RespondWithData(m) }
// UpdateMany handles PUT for the collection func (ctl *AttributesController) UpdateMany(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } ems := []models.AttributeType{} err = c.Fill(&ems) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } for _, v := range ems { if strings.Trim(v.Key, " ") == "" { c.RespondWithErrorMessage( "key must be supplied with every attribute when updating multiple attributes", http.StatusBadRequest, ) return } } perms := models.GetPermission(models.MakeAuthorisationContext(c, 0, itemTypeID, itemID)) if !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } status, err = models.UpdateManyAttributes(itemTypeID, itemID, ems) if err != nil { c.RespondWithErrorDetail(err, status) return } for _, m := range ems { audit.Replace( c.Site.ID, h.ItemTypes[h.ItemTypeAttribute], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) } c.RespondWithOK() }
// ReadMany handles GET for the collection func (ctl *HuddleParticipantsController) ReadMany(c *models.Context) { // Validate inputs huddleID, err := strconv.ParseInt(c.RouteVars["huddle_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("huddle_id in URL is not a number", http.StatusBadRequest) return } r, status, err := models.GetHuddle(c.Site.ID, c.Auth.ProfileID, huddleID) if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeHuddle], huddleID), ) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation limit, offset, status, err := h.GetLimitAndOffset(c.Request.URL.Query()) if err != nil { c.RespondWithErrorDetail(err, status) return } ems, total, pages, status, err := models.GetHuddleParticipants(c.Site.ID, huddleID, limit, offset) if err != nil { c.RespondWithErrorDetail(err, status) return } // Construct the response m := models.HuddleParticipantsType{} m.HuddleParticipants = h.ConstructArray( ems, fmt.Sprintf("%s/participants", r.GetLink()), total, limit, offset, pages, c.Request.URL, ) c.RespondWithData(m) }
// Create handles GET func (ctl *MicrocosmsController) Create(c *models.Context) { // Validate inputs m := models.MicrocosmType{} err := c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Start : Authorisation perms := models.GetPermission( models.MakeAuthorisationContext(c, 0, h.ItemTypes[h.ItemTypeSite], c.Site.ID), ) if !perms.CanCreate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End : Authorisation // Populate where applicable from auth and context m.SiteID = c.Site.ID m.Meta.CreatedByID = c.Auth.ProfileID m.Meta.Created = time.Now() m.OwnedByID = c.Auth.ProfileID status, err := m.Insert() if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Create( c.Site.ID, h.ItemTypes[h.ItemTypeMicrocosm], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithSeeOther( fmt.Sprintf( "%s/%d", h.APITypeMicrocosm, m.ID, ), ) }
// Read handles GET func (ctl *AttendeeController) Read(c *models.Context) { // Verify ID is a positive integer eventID, err := strconv.ParseInt(c.RouteVars["event_id"], 10, 64) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The supplied event_id ('%s') is not a number.", c.RouteVars["event_id"]), http.StatusBadRequest, ) return } profileID, err := strconv.ParseInt(c.RouteVars["profile_id"], 10, 64) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The supplied profile_id ('%s') is not a number.", c.RouteVars["profile_id"]), http.StatusBadRequest, ) return } attendeeID, status, err := models.GetAttendeeID(eventID, profileID) if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeAttendee], attendeeID), ) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation // Read Event m, status, err := models.GetAttendee(c.Site.ID, attendeeID) if err != nil { c.RespondWithErrorDetail(err, status) return } m.Meta.Permissions = perms c.RespondWithData(m) }
// Read handles GET func (ctl *CommentContextController) Read(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, itemTypeID, itemID), ) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation limit, _, status, err := h.GetLimitAndOffset(c.Request.URL.Query()) if err != nil { c.RespondWithErrorDetail(err, status) return } m, status, err := models.GetCommentSummary(c.Site.ID, itemID) if err != nil { c.RespondWithErrorDetail(err, status) return } link, status, err := m.GetPageLink(limit, c.Auth.ProfileID) if err != nil { c.RespondWithErrorDetail(err, status) return } pageURL, err := url.Parse(link.Href) if err != nil { c.RespondWithErrorMessage(err.Error(), http.StatusInternalServerError) return } queryString := pageURL.Query() queryString.Add("comment_id", strconv.FormatInt(m.ID, 10)) pageURL.RawQuery = queryString.Encode() c.RespondWithLocation(pageURL.String()) }
// Delete handles DELETE func (ctl *CommentController) Delete(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, itemTypeID, itemID), ) if !perms.CanDelete { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation // Partially instantiated type for Id passing m, status, err := models.GetCommentSummary(c.Site.ID, itemID) if err != nil { if status == http.StatusNotFound { c.RespondWithOK() return } c.RespondWithErrorDetail(err, status) return } // Delete resource status, err = m.Delete(c.Site.ID) if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Delete( c.Site.ID, h.ItemTypes[h.ItemTypeComment], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithOK() }
// Delete handles DELETE func (ctl *HuddleController) Delete(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, itemTypeID, itemID), ) if !perms.CanDelete { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation m, status, err := models.GetHuddle(c.Site.ID, c.Auth.ProfileID, itemID) if err != nil { if status == http.StatusNotFound { c.RespondWithOK() return } c.RespondWithErrorDetail(err, status) return } status, err = m.Delete(c.Site.ID, c.Auth.ProfileID) if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Delete( c.Site.ID, h.ItemTypes[h.ItemTypeHuddle], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithOK() }
// Update handles PUT func (ctl *HuddleParticipantController) Update(c *models.Context) { huddleID, err := strconv.ParseInt(c.RouteVars["huddle_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("huddle_id in URL is not a number", http.StatusBadRequest) return } r, status, err := models.GetHuddle(c.Site.ID, c.Auth.ProfileID, huddleID) if err != nil { c.RespondWithErrorDetail(err, status) return } profileID, err := strconv.ParseInt(c.RouteVars["profile_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("profile_id in URL is not a number", http.StatusBadRequest) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeHuddle], huddleID), ) if !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } if r.IsConfidential == false { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation m := models.HuddleParticipantType{} m.ID = profileID status, err = m.Update(c.Site.ID, huddleID) if err != nil { c.RespondWithErrorDetail(err, status) return } c.RespondWithSeeOther(m.GetLink(r.GetLink())) }
// Delete handles DELETE func (ctl *HuddleParticipantController) Delete(c *models.Context) { huddleID, err := strconv.ParseInt(c.RouteVars["huddle_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("huddle_id in URL is not a number", http.StatusBadRequest) return } _, status, err := models.GetHuddle(c.Site.ID, c.Auth.ProfileID, huddleID) if err != nil { c.RespondWithErrorDetail(err, status) return } profileID, err := strconv.ParseInt(c.RouteVars["profile_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("profile_id in URL is not a number", http.StatusBadRequest) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeHuddle], huddleID), ) if !perms.CanDelete { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation if profileID != c.Auth.ProfileID { c.RespondWithErrorMessage("Only the participant in question can remove a participant from a huddle", http.StatusBadRequest) return } m := models.HuddleParticipantType{} m.ID = profileID status, err = m.Delete(huddleID) if err != nil { c.RespondWithErrorDetail(err, status) return } c.RespondWithOK() }
// ReadMany handles GET for a collection func (ctl *AttributesController) ReadMany(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } perms := models.GetPermission(models.MakeAuthorisationContext(c, 0, itemTypeID, itemID)) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // Fetch query string args if any exist limit, offset, status, err := h.GetLimitAndOffset(c.Request.URL.Query()) if err != nil { c.RespondWithErrorDetail(err, status) return } ems, total, pages, status, err := models.GetAttributes(itemTypeID, itemID, limit, offset) if err != nil { c.RespondWithErrorDetail(err, status) return } // Construct the response m := models.AttributesType{} m.Attributes = h.ConstructArray( ems, fmt.Sprintf(h.APITypeAttribute, c.RouteVars["type"], 0), total, limit, offset, pages, c.Request.URL, ) c.RespondWithData(m) }
// ReadMany handles GET func (ctl *MicrocosmsController) ReadMany(c *models.Context) { perms := models.GetPermission( models.MakeAuthorisationContext(c, 0, h.ItemTypes[h.ItemTypeSite], c.Site.ID), ) // Fetch query string args if any exist limit, offset, status, err := h.GetLimitAndOffset(c.Request.URL.Query()) if err != nil { c.RespondWithErrorDetail(err, status) return } // Fetch list of microcosms ems, total, pages, status, err := models.GetMicrocosms(c.Site.ID, c.Auth.ProfileID, limit, offset) if err != nil { c.RespondWithErrorDetail(err, status) return } // Construct the response thisLink := h.GetLinkToThisPage(*c.Request.URL, offset, limit, total) m := models.MicrocosmsType{} m.Microcosms = h.ConstructArray( ems, h.APITypeMicrocosm, total, limit, offset, pages, c.Request.URL, ) m.Meta.Links = []h.LinkType{ h.LinkType{Rel: "self", Href: thisLink.String()}, } m.Meta.Permissions = perms c.RespondWithData(m) }
// Read handles GET func (ctl *CommentController) Read(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, itemTypeID, itemID), ) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation limit, _, status, err := h.GetLimitAndOffset(c.Request.URL.Query()) if err != nil { c.RespondWithErrorDetail(err, status) return } m, status, err := models.GetComment(c.Site.ID, itemID, c.Auth.ProfileID, limit) if err != nil { c.RespondWithErrorDetail(err, status) return } m.Meta.Permissions = perms if c.Auth.ProfileID > 0 { go models.MarkAsRead(m.ItemTypeID, m.ItemID, c.Auth.ProfileID, m.Meta.Created) } c.RespondWithData(m) }
// Read handles GET func (ctl *HuddleParticipantController) Read(c *models.Context) { huddleID, err := strconv.ParseInt(c.RouteVars["huddle_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("huddle_id in URL is not a number", http.StatusBadRequest) return } _, status, err := models.GetHuddle(c.Site.ID, c.Auth.ProfileID, huddleID) if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeHuddle], huddleID), ) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation profileID, err := strconv.ParseInt(c.RouteVars["profile_id"], 10, 64) if err != nil { c.RespondWithErrorMessage("profile_id in URL is not a number", http.StatusBadRequest) return } m, status, err := models.GetHuddleParticipant(c.Site.ID, huddleID, profileID) if err != nil { c.RespondWithErrorDetail(err, status) return } c.RespondWithData(m) }
// ReadMany handles GET func (ctl *AttendeesCSVController) ReadMany(c *models.Context) { eventID, err := strconv.ParseInt(c.RouteVars["event_id"], 10, 64) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The supplied event_id ('%s') is not a number.", c.RouteVars["event_id"]), http.StatusBadRequest, ) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeEvent], eventID), ) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } if !(perms.IsOwner || perms.IsModerator || perms.IsSiteOwner) { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation attendees, status, err := models.GetAttendeesCSV(c.Site.ID, eventID, c.Auth.ProfileID) if err != nil { c.RespondWithErrorDetail(err, status) return } c.ResponseWriter.Header().Set(`Cache-Control`, `no-cache, max-age=0`) c.ResponseWriter.Header().Set(`Vary`, `Authorization`) c.ResponseWriter.Header().Set(`Content-Type`, `text/csv`) c.ResponseWriter.Header().Set(`Content-Disposition`, fmt.Sprintf(`attachment; filename=event%d.csv`, eventID)) c.WriteResponse([]byte(attendees), http.StatusOK) }
// Create handles POST func (ctl *EventsController) Create(c *models.Context) { m := models.EventType{} m.Meta.Flags.Open = true err := c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Start : Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeMicrocosm], m.MicrocosmID), ) if !perms.CanCreate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End : Authorisation // Populate where applicable from auth and context m.Meta.CreatedByID = c.Auth.ProfileID m.Meta.Created = time.Now() status, err := m.Insert(c.Site.ID, c.Auth.ProfileID) if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Create( c.Site.ID, h.ItemTypes[h.ItemTypeEvent], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) go models.SendUpdatesForNewItemInAMicrocosm(c.Site.ID, m) go models.RegisterWatcher( c.Auth.ProfileID, h.UpdateTypes[h.UpdateTypeNewComment], m.ID, h.ItemTypes[h.ItemTypeEvent], c.Site.ID, ) c.RespondWithSeeOther( fmt.Sprintf( "%s/%d", h.APITypeEvent, m.ID, ), ) }
// Delete handles DELETE func (ctl *AttendeeController) Delete(c *models.Context) { // Validate inputs eventID, err := strconv.ParseInt(c.RouteVars["event_id"], 10, 64) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The supplied event_id ('%s') is not a number.", c.RouteVars["event_id"]), http.StatusBadRequest, ) return } profileID, err := strconv.ParseInt(c.RouteVars["profile_id"], 10, 64) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The supplied profile_id ('%s') is not a number.", c.RouteVars["profile_id"]), http.StatusBadRequest, ) return } attendeeID, status, err := models.GetAttendeeID(eventID, profileID) if err != nil { c.RespondWithOK() return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeAttendee], attendeeID), ) if !perms.CanDelete { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation m, status, err := models.GetAttendee(c.Site.ID, attendeeID) if err != nil { c.RespondWithErrorDetail(err, status) return } // Delete resource status, err = m.Delete(c.Site.ID) if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Replace( c.Site.ID, h.ItemTypes[h.ItemTypeAttendee], attendeeID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithOK() }
// Patch handles PATCH func (ctl *EventController) Patch(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } patches := []h.PatchType{} err = c.Fill(&patches) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } status, err = h.TestPatch(patches) if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation ac := models.MakeAuthorisationContext(c, 0, itemTypeID, itemID) perms := models.GetPermission(ac) if !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // All patches are 'replace' for _, patch := range patches { status, err := patch.ScanRawValue() if !patch.Bool.Valid { c.RespondWithErrorDetail(err, status) return } switch patch.Path { case "/meta/flags/sticky": // Only super users' can sticky and unsticky if !perms.IsModerator { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } if !patch.Bool.Valid { c.RespondWithErrorMessage("/meta/flags/sticky requires a bool value", http.StatusBadRequest) return } case "/meta/flags/open": // Only super users' and item owners can open and close if !(perms.IsModerator || perms.IsOwner) { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } if !patch.Bool.Valid { c.RespondWithErrorMessage("/meta/flags/open requires a bool value", http.StatusBadRequest) return } case "/meta/flags/deleted": // Only super users' can undelete, but super users' and owners can delete if !patch.Bool.Valid { c.RespondWithErrorMessage("/meta/flags/deleted requires a bool value", http.StatusBadRequest) return } if (patch.Bool.Bool == false && !(perms.IsModerator || perms.IsOwner)) || !perms.IsModerator { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } case "/meta/flags/moderated": if !perms.IsModerator { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } default: c.RespondWithErrorMessage("Invalid patch operation path", http.StatusBadRequest) return } } // End Authorisation m, status, err := models.GetEvent(c.Site.ID, itemID, c.Auth.ProfileID) if err != nil { c.RespondWithErrorDetail(err, status) return } status, err = m.Patch(ac, patches) if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Update( c.Site.ID, h.ItemTypes[h.ItemTypeEvent], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithOK() }
// Update handles PUT func (ctl *AttendeeController) Update(c *models.Context) { // Verify ID is a positive integer eventID, err := strconv.ParseInt(c.RouteVars["event_id"], 10, 64) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The supplied event_id ('%s') is not a number.", c.RouteVars["event_id"]), http.StatusBadRequest, ) return } m := models.AttendeeType{} err = c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeEvent], eventID), ) if !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } if perms.IsOwner || perms.IsModerator || perms.IsSiteOwner { if m.ProfileID != c.Auth.ProfileID && m.RSVP == "yes" { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } } else { if m.ProfileID != c.Auth.ProfileID { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } } _, status, err := models.GetProfileSummary(c.Site.ID, m.ProfileID) if err != nil { c.RespondWithErrorMessage(h.NoAuthMessage, status) return } // End Authorisation // Populate where applicable from auth and context t := time.Now() m.EventID = eventID m.Meta.CreatedByID = c.Auth.ProfileID m.Meta.Created = t m.Meta.EditedByNullable = sql.NullInt64{Int64: c.Auth.ProfileID, Valid: true} m.Meta.EditedNullable = pq.NullTime{Time: t, Valid: true} status, err = m.Update(c.Site.ID) if err != nil { c.RespondWithErrorDetail(err, status) return } if m.RSVP == "yes" { go models.SendUpdatesForNewAttendeeInAnEvent(c.Site.ID, m) } audit.Replace( c.Site.ID, h.ItemTypes[h.ItemTypeAttendee], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithSeeOther( fmt.Sprintf("%s/%d", fmt.Sprintf(h.APITypeAttendee, m.EventID), m.ProfileID), ) }
// Read handles GET func (ctl *EventController) Read(c *models.Context) { _, itemTypeID, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } // Start Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, itemTypeID, itemID), ) if !perms.CanRead { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End Authorisation // Read Event m, status, err := models.GetEvent(c.Site.ID, itemID, c.Auth.ProfileID) if err != nil { c.RespondWithErrorDetail(err, status) return } // Get Comments m.Comments, status, err = models.GetComments( c.Site.ID, h.ItemTypeEvent, m.ID, c.Request.URL, c.Auth.ProfileID, m.Meta.Created, ) if err != nil { c.RespondWithErrorDetail(err, status) return } m.Meta.Permissions = perms // Mark as read (to the last comment on this page if applicable) if c.Auth.ProfileID > 0 { read := m.Meta.Created switch m.Comments.Items.(type) { case []models.CommentSummaryType: comments := m.Comments.Items.([]models.CommentSummaryType) if len(comments) > 0 { read = comments[len(comments)-1].Meta.Created if m.Comments.Page >= m.Comments.Pages { read = time.Now() } } default: } go models.MarkAsRead(h.ItemTypes[h.ItemTypeEvent], m.ID, c.Auth.ProfileID, read) // Get watcher status watcherID, sendEmail, sendSms, ignored, status, err := models.GetWatcherAndIgnoreStatus( h.ItemTypes[h.ItemTypeEvent], m.ID, c.Auth.ProfileID, ) if err != nil { c.RespondWithErrorDetail(err, status) return } if ignored { m.Meta.Flags.Ignored = true } if watcherID > 0 { m.Meta.Flags.Watched = true m.Meta.Flags.SendEmail = sendEmail m.Meta.Flags.SendSMS = sendSms } } go models.IncrementViewCount(h.ItemTypes[h.ItemTypeEvent], m.ID) c.RespondWithData(m) }