// Update handles PUT func (ctl *ProfileOptionsController) Update(c *models.Context) { var m = models.ProfileOptionType{} err := c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Profile ID cannot be changed m.ProfileID = c.Auth.ProfileID status, err := m.Update() if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Update( c.Site.ID, h.ItemTypes[h.ItemTypeProfile], m.ProfileID, c.Auth.ProfileID, time.Now(), c.IP, ) // Respond c.RespondWithSeeOther( fmt.Sprintf("/api/v1/profiles/options"), ) }
// Update handles PUT func (ctl *IgnoredController) Update(c *models.Context) { m := models.IgnoreType{} err := c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } if c.Auth.ProfileID < 1 { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } m.ProfileID = c.Auth.ProfileID status, err := m.Update() if err != nil { c.RespondWithErrorDetail(err, status) return } c.RespondWithOK() }
// 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 *ProfileReadController) Update(c *models.Context) { if c.Auth.ProfileID == 0 { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } rs := models.ReadScopeType{} err := c.Fill(&rs) if err != nil { glog.Errorln(err.Error()) c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } itemTypeID, ok := h.ItemTypes[rs.ItemType] if !ok { c.RespondWithErrorMessage("Unknown item type", http.StatusBadRequest) return } rs.ItemTypeID = itemTypeID status, err := models.MarkScopeAsRead(c.Auth.ProfileID, rs) if err != nil { c.RespondWithErrorDetail(err, status) return } c.RespondWithOK() }
// 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, ), ) }
// Create handles POST func (ctl *ProfilesController) Create(c *models.Context) { m := models.ProfileType{} m.Visible = true err := c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // TODO: Auth rules on creation if m.SiteID != 0 { c.RespondWithErrorMessage( "You cannot supply a site ID when creating a profile", http.StatusBadRequest, ) return } if m.UserID != 0 { c.RespondWithErrorMessage( "You cannot supply a user ID when creating a profile", http.StatusBadRequest, ) return } // Populate site and user ID from goweb context m.SiteID = c.Site.ID m.UserID = c.Auth.UserID status, err := m.Insert() if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Create( 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, ), ) }
// Update handles PUT func (ctl *WatcherController) Update(c *models.Context) { m := models.WatcherType{} err := c.Fill(&m) if err != nil { glog.Warning(err) c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } itemType := strings.ToLower(m.ItemType) if itemType != "" { if _, exists := h.ItemTypes[itemType]; !exists { glog.Warning(err) c.RespondWithErrorMessage( fmt.Sprintf("Watcher could not be saved: Item type not found"), http.StatusBadRequest, ) return } m.ItemTypeID = h.ItemTypes[itemType] } var status int // watcher must exist to be updated // Also the returned watcher ID belongs to the authed person by definition // - no need to check later m.ID, _, _, _, status, err = models.GetWatcherAndIgnoreStatus( m.ItemTypeID, m.ItemID, c.Auth.ProfileID, ) if err != nil { glog.Error(err) c.RespondWithErrorDetail(err, status) return } // To update we only need id, SendEmail and SendSMS status, err = m.Update() if err != nil { glog.Error(err) c.RespondWithErrorMessage( fmt.Sprintf("Could not update watcher: %v", err.Error()), http.StatusBadRequest, ) return } // Respond c.RespondWithOK() }
// Update handles PUT func (ctl *SiteController) Update(c *models.Context) { _, _, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } m, status, err := models.GetSite(itemID) if err != nil { c.RespondWithErrorDetail(err, status) return } // Use the user ID to check, since the current context is a different site (the root site) // than the site the owner profile is associated with. owner, status, err := models.GetProfileSummary(m.ID, m.OwnedByID) if err != nil { c.RespondWithErrorDetail(err, status) return } if owner.UserID != c.Auth.UserID { c.RespondWithErrorMessage( fmt.Sprintf("You must be the owner of the site to update it"), http.StatusForbidden, ) return } err = c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } status, err = m.Update() if err != nil { c.RespondWithErrorDetail(err, status) return } audit.Replace( c.Site.ID, h.ItemTypes[h.ItemTypeSite], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithSeeOther(fmt.Sprintf("%s/%d", h.APITypeSite, m.ID)) }
// 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, ), ) }
// 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() }
// 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, ), ) }
// Update handles PUT func (ctl *UpdateOptionController) Update(c *models.Context) { _, _, itemID, status, err := c.GetItemTypeAndItemID() if err != nil { c.RespondWithErrorDetail(err, status) return } var exists bool m, status, err := models.GetUpdateOptionByUpdateType(c.Auth.ProfileID, itemID) if err != nil && status != http.StatusNotFound { c.RespondWithErrorDetail(err, status) return } if status == http.StatusOK { exists = true } err = c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Profile ID cannot be changed m.UpdateTypeID = itemID m.ProfileID = c.Auth.ProfileID if exists { // Update status, err = m.Update() } else { // Create status, err = m.Insert() } if err != nil { c.RespondWithErrorDetail(err, status) return } // Respond c.RespondWithSeeOther( fmt.Sprintf( h.APITypeUpdateOptionType, m.UpdateTypeID, ), ) }
// Create handles POST func (ctl *WatchersController) Create(c *models.Context) { // Fill from POST data m := WatcherType{} err := c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } itemType := strings.ToLower(m.ItemType) if itemType != "" { if _, exists := h.ItemTypes[itemType]; !exists { c.RespondWithErrorMessage( fmt.Sprintf("Watcher could not be saved: Item type not found"), http.StatusBadRequest, ) return } m.ItemTypeID = h.ItemTypes[itemType] } else { c.RespondWithErrorMessage( fmt.Sprintf("No itemType supplied, cannot create a watcher"), http.StatusBadRequest, ) return } sendEmail, status, err := models.RegisterWatcher( c.Auth.ProfileID, m.UpdateTypeID, m.ItemID, m.ItemTypeID, c.Site.ID, ) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Watcher could not be registered: %v", err.Error()), status, ) return } c.RespondWithData(sendEmail) }
// Update handles PUT func (ctl *MenuController) Update(c *models.Context, siteID int64) { ems := []h.LinkType{} // Start :: Auth site, status, err := models.GetSite(siteID) if err != nil { c.RespondWithErrorDetail(err, status) return } // Use the user ID to check, since the current context is a different site (the root site) // than the site the owner profile is associated with. owner, status, err := models.GetProfileSummary(site.ID, site.OwnedByID) if err != nil { c.RespondWithErrorDetail(err, status) return } if owner.UserID != c.Auth.UserID { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } // End :: Auth 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.UpdateMenu(siteID, ems) if err != nil { c.RespondWithErrorDetail(err, status) return } 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), ) }
// Create handles POST func (ctl *AuthController) Create(c *models.Context) { accessTokenRequest := models.AccessTokenRequestType{} err := c.Fill(&accessTokenRequest) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Audience is the host that Persona authenticates the user for var audience string if c.Site.Domain != "" { audience = c.Site.Domain } else if c.Site.SubdomainKey == "root" { audience = conf.ConfigStrings[conf.MicrocosmDomain] } else { audience = fmt.Sprintf("%s.%s", c.Site.SubdomainKey, conf.ConfigStrings[conf.MicrocosmDomain]) } // Verify persona assertion personaRequest := models.PersonaRequestType{ Assertion: accessTokenRequest.Assertion, Audience: audience, } jsonData, err := json.Marshal(personaRequest) if err != nil { glog.Errorf("Could not marshal Persona req: %s", err.Error()) c.RespondWithErrorMessage( fmt.Sprintf("Bad persona request format: %v", err.Error()), http.StatusBadRequest, ) return } resp, err := http.Post( conf.ConfigStrings[conf.PersonaVerifierURL], "application/json", bytes.NewReader(jsonData), ) if err != nil { glog.Errorln(err.Error()) c.RespondWithErrorMessage( fmt.Sprintf("Persona verification error: %v", err.Error()), http.StatusInternalServerError, ) return } body, err := ioutil.ReadAll(resp.Body) if err != nil { glog.Errorf("Couldn't read Persona response: %s", err.Error()) c.RespondWithErrorMessage( fmt.Sprintf("Error unmarshalling persona response: %v", err.Error()), http.StatusInternalServerError, ) return } resp.Body.Close() var personaResponse = models.PersonaResponseType{} json.Unmarshal(body, &personaResponse) if personaResponse.Status != "okay" { // Split and decode the assertion to log the user's email address. var decoded bool if personaRequest.Assertion != "" { parts := strings.Split(personaRequest.Assertion, "~") moreParts := strings.Split(parts[0], ".") if len(moreParts) > 1 { data, err := base64.StdEncoding.DecodeString(moreParts[1] + "====") if err == nil { decoded = true glog.Errorf("Bad Persona response: %+v with decoded assertion: %+v", personaResponse, data) } } } if !decoded { glog.Errorf("Bad Persona response: %+v with assertion: %+v", personaResponse, personaRequest) } c.RespondWithErrorMessage( fmt.Sprintf("Persona login error: %v", personaResponse.Status), http.StatusInternalServerError, ) return } if personaResponse.Email == "" { glog.Errorf("No persona email address") c.RespondWithErrorMessage( "Persona error: no email address received", http.StatusInternalServerError, ) return } // Retrieve user details by email address user, status, err := models.GetUserByEmailAddress(personaResponse.Email) if status == http.StatusNotFound { // Check whether this email is a spammer before we attempt to create // an account if models.IsSpammer(personaResponse.Email) { glog.Errorf("Spammer: %s", personaResponse.Email) c.RespondWithErrorMessage("Spammer", http.StatusInternalServerError) return } user, status, err = models.CreateUserByEmailAddress(personaResponse.Email) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Couldn't create user: %v", err.Error()), http.StatusInternalServerError, ) return } } else if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Error retrieving user: %v", err.Error()), http.StatusInternalServerError, ) return } // Create a corresponding profile for this user profile, status, err := models.GetOrCreateProfile(c.Site, user) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Failed to create profile with ID %d: %v", profile.ID, err.Error()), status, ) return } // Fetch API client details by secret client, err := models.RetrieveClientBySecret(accessTokenRequest.ClientSecret) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Error processing client secret: %v", err.Error()), http.StatusInternalServerError, ) return } // Create and store access token tokenValue, err := h.RandString(128) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Could not generate a random string: %v", err.Error()), http.StatusInternalServerError, ) return } m := models.AccessTokenType{} m.TokenValue = tokenValue m.UserID = user.ID m.ClientID = client.ClientID status, err = m.Insert() if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Could not create an access token: %v", err.Error()), status, ) return } audit.Create( c.Site.ID, h.ItemTypes[h.ItemTypeAuth], profile.ID, profile.ID, time.Now(), c.IP, ) c.RespondWithData(tokenValue) }
// Create handles POST func (ctl *UsersController) Create(c *models.Context) { // Batch create users by email address ems := []models.UserType{} err := c.Fill(&ems) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } if !c.Auth.IsSiteOwner { c.RespondWithErrorMessage( "Only a site owner can batch create users", http.StatusForbidden, ) return } for _, m := range ems { status, err := m.Validate(false) if err != nil { c.RespondWithErrorDetail(err, status) return } } // We are good to go profiles := []models.ProfileType{} for _, m := range ems { // Retrieve user details by email address user, status, err := models.GetUserByEmailAddress(m.Email) if status == http.StatusNotFound { user, status, err = models.CreateUserByEmailAddress(m.Email) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Couldn't create user: %v", err.Error()), http.StatusInternalServerError, ) return } audit.Create( c.Site.ID, h.ItemTypes[h.ItemTypeUser], user.ID, c.Auth.ProfileID, time.Now(), c.IP, ) } else if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Error retrieving user: %v", err.Error()), http.StatusInternalServerError, ) return } // create a corresponding profile for this user profile, status, err := models.GetOrCreateProfile(c.Site, user) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Failed to create profile with ID %d: %v", profile.ID, err.Error()), status, ) return } audit.Create( c.Site.ID, h.ItemTypes[h.ItemTypeProfile], profile.ID, c.Auth.ProfileID, time.Now(), c.IP, ) profiles = append(profiles, profile) } c.RespondWithData(profiles) }
// Patch handles PATCH func (ctl *RoleController) Patch(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("microcosm_id in URL is not a number", http.StatusBadRequest) 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, microcosmID, h.ItemTypes[h.ItemTypeMicrocosm], microcosmID) perms := models.GetPermission(ac) 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 } } // 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 "/moderator": if !patch.Bool.Valid { c.RespondWithErrorMessage("/moderator requires a bool value", http.StatusBadRequest) return } case "/banned": if !patch.Bool.Valid { c.RespondWithErrorMessage("/banned requires a bool value", http.StatusBadRequest) return } case "/read": if !patch.Bool.Valid { c.RespondWithErrorMessage("/read requires a bool value", http.StatusBadRequest) return } case "/create": if !patch.Bool.Valid { c.RespondWithErrorMessage("/create requires a bool value", http.StatusBadRequest) return } case "/update": if !patch.Bool.Valid { c.RespondWithErrorMessage("/update requires a bool value", http.StatusBadRequest) return } case "/delete": if !patch.Bool.Valid { c.RespondWithErrorMessage("/delete requires a bool value", http.StatusBadRequest) return } case "/closeOwn": if !patch.Bool.Valid { c.RespondWithErrorMessage("/closeOwn requires a bool value", http.StatusBadRequest) return } case "/openOwn": if !patch.Bool.Valid { c.RespondWithErrorMessage("/openOwn requires a bool value", http.StatusBadRequest) return } case "/readOthers": if !patch.Bool.Valid { c.RespondWithErrorMessage("/readOthers requires a bool value", http.StatusBadRequest) return } default: c.RespondWithErrorMessage("Invalid patch operation path", http.StatusBadRequest) return } } // End Authorisation m, status, err := models.GetRole(c.Site.ID, microcosmID, roleID, 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.ItemTypeRole], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithOK() }
// Create handles POST func (ctl *AttachmentsController) Create(c *models.Context) { attachment := models.AttachmentType{} err := c.Fill(&attachment) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } if attachment.FileHash == "" { c.RespondWithErrorMessage( "You must supply a file hash", http.StatusBadRequest, ) return } // Check that the file hash has a corresponding attachment_meta record metadata, status, err := models.GetMetadata(attachment.FileHash) if err != nil { if status == http.StatusNotFound { c.RespondWithErrorMessage( fmt.Sprintf("File does not have a metadata record"), http.StatusBadRequest, ) return } c.RespondWithErrorMessage( fmt.Sprintf("Could not retrieve metadata: %v", err.Error()), http.StatusBadRequest, ) return } attachment.AttachmentMetaID = metadata.AttachmentMetaID // Determine whether this is an attachment to a profile or comment, and if the // user is authorised to do so pathPrefix := "" if c.RouteVars["profile_id"] != "" { 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 } _, status, err := models.GetProfileSummary(c.Site.ID, profileID) if err != nil { if status == http.StatusNotFound { c.RespondWithErrorMessage( fmt.Sprintf("Profile with ID ('%d') does not exist.", profileID), http.StatusBadRequest, ) return } c.RespondWithErrorMessage( fmt.Sprintf("Could not retrieve profile: %v.", err.Error()), http.StatusInternalServerError, ) return } perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeProfile], profileID), ) if !perms.CanCreate && !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } attachment.ItemID = profileID attachment.ItemTypeID = h.ItemTypes[h.ItemTypeProfile] pathPrefix = h.APITypeProfile } else if c.RouteVars["comment_id"] != "" { commentID, err := strconv.ParseInt(c.RouteVars["comment_id"], 10, 64) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The supplied comment ID ('%s') is not a number.", c.RouteVars["comment_id"]), http.StatusBadRequest, ) return } _, status, err := models.GetCommentSummary(c.Site.ID, commentID) if err != nil { if status == http.StatusNotFound { c.RespondWithErrorMessage( fmt.Sprintf("Comment with ID ('%d') does not exist.", commentID), http.StatusBadRequest, ) return } c.RespondWithErrorMessage( fmt.Sprintf("Could not retrieve comment: %v.", err.Error()), http.StatusInternalServerError, ) return } perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, h.ItemTypes[h.ItemTypeComment], commentID), ) if !perms.CanCreate && !perms.CanUpdate { c.RespondWithErrorMessage(h.NoAuthMessage, http.StatusForbidden) return } if metadata.FileSize > 3145728 { c.RespondWithErrorMessage(fmt.Sprintf("File size must be under 3 megabytes"), http.StatusBadRequest) return } attachment.ItemID = commentID attachment.ItemTypeID = h.ItemTypes[h.ItemTypeComment] pathPrefix = h.APITypeComment } else { c.RespondWithErrorMessage( "You must supply a profile_id or comment_id as a RouteVar", http.StatusBadRequest, ) return } // Check that this file hasn't already been attached to this item oldattachment := models.AttachmentType{} oldattachment, status, err = models.GetAttachment( attachment.ItemTypeID, attachment.ItemID, attachment.FileHash, false, ) if err != nil && status != http.StatusNotFound { c.RespondWithErrorMessage( fmt.Sprintf("An error occurred when checking the attachment: %v", err.Error()), http.StatusInternalServerError, ) return } if status != http.StatusNotFound && attachment.ItemTypeID != h.ItemTypes[h.ItemTypeProfile] { c.RespondWithSeeOther( fmt.Sprintf("%s/%d/%s", pathPrefix, oldattachment.ItemID, h.APITypeAttachment), ) return } if status == http.StatusNotFound { // Update attach count on attachment_meta metadata.AttachCount++ status, err = metadata.Update() if err != nil { c.RespondWithErrorDetail(err, status) return } attachment.ProfileID = c.Auth.ProfileID attachment.Created = time.Now() status, err = attachment.Insert() if err != nil { c.RespondWithErrorDetail(err, status) return } } else { //already exists, need to update it and pull back the attachmentId attachment = oldattachment attachment.Created = time.Now() status, err = attachment.Update() if err != nil { c.RespondWithErrorDetail(err, status) return } } // If attaching to a profile, update the profile with new avatar URL if attachment.ItemTypeID == h.ItemTypes[h.ItemTypeProfile] { profile, _, err := models.GetProfile(c.Site.ID, attachment.ItemID) if err != nil { c.RespondWithErrorDetail(err, status) return } filePath := metadata.FileHash if metadata.FileExt != "" { filePath += `.` + metadata.FileExt } profile.AvatarURLNullable = sql.NullString{ String: fmt.Sprintf("%s/%s", h.APITypeFile, filePath), Valid: true, } profile.AvatarIDNullable = sql.NullInt64{ Int64: attachment.AttachmentID, Valid: true, } status, err = profile.Update() if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Could not update profile with avatar: %v", err.Error()), status, ) return } } c.RespondWithSeeOther( fmt.Sprintf("%s/%d/%s", pathPrefix, attachment.ItemID, h.APITypeAttachment), ) }
// UpdateMany handles PUT on the collection func (ctl *AttendeesController) UpdateMany(c *models.Context) { // Verify event_id is a positive integer eventID, err := strconv.ParseInt(c.RouteVars["event_id"], 10, 64) if err != nil { glog.Errorln(err.Error()) c.RespondWithErrorMessage( fmt.Sprintf("The supplied event ID ('%s') is not a number.", c.RouteVars["event_id"]), http.StatusBadRequest, ) return } ems := []models.AttendeeType{} err = c.Fill(&ems) if err != nil { glog.Errorln(err.Error()) 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.CanCreate { c.RespondWithErrorDetail( e.New(c.Site.ID, c.Auth.ProfileID, "attendees.go::UpdateMany", e.NoCreate, "Not authorized to create attendee: CanCreate false"), http.StatusForbidden, ) return } // Everyone can set self to any status. Event/site owners can set people to any status apart from 'attending'. // Also check that profile exists on site. if perms.IsOwner || perms.IsModerator || perms.IsSiteOwner { for _, m := range ems { if m.ProfileID != c.Auth.ProfileID && m.RSVP == "yes" { 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 } } } else { for _, m := range ems { 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 t := time.Now() // Populate where applicable from auth and context for i := range ems { ems[i].EventID = eventID ems[i].Meta.CreatedByID = c.Auth.ProfileID ems[i].Meta.Created = t ems[i].Meta.EditedNullable = pq.NullTime{Time: t, Valid: true} ems[i].Meta.EditedByNullable = sql.NullInt64{Int64: c.Auth.ProfileID, Valid: true} } status, err := models.UpdateManyAttendees(c.Site.ID, ems) if err != nil { glog.Error(err) c.RespondWithErrorDetail(err, status) return } for _, m := range ems { if m.RSVP == "yes" { go models.SendUpdatesForNewAttendeeInAnEvent(c.Site.ID, m) // The new attendee should be following the event now go models.RegisterWatcher( m.ProfileID, h.UpdateTypes[h.UpdateTypeEventReminder], m.EventID, h.ItemTypes[h.ItemTypeEvent], c.Site.ID, ) } audit.Replace( c.Site.ID, h.ItemTypes[h.ItemTypeAttendee], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) } c.RespondWithOK() }
// DeleteMany handles DELETE // Removes one or more profiles (that were explicitly assigned) from this role func (ctl *RoleProfilesController) DeleteMany(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 } ems := []models.RoleProfileType{} err = c.Fill(&ems) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // 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 = models.DeleteManyRoleProfiles(roleID, ems) if err != nil { c.RespondWithErrorDetail(err, status) return } c.RespondWithOK() }
// Create handles POST func (ctl *CommentsController) Create(c *models.Context) { m := models.CommentSummaryType{} err := c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Populate where applicable from auth and context m.Meta.CreatedByID = c.Auth.ProfileID m.Meta.Created = time.Now() status, err := m.Validate(c.Site.ID, false) if err != nil { c.RespondWithErrorDetail(err, status) return } // Start : Authorisation perms := models.GetPermission( models.MakeAuthorisationContext( c, 0, m.ItemTypeID, m.ItemID), ) if !perms.CanCreate { c.RespondWithErrorDetail( e.New( c.Site.ID, c.Auth.ProfileID, "comments.go::Create", e.NoCreate, "Not authorized to create comment: CanCreate false", ), http.StatusForbidden, ) return } // End : Authorisation // Create status, err = m.Insert(c.Site.ID) if err != nil { c.RespondWithErrorDetail(err, status) return } go audit.Create( c.Site.ID, h.ItemTypes[h.ItemTypeComment], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) // Send updates and register watcher if m.ItemTypeID == h.ItemTypes[h.ItemTypeHuddle] { models.RegisterWatcher( c.Auth.ProfileID, h.UpdateTypes[h.UpdateTypeNewCommentInHuddle], m.ItemID, m.ItemTypeID, c.Site.ID, ) go models.SendUpdatesForNewCommentInHuddle(c.Site.ID, m) models.MarkAsRead(h.ItemTypes[h.ItemTypeHuddle], m.ItemID, c.Auth.ProfileID, time.Now()) models.UpdateUnreadHuddleCount(c.Auth.ProfileID) } else { models.RegisterWatcher( c.Auth.ProfileID, h.UpdateTypes[h.UpdateTypeNewComment], m.ItemID, m.ItemTypeID, c.Site.ID, ) go models.SendUpdatesForNewCommentInItem(c.Site.ID, m) } if m.InReplyTo > 0 { go models.SendUpdatesForNewReplyToYourComment(c.Site.ID, m) } // Respond c.RespondWithSeeOther( fmt.Sprintf( "%s/%d", h.APITypeComment, m.ID, ), ) }
// Update handles PUT func (ctl *RoleController) Update(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("microcosm_id in URL is not a number", http.StatusBadRequest) return } m, status, err := models.GetRole(c.Site.ID, microcosmID, roleID, 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 } // 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 } } // 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.ItemTypeRole], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithSeeOther(m.GetLink()) }
// 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() }
// Create handles POST // If microcosm_id is provided in request args then this is a role on a microcosm // otherwise this is a default role on this site func (ctl *RolesController) Create(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 } // Validate inputs m := models.RoleType{} 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, 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 } } // End : Authorisation // Populate where applicable from auth and context m.SiteID = c.Site.ID m.MicrocosmID = microcosmID 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.ItemTypeRole], m.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithSeeOther(m.GetLink()) }
// 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, ), ) }
// Create handles POST func (ctl *SitesController) Create(c *models.Context) { if c.Auth.ProfileID < 1 { c.RespondWithErrorMessage( fmt.Sprintf("You must be logged in to the root site create a site"), http.StatusForbidden, ) return } if c.Site.ID != 1 { c.RespondWithErrorMessage( fmt.Sprintf("Sites can only be created from the root site"), http.StatusBadRequest, ) return } bytes, _ := httputil.DumpRequest(c.Request, true) glog.Infoln(string(bytes)) m := models.SiteType{} // Default theme m.ThemeID = 1 err := c.Fill(&m) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("The post data is invalid: %v", err.Error()), http.StatusBadRequest, ) return } // Fetch full user info from context user ID user, status, err := models.GetUser(c.Auth.UserID) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Could not retrieve use associated with ID %d", c.Auth.UserID), status, ) return } site, _, status, err := models.CreateOwnedSite(m, user) if err != nil { c.RespondWithErrorMessage( fmt.Sprintf("Error creating site: %s", err.Error()), http.StatusInternalServerError, ) return } audit.Create( c.Site.ID, h.ItemTypes[h.ItemTypeSite], site.ID, c.Auth.ProfileID, time.Now(), c.IP, ) c.RespondWithSeeOther(fmt.Sprintf("%s/%d", h.APITypeSite, site.ID)) }