예제 #1
0
// HandleDownvote handles POST to /stories/123/downvote
func HandleDownvote(context router.Context) error {

	// Prevent CSRF
	err := authorise.AuthenticityToken(context)
	if err != nil {
		return router.NotAuthorizedError(err, "Vote Failed", "CSRF failure")
	}

	// Find the story
	story, err := stories.Find(context.ParamInt("id"))
	if err != nil {
		return router.NotFoundError(err)
	}
	user := authorise.CurrentUser(context)
	ip := getUserIP(context)

	if !user.Admin() {
		// Check we have no votes already from this user, if we do fail
		if storyHasUserVote(story, user) {
			return router.NotAuthorizedError(err, "Vote Failed", "Sorry you are not allowed to vote twice, nice try!")
		}
	}

	// Authorise upvote on story for this user - our rules are:
	if !user.CanDownvote() {
		return router.NotAuthorizedError(err, "Vote Failed", "Sorry, you can't downvote yet")
	}

	err = authorise.Resource(context, story)
	if err != nil {
		return router.NotAuthorizedError(err, "Vote Failed", "Sorry you are not allowed to vote")
	}

	err = adjustUserPoints(user, -1)
	if err != nil {
		return err
	}

	// Adjust points on story and add to the vote table
	err = addStoryVote(story, user, ip, -1)
	if err != nil {
		return err
	}

	return updateStoriesRank()
}
예제 #2
0
// HandleFlag handles POST to /stories/123/flag
func HandleFlag(context router.Context) error {

	// Protect against CSRF
	err := authorise.AuthenticityToken(context)
	if err != nil {
		return router.NotAuthorizedError(err, "Flag Failed", "CSRF failure")
	}

	// Find the story
	story, err := stories.Find(context.ParamInt("id"))
	if err != nil {
		return router.NotFoundError(err)
	}
	user := authorise.CurrentUser(context)
	ip := getUserIP(context)

	// Check we have no votes already from this user, if we do fail
	if storyHasUserFlag(story, user) {
		return router.NotAuthorizedError(err, "Flag Failed", "Sorry you are not allowed to flag twice, nice try!")
	}

	// Authorise upvote on story for this user
	if !user.CanFlag() {
		return router.NotAuthorizedError(err, "Flag Failed", "Sorry, you can't flag yet")
	}

	err = authorise.Resource(context, story)
	if err != nil {
		return router.NotAuthorizedError(err, "Flag Failed", "Sorry you are not allowed to flag")
	}

	err = adjustUserPoints(user, -1)
	if err != nil {
		return err
	}

	err = addStoryVote(story, user, ip, -5)
	if err != nil {
		return err
	}
	return updateStoriesRank()
}
예제 #3
0
// HandleDownvote handles POST to /comments/123/downvote
func HandleDownvote(context router.Context) error {

	// Prevent CSRF
	err := authorise.AuthenticityToken(context)
	if err != nil {
		return router.NotAuthorizedError(err, "Vote Failed", "CSRF failure")
	}

	// Find the comment
	comment, err := comments.Find(context.ParamInt("id"))
	if err != nil {
		return router.NotFoundError(err)
	}
	user := authorise.CurrentUser(context)
	ip := getUserIP(context)

	if !user.Admin() {
		// Check we have no votes already from this user, if we do fail
		if commentHasUserVote(comment, user) {
			return router.NotAuthorizedError(err, "Vote Failed", "Sorry you are not allowed to vote twice, nice try!")
		}
	}

	// Authorise upvote on comment for this user - our rules are:
	if !user.CanDownvote() {
		return router.NotAuthorizedError(err, "Vote Failed", "Sorry, you can't downvote yet")
	}

	// CURRENT User burns points for downvoting
	err = adjustUserPoints(user, -1)
	if err != nil {
		return err
	}

	// Adjust points on comment and add to the vote table
	err = addCommentVote(comment, user, ip, -1)
	if err != nil {
		return err
	}

	return updateCommentsRank(comment.StoryId)
}
예제 #4
0
// HandleCreate handles the POST of the create form for comments
func HandleCreate(context router.Context) error {

	// Authorise csrf token
	err := authorise.AuthenticityToken(context)
	if err != nil {
		return router.NotAuthorizedError(err)
	}

	// Check permissions - if not logged in and above 0 points, redirect
	if !authorise.CurrentUser(context).CanComment() {
		return router.NotAuthorizedError(nil, "Sorry", "You need to be registered and have more than 0 points to comment.")
	}

	// Setup context
	params, err := context.Params()
	if err != nil {
		return router.InternalError(err)
	}

	// Find parent story - this must exist
	story, err := stories.Find(params.GetInt("story_id"))
	if err != nil {
		return router.NotFoundError(err)
	}

	params.SetInt("story_id", story.Id)
	params.Set("story_name", story.Name)

	// Set a few params
	user := authorise.CurrentUser(context)
	params.SetInt("user_id", user.Id)
	params.Set("user_name", user.Name)
	params.SetInt("points", 1)

	// Find the parent and set dotted id
	// these are of the form xx.xx. with a trailing dot
	// this saves us from saving twice on create
	parentID := context.ParamInt("parent_id")
	if parentID > 0 {
		parent, err := comments.Find(parentID)
		if err != nil {
			return router.NotFoundError(err)
		}
		context.Logf("PARENT:%d - %s", parent.Id, parent.DottedIds)
		params.Set("dotted_ids", fmt.Sprintf(parent.DottedIds+"."))
	}

	// Clean params allowing all through (since we have manually reset them above)
	accepted := comments.AllowedParamsAdmin()
	cleanedParams := params.Clean(accepted)
	id, err := comments.Create(cleanedParams)
	if err != nil {
		return router.InternalError(err)
	}

	// Log creation
	context.Logf("#info Created comment id,%d", id)

	// Update the story comment count
	storyParams := map[string]string{"comment_count": fmt.Sprintf("%d", story.CommentCount+1)}
	err = story.Update(storyParams)
	if err != nil {
		return router.InternalError(err, "Error", "Could not update story.")
	}

	// Redirect to the new comment
	m, err := comments.Find(id)
	if err != nil {
		return router.InternalError(err)
	}

	// Re-rank comments on this story
	err = updateCommentsRank(m.StoryId)
	if err != nil {
		return err
	}

	return router.Redirect(context, m.URLStory())
}
예제 #5
0
// HandleCreate handles the POST of the create form for stories
func HandleCreate(context router.Context) error {

	// Check csrf token
	err := authorise.AuthenticityToken(context)
	if err != nil {
		return router.NotAuthorizedError(err)
	}

	// Check permissions - if not logged in and above 1 points, redirect to error
	if !authorise.CurrentUser(context).CanSubmit() {
		return router.NotAuthorizedError(nil, "Sorry", "You need to be registered and have more than 1 points to submit stories.")
	}

	// Get params
	params, err := context.Params()
	if err != nil {
		return router.InternalError(err)
	}

	// Get user details
	user := authorise.CurrentUser(context)
	ip := getUserIP(context)

	// Process urls
	url := params.Get("url")

	// Strip trailing slashes on url before comparisons
	if strings.HasSuffix(url, "/") {
		url = strings.Trim(url, "/")
	}

	// Strip ?utm_source etc - remove all after ?utm_source
	if strings.Contains(url, "?utm_") {
		url = strings.Split(url, "?utm_")[0]
	}

	// Strip url fragments (For example trailing # on medium urls)
	if strings.Contains(url, "#") {
		url = strings.Split(url, "#")[0]
	}

	// Rewrite mobile youtube links
	if strings.HasPrefix(url, "https://m.youtube.com") {
		url = strings.Replace(url, "https://m.youtube.com", "https://www.youtube.com", 1)
	}

	params.Set("url", url)

	// Check that no story with this url already exists
	q := stories.Where("url=?", url)
	duplicates, err := stories.FindAll(q)
	if err != nil {
		return router.InternalError(err)
	}

	if len(duplicates) > 0 {
		story := duplicates[0]

		// Check we have no votes already from this user, if we do fail
		if storyHasUserVote(story, user) {
			return router.NotAuthorizedError(err, "Vote Failed", "Sorry you are not allowed to vote twice, nice try!")

		}

		// Add a point to dupe and return
		addStoryVote(story, user, ip, 1)
		return router.Redirect(context, story.URLShow())
	}
	// Clean params according to role
	accepted := stories.AllowedParams()
	if authorise.CurrentUser(context).Admin() {
		accepted = stories.AllowedParamsAdmin()
	}
	cleanedParams := params.Clean(accepted)

	// Set a few params
	cleanedParams["points"] = "1"
	cleanedParams["user_id"] = fmt.Sprintf("%d", user.Id)
	cleanedParams["user_name"] = user.Name

	id, err := stories.Create(cleanedParams)
	if err != nil {
		return err // Create returns a router.Error
	}

	// Log creation
	context.Logf("#info Created story id,%d", id)

	// Redirect to the new story
	story, err := stories.Find(id)
	if err != nil {
		return router.InternalError(err)
	}

	// We need to add a vote to the story here too by adding a join to the new id
	err = recordStoryVote(story, user, ip, +1)
	if err != nil {
		return err
	}

	// Re-rank stories
	err = updateStoriesRank()
	if err != nil {
		return err
	}

	return router.Redirect(context, story.URLIndex())
}
예제 #6
0
// HandleCreate handles POST /users/create from the register page
func HandleCreate(context router.Context) error {

	// Check csrf token
	err := authorise.AuthenticityToken(context)
	if err != nil {
		return router.NotAuthorizedError(err)
	}

	// Setup context
	params, err := context.Params()
	if err != nil {
		return router.InternalError(err)
	}

	// Check for email duplicates
	email := params.Get("email")
	if len(email) > 0 {

		if len(email) < 3 || !strings.Contains(email, "@") {
			return router.InternalError(err, "Invalid email", "Please just miss out the email field, or use a valid email.")
		}

		count, err := users.Query().Where("email=?", email).Count()
		if err != nil {
			return router.InternalError(err)
		}
		if count > 0 {
			return router.NotAuthorizedError(err, "User already exists", "Sorry, a user already exists with that email.")
		}
	}

	// Check for invalid or duplicate names
	name := params.Get("name")
	if len(name) < 2 {
		return router.InternalError(err, "Name too short", "Please choose a username longer than 2 characters")
	}

	count, err := users.Query().Where("name=?", name).Count()
	if err != nil {
		return router.InternalError(err)
	}
	if count > 0 {
		return router.NotAuthorizedError(err, "User already exists", "Sorry, a user already exists with that name, please choose another.")
	}

	// Set some defaults for the new user
	params.SetInt("status", status.Published)
	params.SetInt("role", users.RoleReader)
	params.SetInt("points", 1)

	// Now try to create the user - NB AllowedParamsAdmin, we allow points etc on create as we explicitly set them
	id, err := users.Create(params.Clean(users.AllowedParamsAdmin()))
	if err != nil {
		return router.InternalError(err, "Error", "Sorry, an error occurred creating the user record.")
	}

	context.Logf("#info Created user id,%d", id)

	// Find the user again so we can save login
	user, err := users.Find(id)
	if err != nil {
		context.Logf("#error parsing user id: %s", err)
		return router.NotFoundError(err)
	}

	// Save the fact user is logged in to session cookie
	err = loginUser(context, user)
	if err != nil {
		return router.InternalError(err)
	}

	// Redirect to root
	return router.Redirect(context, "/?message=welcome")
}