// POST /users/password/reset func HandlePasswordResetSend(context router.Context) error { // Find the user by email (if not found let them know) // Find the user by hex token in the db email := context.Param("email") user, err := users.First(users.Where("email=?", email)) if err != nil { return router.Redirect(context, "/users/password/reset?message=invalid_email") } // Generate a random token and url for the email token := auth.BytesToHex(auth.RandomToken()) // Generate the url to use in our email base := fmt.Sprintf("%s://%s", context.Request().URL.Scheme, context.Request().URL.Host) url := fmt.Sprintf("%s/users/password?token=%s", base, token) context.Logf("#info sending reset email:%s url:%s", email, url) // Update the user record with with this token p := map[string]string{"reset_token": token} user.Update(p) // Send a password reset email out //mail.Send("mymail") // Tell the user what we have done return router.Redirect(context, "/users/password/sent") }
// POST users/create func HandleCreate(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Setup context params, err := context.Params() if err != nil { return router.InternalError(err) } // We should check for duplicates in here id, err := users.Create(params.Map()) if err != nil { return router.InternalError(err, "Error", "Sorry, an error occurred creating the user record.") } else { context.Logf("#info Created user id,%d", id) } // Redirect to the new user p, err := users.Find(id) if err != nil { return router.InternalError(err, "Error", "Sorry, an error occurred finding the new user record.") } return router.Redirect(context, p.URLIndex()) }
// HandleCreate handles the POST of the create form for pages func HandleCreate(context router.Context) error { // Authorise err := authorise.ResourceAndAuthenticity(context, nil) if err != nil { return router.NotAuthorizedError(err) } // Setup context params, err := context.Params() if err != nil { return router.InternalError(err) } id, err := pages.Create(params.Map()) if err != nil { return router.InternalError(err) } // Log creation context.Logf("#info Created page id,%d", id) // Redirect to the new page m, err := pages.Find(id) if err != nil { return router.InternalError(err) } return router.Redirect(context, m.URLIndex()) }
// HandleUpdate handles POST or PUT /images/1/update func HandleUpdate(context router.Context) error { // Find the image image, err := images.Find(context.ParamInt("id")) if err != nil { context.Logf("#error Error finding image %s", err) return router.NotFoundError(err) } // Authorise err = authorise.Resource(context, image) if err != nil { return router.NotAuthorizedError(err) } // Update the image params, err := context.Params() if err != nil { return router.InternalError(err) } err = image.Update(params.Map()) if err != nil { return router.InternalError(err) } // We redirect back to source if redirect param is set return router.Redirect(context, image.URLUpdate()) }
// errHandler renders an error using error templates if available func errHandler(context router.Context, e error) { // Cast the error to a status error if it is one, if not wrap it in a Status 500 error err := router.ToStatusError(e) view := view.New(context) view.AddKey("title", err.Title) view.AddKey("message", err.Message) if !context.Production() { view.AddKey("status", err.Status) view.AddKey("file", err.FileLine()) view.AddKey("error", err.Err) } // Set the status correctly for errors context.Writer().WriteHeader(err.Status) // Use our error template view.Template("app/views/error.html.got") context.Logf("#error %s\n", err) view.Render() }
// errHandler renders an error using error templates if available func errHandler(context router.Context, e error) { // Cast the error to a status error if it is one, if not wrap it in a Status 500 error err := router.ToStatusError(e) view := view.New(context) view.AddKey("title", err.Title) view.AddKey("message", err.Message) if !context.Production() { view.AddKey("status", err.Status) view.AddKey("file", err.FileLine()) view.AddKey("error", err.Err) } view.Template("app/views/error.html.got") // Log 404 as info only if err.Status == 404 { context.Logf("#info %s\n", err) } else { context.Logf("#error %s\n", err) } view.Render() }
// HandleIndex serves a get request at /pages func HandleIndex(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Fetch the pages q := pages.Query().Order("url asc") // Filter if necessary filter := context.Param("filter") if len(filter) > 0 { filter = strings.Replace(filter, "&", "", -1) filter = strings.Replace(filter, " ", "", -1) filter = strings.Replace(filter, " ", " & ", -1) q.Where("(to_tsvector(name) || to_tsvector(summary) || to_tsvector(url) @@ to_tsquery(?) )", filter) } pageList, err := pages.FindAll(q) if err != nil { context.Logf("#error Error indexing pages %s", err) return router.InternalError(err) } // Serve template view := view.New(context) view.AddKey("filter", filter) view.AddKey("pages", pageList) return view.Render() }
// 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) } context.Logf("PARAMS RECD:%v", params) err = user.Update(params.Map()) if err != nil { return router.InternalError(err) } // Redirect to user return router.Redirect(context, user.URLShow()) }
// HandleShow serve a get request at /users/1 func HandleShow(context router.Context) error { // 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) } userMeta := fmt.Sprintf("%s – %s", user.Name, user.Summary) // Set up view view := view.New(context) // Find the first image which matches this user image, err := images.Find(user.ImageID) if err == nil { // only add image key if we have one view.AddKey("image", image) } // Render the Template view.AddKey("user", user) view.AddKey("meta_title", userMeta) view.AddKey("meta_desc", userMeta) view.AddKey("meta_keywords", user.Keywords()) return view.Render() }
// CreateAuthenticityToken returns an auth.AuthenticityToken and writes a secret to check it to the cookie func CreateAuthenticityToken(context router.Context) string { token, err := auth.AuthenticityToken(context.Writer(), context.Request()) if err != nil { context.Logf("#warn invalid authenticity token at %v", context) return "" // empty strings are invalid as tokens } return token }
// 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.Resource(context, user) if err != nil { return router.NotAuthorizedError(err) } // We expect only one image, what about replacing the existing when updating? // At present we just create a new image files, err := context.ParamFiles("image") if err != nil { return router.InternalError(err) } // Get the params params, err := context.Params() if err != nil { return router.InternalError(err) } var imageID int64 if len(files) > 0 { fileHandle := files[0] // Create an image (saving the image representation on disk) imageParams := map[string]string{"name": user.Name, "status": "100"} imageID, err = images.Create(imageParams, fileHandle) if err != nil { return router.InternalError(err) } params.Set("image_id", fmt.Sprintf("%d", imageID)) delete(params, "image") } err = user.Update(params.Map()) if err != nil { return router.InternalError(err) } // Redirect to user return router.Redirect(context, user.URLShow()) }
func loginUser(context router.Context, user *users.User) error { // Now save the user details in a secure cookie, so that we remember the next request session, err := auth.Session(context, context.Request()) if err != nil { return err } context.Logf("#info Login success for user: %d %s", user.Id, user.Email) session.Set(auth.SessionUserKey, fmt.Sprintf("%d", user.Id)) session.Save(context) return nil }
// AuthenticityToken checks the token in the current request func AuthenticityToken(context router.Context) error { token := context.Param(auth.SessionTokenKey) err := auth.CheckAuthenticityToken(token, context.Request()) if err != nil { // If the check fails, log out the user and completely clear the session context.Logf("#warn invalid authenticity token at %v", context) session, err := auth.SessionGet(context.Request()) if err != nil { return err } session.Clear(context.Writer()) } return err }
// HandleCreate handles the POST of the create form for users func HandleCreate(context router.Context) error { // Authorise err := authorise.Resource(context, nil) if err != nil { return router.NotAuthorizedError(err) } // Setup context params, err := context.Params() if err != nil { return router.InternalError(err) } // Default to customer role etc - admins will have to promote afterwards params.Set("role", fmt.Sprintf("%d", users.RoleCustomer)) params.Set("status", fmt.Sprintf("%d", status.Published)) id, err := users.Create(params.Map()) if err != nil { return err } // Log creation context.Logf("#info Created user id,%d", id) // Redirect to the new user user, err := users.Find(id) if err != nil { return router.InternalError(err) } // Save the details in a secure cookie session, err := auth.Session(context, context.Request()) if err != nil { return router.InternalError(err) } context.Logf("#info CREATE for user: %d", user.Id) session.Set(auth.SessionUserKey, fmt.Sprintf("%d", user.Id)) session.Save(context) // Send them to their user profile page return router.Redirect(context, user.URLShow()) }
// HandleUpdateShow handles GET /pages/1/update (show form to update) func HandleUpdateShow(context router.Context) error { // Find the page page, err := pages.Find(context.ParamInt("id")) if err != nil { context.Logf("#error Error finding page %s", err) return router.NotFoundError(err) } // Authorise updating page err = authorise.Resource(context, page) if err != nil { return router.NotAuthorizedError(err) } // Render the template view := view.New(context) view.AddKey("page", page) return view.Render() }
// 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() }
// HandleUpdateShow serves a get request at /images/1/update (show form to update) func HandleUpdateShow(context router.Context) error { // Setup context for template view := view.New(context) image, err := images.Find(context.ParamInt("id")) if err != nil { context.Logf("#error Error finding image %s", err) return router.NotFoundError(err) } // Authorise err = authorise.Resource(context, image) if err != nil { return router.NotAuthorizedError(err) } view.AddKey("redirect", context.Param("redirect")) view.AddKey("image", image) return view.Render() }
func renderPage(context router.Context, page *pages.Page) error { view := view.New(context) // Setup context for template if page.Template != "" { view.Template(page.Template) } else { view.Template("pages/views/show.html.got") } view.AddKey("page", page) view.AddKey("meta_title", page.Name) view.AddKey("meta_desc", page.Summary) view.AddKey("meta_keywords", page.Keywords) // Serve template context.Logf("#info Rendering page for path %s", context.Path()) return view.Render() }
// HandleLogin handles a post to /users/login func HandleLogin(context router.Context) error { // Check we're not already logged in, if so redirect // Get the user details from the database params, err := context.Params() if err != nil { return router.NotFoundError(err) } // Find the user with this email q := users.Where("email=?", params.Get("email")) user, err := users.First(q) if err != nil { q = users.Where("name=?", params.Get("email")) // NB use of email field user, err = users.First(q) } if err != nil { context.Logf("#error Login failed for user no such user : %s %s", params.Get("email"), err) return router.Redirect(context, "/users/login?error=failed_email") } err = auth.CheckPassword(params.Get("password"), user.EncryptedPassword) if err != nil { context.Logf("#error Login failed for user : %s %s", params.Get("email"), err) return router.Redirect(context, "/users/login?error=failed_password") } // Save the fact user is logged in to session cookie err = loginUser(context, user) if err != nil { return router.InternalError(err) } // Redirect to whatever page the user tried to visit before (if any) // For now send them to root return router.Redirect(context, "/") }
// 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) } // Set up view view := view.New(context) // Render the Template view.AddKey("user", user) view.AddKey("meta_title", user.Name) view.AddKey("meta_desc", user.Name) return view.Render() }
// 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) // view.AddKey("admin_links", helpers.Link("Destroy User", url.Destroy(user), "method=post")) return view.Render() }
// POST pages/create func HandleCreate(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Setup context params, err := context.Params() if err != nil { return router.InternalError(err) } id, err := pages.Create(params.Map()) if err != nil { context.Logf("#info Failed to create page %v", params) return router.InternalError(err) } // Log creation context.Logf("#info Created page id,%d", id) // Redirect to the new page p, err := pages.Find(id) if err != nil { context.Logf("#error Error creating page,%s", err) } return router.Redirect(context, p.URLIndex()) }
// HandleIndex displays a list of stories at /stories func HandleIndex(context router.Context) error { // Build a query q := stories.Query().Limit(listLimit) // Order by date by default q.Where("points > -6").Order("created_at desc") // Filter if necessary - this assumes name and summary cols filter := context.Param("filter") if len(filter) > 0 { context.Logf("FILTER %s", filter) // Replace special characters with escaped sequence filter = strings.Replace(filter, "_", "\\_", -1) filter = strings.Replace(filter, "%", "\\%", -1) // initially very simple, do ilike query for filter with wildcards q.Where("stories.name ILIKE ?", "%"+filter+"%") // If filtering, order by rank, not by date q.Order("rank desc, points desc, id desc") } // Fetch the stories results, err := stories.FindAll(q) if err != nil { return router.InternalError(err) } // Render the template view := view.New(context) view.AddKey("filter", filter) view.AddKey("stories", results) view.AddKey("meta_title", "Go Hacker News Links") view.AddKey("authenticity_token", authorise.CreateAuthenticityToken(context)) return view.Render() }
// HandleIndex serves a GET request at /users func HandleIndex(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Fetch the users q := users.Query().Order("role desc, created_at desc") userList, err := users.FindAll(q) if err != nil { context.Logf("#error Error indexing users %s", err) return router.InternalError(err) } // Serve template view := view.New(context) view.AddKey("users", userList) return view.Render() }
// HandleBlog displays a list of posts in reverse chronological order func HandleBlog(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Build a query q := posts.Published().Order("created_at desc") // Filter if necessary - this assumes name and summary cols filter := context.Param("filter") if len(filter) > 0 { filter = strings.Replace(filter, "&", "", -1) filter = strings.Replace(filter, " ", "", -1) filter = strings.Replace(filter, " ", " & ", -1) q.Where("( to_tsvector(name) || to_tsvector(summary) @@ to_tsquery(?) )", filter) } // Fetch the posts results, err := posts.FindAll(q) if err != nil { return router.InternalError(err) } context.Logf("POSTS HERE :%v", results) // Render the template view := view.New(context) view.AddKey("filter", filter) view.AddKey("posts", results) view.Template("posts/views/blog.html.got") return view.Render() }
// 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()) }
// 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() }
// HandleLogin handles a post to /users/login func HandleLogin(context router.Context) error { // Check we're not already logged in, if so redirect // Get the user details from the database params, err := context.Params() if err != nil { return router.NotFoundError(err) } // Need something neater than this - how best to do it? q := users.Where("email=?", params.Get("email")) user, err := users.First(q) if err != nil { context.Logf("#error Login failed for user no such user : %s %s", params.Get("email"), err) return router.Redirect(context, "/users/login?error=failed_email") } err = auth.CheckPassword(params.Get("password"), user.EncryptedPassword) if err != nil { context.Logf("#error Login failed for user : %s %s", params.Get("email"), err) return router.Redirect(context, "/users/login?error=failed_password") } // Now save the user details in a secure cookie, so that we remember the next request session, err := auth.Session(context, context.Request()) if err != nil { context.Logf("#error problem retrieving session") } context.Logf("#info Login success for user: %d %s", user.Id, user.Email) session.Set(auth.SessionUserKey, fmt.Sprintf("%d", user.Id)) session.Save(context) // Redirect to whatever page the user tried to visit before (if any) // For now send them to root return router.Redirect(context, "/") }
// HandleCreate responds to POST images/create func HandleCreate(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // We expect only one image, what about replacing the existing when updating? // At present we just create a new image files, err := context.ParamFiles("image") if err != nil { return router.InternalError(err) } if len(files) == 0 { return router.NotFoundError(nil) } // Get the params params, err := context.Params() if err != nil { return router.InternalError(err) } id, err := images.Create(params.Map(), files[0]) if err != nil { context.Logf("#error Error creating image,%s", err) return router.InternalError(err) } // Log creation context.Logf("#info Created image id,%d", id) // Redirect to the new image m, err := images.Find(id) if err != nil { context.Logf("#error Error creating image,%s", err) } return router.Redirect(context, m.URLShow()) }
// HandleCreate responds to POST tags/create func HandleCreate(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Setup context params, err := context.Params() if err != nil { return router.InternalError(err) } id, err := tags.Create(params.Map()) if err != nil { context.Logf("#info Failed to create tag %v", params) return router.InternalError(err) } // Log creation context.Logf("#info Created tag id,%d", id) // Redirect to the new tag tag, err := tags.Find(id) if err != nil { context.Logf("#error Error creating tag,%s", err) } // Always regenerate dotted ids - we fetch all tags first to avoid db calls q := tags.Query().Select("select id,parent_id from tags").Order("id asc") tagsList, err := tags.FindAll(q) if err == nil { dottedParams := map[string]string{} dottedParams["dotted_ids"] = tag.CalculateDottedIds(tagsList) tags.Query().Where("id=?", tag.Id).Update(dottedParams) } return router.Redirect(context, tag.URLIndex()) }