// Returns a generic OAuth 2.0 backend endpoint. func NewOAuth2Provider(config *Config, authUrl, tokenUrl string) negroni.HandlerFunc { c := &oauth2.Config{ ClientID: config.ClientID, ClientSecret: config.ClientSecret, Scopes: config.Scopes, RedirectURL: config.RedirectURL, Endpoint: oauth2.Endpoint{ AuthURL: authUrl, TokenURL: tokenUrl, }, } maskedValues = make(map[string][]byte) return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { s := sessions.GetSession(r) if r.Method == "GET" { switch r.URL.Path { case PathLogin: login(c, s, w, r) case PathLogout: logout(s, w, r) case PathCallback: handleOAuth2Callback(c, s, w, r) default: next(w, r) } } else { next(w, r) } } }
// Edit show the edition form for articles. func Edit(w http.ResponseWriter, r *http.Request, p httprouter.Params) { // Ensure the user is logged if sessions.GetSession(r).Get("logged") != true { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } var article Article // Get the article from the database. err := database.Get(&article, "SELECT * FROM articles WHERE slug = ?", p.ByName("slug")) if err != nil && err != sql.ErrNoRows { panic(err) } if err == sql.ErrNoRows { http.Error(w, "Page not found", http.StatusNotFound) return } render(w, r, "article_edit", map[string]interface{}{ "Title": "Edit " + article.Title, "Article": article, }) }
// Returns a generic OAuth 2.0 backend endpoint. func NewOAuth2Provider(opts *Options, authUrl, tokenUrl string) negroni.HandlerFunc { config := &oauth2.Config{ ClientID: opts.ClientID, ClientSecret: opts.ClientSecret, Scopes: opts.Scopes, RedirectURL: opts.RedirectURL, Endpoint: oauth2.Endpoint{ AuthURL: authUrl, TokenURL: tokenUrl, }, } return func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { s := sessions.GetSession(r) if r.Method == "GET" { switch r.URL.Path { case PathLogin: login(opts, config, s, rw, r) case PathLogout: logout(s, rw, r) case PathCallback: handleOAuth2Callback(opts, config, s, rw, r) default: next(rw, r) } } else { next(rw, r) } } }
// View handle the displaying of articles. func View(w http.ResponseWriter, r *http.Request, p httprouter.Params) { var article Article err := database.Get(&article, "SELECT * FROM articles WHERE slug = ?", p.ByName("slug")) if err != nil && err != sql.ErrNoRows { panic(err) } if err == sql.ErrNoRows { http.Error(w, "Page not found", http.StatusNotFound) return } // Reject the request if the user isn't logged and that the article isn't published. if sessions.GetSession(r).Get("logged") != true && !article.IsPublished { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } render(w, r, "article", map[string]interface{}{ "Title": article.Title, "Article": article, }) }
// Update do the actual modification of the article in the database. func Update(w http.ResponseWriter, r *http.Request, p httprouter.Params) { // Ensure the user is logged. if sessions.GetSession(r).Get("logged") != true { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } var article Article err := database.Get(&article, "SELECT * FROM articles WHERE slug = ?", p.ByName("slug")) if err != nil && err != sql.ErrNoRows { panic(err) } if err == sql.ErrNoRows { http.Error(w, "Page not found", http.StatusNotFound) return } // Validate the request's form data for the article. var v = NewValidator(r) v.NotEmpty("title") v.MaxLen("title", 150) v.NotEmpty("slug") v.MaxLen("slug", 150) v.DoesntExists("slug", "articles", "slug", article.Slug) v.NotEmpty("tagline") v.MaxLen("tagline", 450) v.NotEmpty("text") // In case of error, forward them to the next request. if v.HasErrors() { sessions.GetSession(r).AddFlash(v.Errors(), "_errors") sessions.GetSession(r).AddFlash(r.Form, "_inputs") http.Redirect(w, r, "/article/"+article.Slug+"/edit", http.StatusFound) return } // If everything is fine, update the article in the database. _, err = database.Exec("UPDATE articles SET title = ?, slug = ?, tagline = ?, text = ?, tags = ?, updated_at = datetime('now') WHERE id = ?", r.FormValue("title"), r.FormValue("slug"), r.FormValue("tagline"), r.FormValue("text"), r.FormValue("tags"), article.ID) if err != nil { panic(err) } http.Redirect(w, r, "/article/"+r.FormValue("slug"), http.StatusFound) }
func GetToken(r *http.Request) Tokens { s := sessions.GetSession(r) t := unmarshallToken(s) //not doing this doesn't pass through the //nil return, causing a test to fail - not sure why?? if t == nil { return nil } else { return t } }
// render write the given template on a response writer. func render(w http.ResponseWriter, r *http.Request, name string, data map[string]interface{}) { data["Logged"] = sessions.GetSession(r).Get("logged") data["Configuration"] = configuration var rawErrors = sessions.GetSession(r).Flashes("_errors") if len(rawErrors) != 0 { data["Errors"] = rawErrors[0].([]string) } var rawInputs = sessions.GetSession(r).Flashes("_inputs") if len(rawInputs) != 0 { data["Inputs"] = rawInputs[0].(*url.Values) } out, err := templates.Render(name, data) if err != nil { http.Error(w, "error while generating the page:"+err.Error(), http.StatusInternalServerError) } w.Write([]byte(out)) }
// Write display the form for writing articles. func Write(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { // Ensure the user is logged. if sessions.GetSession(r).Get("logged") != true { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } render(w, r, "article_form", map[string]interface{}{ "Title": "Write", }) }
func SetToken(r *http.Request, t interface{}) { s := sessions.GetSession(r) val, _ := json.Marshal(t) s.Set(keyToken, val) //Check immediately to see if the token is expired tk := unmarshallToken(s) if tk != nil { // check if the access token is expired if !tk.Valid() && tk.Refresh() == "" { s.Delete(keyToken) tk = nil } } }
// Authenticate check the user credentials. func Authenticate(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { if subtle.ConstantTimeEq(int32(len(r.FormValue("password"))), int32(len(configuration.Password))) == 0 { http.Redirect(w, r, "/login", http.StatusFound) return } if subtle.ConstantTimeCompare([]byte(r.FormValue("password")), []byte(configuration.Password)) == 0 { http.Redirect(w, r, "/login", http.StatusFound) return } sessions.GetSession(r).Set("logged", true) http.Redirect(w, r, "/read", http.StatusFound) }
// Create validate and add new articles in the database. func Create(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { // Ensure the user is logged. if sessions.GetSession(r).Get("logged") != true { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } // Validate the request form data. var v = NewValidator(r) v.NotEmpty("title") v.MaxLen("title", 150) v.NotEmpty("slug") v.MaxLen("slug", 150) v.DoesntExists("slug", "articles", "slug") v.NotEmpty("tagline") v.MaxLen("tagline", 450) v.NotEmpty("text") // In case of error, return the user to the previous page with a listing of // the errors and inputs. if v.HasErrors() { sessions.GetSession(r).AddFlash(v.Errors(), "_errors") sessions.GetSession(r).AddFlash(r.Form, "_inputs") http.Redirect(w, r, "/write", http.StatusFound) return } // Insert the new article in the database. _, err := database.Exec("INSERT INTO articles (title, slug, tagline, text, tags, is_published, created_at, updated_at, published_at) VALUES (?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'), datetime('now'))", r.FormValue("title"), r.FormValue("slug"), r.FormValue("tagline"), r.FormValue("text"), r.FormValue("tags"), false) if err != nil { panic(err) } http.Redirect(w, r, "/article/"+r.FormValue("slug"), http.StatusFound) }
// Delete remove articles. func Delete(w http.ResponseWriter, r *http.Request, p httprouter.Params) { // Ensure the user is logged. if sessions.GetSession(r).Get("logged") != true { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } // Remote the article from the database. _, err := database.Exec("DELETE FROM articles WHERE slug = ?", p.ByName("slug")) if err != nil { panic(err) } http.Redirect(w, r, "/read", http.StatusFound) }
// Unpublish switch off visibility of an article. func Unpublish(w http.ResponseWriter, r *http.Request, p httprouter.Params) { // Ensure the user is logged. if sessions.GetSession(r).Get("logged") != true { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } // Switch the flag off. _, err := database.Exec("UPDATE articles SET is_published = ? WHERE slug = ?", false, p.ByName("slug")) if err != nil { panic(err) } http.Redirect(w, r, r.Referer(), http.StatusFound) }
// List show all articles available to the user. func List(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { var articles []*Article // If the user isn't logged, only show published articles and order them by publication date. // If the user is logged, show all articles and order them by creation date. var err error if sessions.GetSession(r).Get("logged") != true { err = database.Select(&articles, "SELECT * FROM articles WHERE is_published = ? ORDER BY published_at DESC", true) } else { err = database.Select(&articles, "SELECT * FROM articles ORDER BY published_at DESC") } if err != nil { panic(err) } render(w, r, "article_list", map[string]interface{}{ "Title": "Read", "Articles": articles, }) }
// Logout de-authenticate the user. func Logout(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { sessions.GetSession(r).Clear() http.Redirect(w, r, r.Referer(), http.StatusFound) }