예제 #1
0
// 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,
		),
	)
}
예제 #2
0
// 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,
		),
	)
}
예제 #3
0
// 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,
		),
	)
}
예제 #4
0
// 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)
}
예제 #5
0
// 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)
}
예제 #6
0
// 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())
}
예제 #7
0
// 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,
		),
	)
}
예제 #8
0
// 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))
}