コード例 #1
0
ファイル: mail.go プロジェクト: gnoirzox/gohackernews
// DailyEmail sends a daily email to subscribed users with top stories - change this to WeeklyEmail
// before putting it into production
// We should probably only do this for kenny at present
func DailyEmail(context schedule.Context) {
	context.Log("Sending daily email")

	// First fetch our stories over 5 points
	q := stories.Popular()

	// Must be within 7 days
	q.Where("created_at > current_timestamp - interval '7 day'")

	// Order by rank
	q.Order("rank desc, points desc, id desc")

	// Don't fetch stories that have already been mailed
	q.Where("newsletter_at IS NULL")

	// Fetch the stories
	topStories, err := stories.FindAll(q)
	if err != nil {
		context.Logf("#error getting top story tweet %s", err)
		return
	}

	if len(topStories) == 0 {
		context.Logf("#warn no stories found for newsletter")
		return
	}

	// Now fetch our recipient (initially just Kenny as this is in testing)
	recipient, err := users.Find(1)
	if err != nil {
		context.Logf("#error getting email reciipents %s", err)
		return
	}

	var jobStories []*stories.Story

	// Email recipients the stories in question - we should perhaps save in db so that we can
	// have an issue number and always reproduce the digests?
	mailContext := map[string]interface{}{
		"stories": topStories,
		"jobs":    jobStories,
	}
	err = mail.SendOne(recipient.Email, "Go News Digest", "users/views/mail/digest.html.got", mailContext)
	if err != nil {
		context.Logf("#error sending email %s", err)
		return
	}

	// Record that these stories have been mailed in db
	params := map[string]string{"newsletter_at": query.TimeString(time.Now().UTC())}
	err = q.Order("").UpdateAll(params)
	if err != nil {
		context.Logf("#error updating top story newsletter_at %s", err)
		return
	}

}
コード例 #2
0
ファイル: update.go プロジェクト: gnoirzox/gohackernews
// HandleUpdateShow serves a get request at /users/1/update (show form to update)
func HandleUpdateShow(context router.Context) error {
	// Setup context for template
	view := view.New(context)

	user, err := users.Find(context.ParamInt("id"))
	if err != nil {
		context.Logf("#error Error finding user %s", err)
		return router.NotFoundError(err)
	}

	// Authorise
	err = authorise.Resource(context, user)
	if err != nil {
		return router.NotAuthorizedError(err)
	}

	view.AddKey("user", user)

	return view.Render()
}
コード例 #3
0
ファイル: destroy.go プロジェクト: gnoirzox/gohackernews
// HandleDestroy responds to POST /users/1/destroy
func HandleDestroy(context router.Context) error {

	// Set the user on the context for checking
	user, err := users.Find(context.ParamInt("id"))
	if err != nil {
		return router.NotFoundError(err)
	}

	// Authorise
	err = authorise.ResourceAndAuthenticity(context, user)
	if err != nil {
		return router.NotAuthorizedError(err)
	}

	// Destroy the user
	user.Destroy()

	// Redirect to users root
	return router.Redirect(context, user.URLIndex())
}
コード例 #4
0
ファイル: authenticate.go プロジェクト: gnoirzox/gohackernews
// CurrentUser returns the saved user (or an empty anon user) for the current session cookie
// Strictly speaking this should be authenticate.User
func CurrentUser(context router.Context) *users.User {

	// First check if the user has already been set on context, if so return it
	if context.Get("current_user") != nil {
		return context.Get("current_user").(*users.User)
	}

	// Start with an anon user by default (role 0, id 0)
	user := &users.User{}

	// Build the session from the secure cookie, or create a new one
	session, err := auth.Session(context.Writer(), context.Request())
	if err != nil {
		context.Logf("#error problem retrieving session")
		return user
	}

	// Fetch the current user record if we have one recorded in the session
	var id int64
	ids := session.Get(auth.SessionUserKey)
	if len(ids) > 0 {
		id, err = strconv.ParseInt(ids, 10, 64)
		if err != nil {
			context.Logf("#error Error decoding session user key:%s\n", err)
			return user
		}
	}

	if id != 0 {
		u, err := users.Find(id)
		if err != nil {
			context.Logf("#info User not found from session id:%d\n", id)
			return user
		}
		user = u
	}

	return user
}
コード例 #5
0
ファイル: votes.go プロジェクト: gnoirzox/gohackernews
// addStoryVote adjusts the story points, and adds a vote record for this user
func addStoryVote(story *stories.Story, user *users.User, ip string, delta int64) error {

	if story.Points < -5 && delta < 0 {
		return router.InternalError(nil, "Vote Failed", "Story is already hidden")
	}

	// Update the story points by delta
	err := story.Update(map[string]string{"points": fmt.Sprintf("%d", story.Points+delta)})
	if err != nil {
		return router.InternalError(err, "Vote Failed", "Sorry your adjust vote points")
	}

	// Update the *story* posting user points by delta
	storyUser, err := users.Find(story.UserId)
	if err != nil {
		return err
	}
	err = adjustUserPoints(storyUser, delta)
	if err != nil {
		return err
	}

	return recordStoryVote(story, user, ip, delta)
}
コード例 #6
0
ファイル: show.go プロジェクト: gnoirzox/gohackernews
// HandleShow serve a get request at /users/1
func HandleShow(context router.Context) error {

	// No auth - this is public

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

	// Get the user comments
	q := comments.Where("user_id=?", user.Id).Limit(10).Order("created_at desc")
	userComments, err := comments.FindAll(q)
	if err != nil {
		return router.InternalError(err)
	}

	// Get the user stories
	q = stories.Where("user_id=?", user.Id).Limit(50).Order("created_at desc")
	userStories, err := stories.FindAll(q)
	if err != nil {
		return router.InternalError(err)
	}

	// Render the Template
	view := view.New(context)
	view.AddKey("user", user)
	view.AddKey("comments", userComments)
	view.AddKey("stories", userStories)
	view.AddKey("meta_title", user.Name)
	view.AddKey("meta_desc", user.Name)

	return view.Render()

}
コード例 #7
0
ファイル: update.go プロジェクト: gnoirzox/gohackernews
// HandleUpdate or PUT /users/1/update
func HandleUpdate(context router.Context) error {

	// Find the user
	id := context.ParamInt("id")
	user, err := users.Find(id)
	if err != nil {
		context.Logf("#error Error finding user %s", err)
		return router.NotFoundError(err)
	}

	// Authorise
	err = authorise.ResourceAndAuthenticity(context, user)
	if err != nil {
		return router.NotAuthorizedError(err)
	}

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

	// Clean params according to role
	accepted := users.AllowedParams()
	if authorise.CurrentUser(context).Admin() {
		accepted = users.AllowedParamsAdmin()
	}
	allowedParams := params.Clean(accepted)
	err = user.Update(allowedParams)
	if err != nil {
		return router.InternalError(err)
	}

	// Redirect to user
	return router.Redirect(context, user.URLShow())
}
コード例 #8
0
ファイル: votes.go プロジェクト: gnoirzox/gohackernews
// addCommentVote adjusts the comment points, and adds a vote record for this user
func addCommentVote(comment *comments.Comment, user *users.User, ip string, delta int64) error {

	if comment.Points < -5 && delta < 0 {
		return router.InternalError(nil, "Vote Failed", "Comment is already hidden")
	}

	// Update the comment points by delta
	err := comment.Update(map[string]string{"points": fmt.Sprintf("%d", comment.Points+delta)})
	if err != nil {
		return router.InternalError(err, "Vote Failed", "Sorry your adjust vote points")
	}

	// Update the *comment* user points by delta
	commentUser, err := users.Find(comment.UserId)
	if err != nil {
		return err
	}
	err = adjustUserPoints(commentUser, delta)
	if err != nil {
		return err
	}

	return recordCommentVote(comment, user, ip, delta)
}
コード例 #9
0
ファイル: create.go プロジェクト: gnoirzox/gohackernews
// 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")
}