mirror of
https://github.com/samsonjs/retrogit.git
synced 2026-04-27 15:07:43 +00:00
Add helper wrapper for handlers that require signed in state, to reduce boilerplate.
This commit is contained in:
parent
852142b726
commit
16f16ae9d9
2 changed files with 98 additions and 91 deletions
68
app/app.go
68
app/app.go
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"appengine"
|
"appengine"
|
||||||
|
|
||||||
"github.com/google/go-github/github"
|
"github.com/google/go-github/github"
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -32,6 +33,36 @@ type AppError struct {
|
||||||
Type int
|
Type int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AppSignedInState struct {
|
||||||
|
Account *Account
|
||||||
|
GitHubClient *github.Client
|
||||||
|
session *sessions.Session
|
||||||
|
request *http.Request
|
||||||
|
responseWriter http.ResponseWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *AppSignedInState) AddFlash(value interface{}) {
|
||||||
|
state.session.AddFlash(value)
|
||||||
|
state.saveSession()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *AppSignedInState) Flashes() []interface{} {
|
||||||
|
flashes := state.session.Flashes()
|
||||||
|
if len(flashes) > 0 {
|
||||||
|
state.saveSession()
|
||||||
|
}
|
||||||
|
return flashes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *AppSignedInState) ClearSession() {
|
||||||
|
state.session.Options.MaxAge = -1
|
||||||
|
state.saveSession()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *AppSignedInState) saveSession() {
|
||||||
|
state.session.Save(state.request, state.responseWriter)
|
||||||
|
}
|
||||||
|
|
||||||
func GitHubFetchError(err error, fetchType string) *AppError {
|
func GitHubFetchError(err error, fetchType string) *AppError {
|
||||||
return &AppError{
|
return &AppError{
|
||||||
Error: err,
|
Error: err,
|
||||||
|
|
@ -84,6 +115,10 @@ func RedirectToRoute(routeName string) *AppError {
|
||||||
return RedirectToUrl(routeUrl.String())
|
return RedirectToUrl(routeUrl.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NotSignedIn() *AppError {
|
||||||
|
return RedirectToRoute("index")
|
||||||
|
}
|
||||||
|
|
||||||
type AppHandler func(http.ResponseWriter, *http.Request) *AppError
|
type AppHandler func(http.ResponseWriter, *http.Request) *AppError
|
||||||
|
|
||||||
func (fn AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (fn AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
@ -92,6 +127,39 @@ func (fn AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SignedInAppHandler func(http.ResponseWriter, *http.Request, *AppSignedInState) *AppError
|
||||||
|
|
||||||
|
func (fn SignedInAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, _ := sessionStore.Get(r, sessionConfig.CookieName)
|
||||||
|
userId, ok := session.Values[sessionConfig.UserIdKey].(int)
|
||||||
|
if !ok {
|
||||||
|
handleAppError(NotSignedIn(), w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c := appengine.NewContext(r)
|
||||||
|
account, err := getAccount(c, userId)
|
||||||
|
if account == nil || err != nil {
|
||||||
|
handleAppError(NotSignedIn(), w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
oauthTransport := githubOAuthTransport(c)
|
||||||
|
oauthTransport.Token = &account.OAuthToken
|
||||||
|
githubClient := github.NewClient(oauthTransport.Client())
|
||||||
|
|
||||||
|
state := &AppSignedInState{
|
||||||
|
Account: account,
|
||||||
|
GitHubClient: githubClient,
|
||||||
|
session: session,
|
||||||
|
responseWriter: w,
|
||||||
|
request: r,
|
||||||
|
}
|
||||||
|
|
||||||
|
if e := fn(w, r, state); e != nil {
|
||||||
|
handleAppError(e, w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func handleAppError(e *AppError, w http.ResponseWriter, r *http.Request) {
|
func handleAppError(e *AppError, w http.ResponseWriter, r *http.Request) {
|
||||||
c := appengine.NewContext(r)
|
c := appengine.NewContext(r)
|
||||||
if e.Type == AppErrorTypeGitHubFetch {
|
if e.Type == AppErrorTypeGitHubFetch {
|
||||||
|
|
|
||||||
121
app/retrogit.go
121
app/retrogit.go
|
|
@ -46,14 +46,14 @@ func init() {
|
||||||
router.Handle("/session/sign-out", AppHandler(signOutHandler)).Name("sign-out").Methods("POST")
|
router.Handle("/session/sign-out", AppHandler(signOutHandler)).Name("sign-out").Methods("POST")
|
||||||
router.Handle("/github/callback", AppHandler(githubOAuthCallbackHandler))
|
router.Handle("/github/callback", AppHandler(githubOAuthCallbackHandler))
|
||||||
|
|
||||||
router.Handle("/digest/view", AppHandler(viewDigestHandler)).Name("view-digest")
|
router.Handle("/digest/view", SignedInAppHandler(viewDigestHandler)).Name("view-digest")
|
||||||
router.Handle("/digest/send", AppHandler(sendDigestHandler)).Name("send-digest").Methods("POST")
|
router.Handle("/digest/send", SignedInAppHandler(sendDigestHandler)).Name("send-digest").Methods("POST")
|
||||||
router.Handle("/digest/cron", AppHandler(digestCronHandler))
|
router.Handle("/digest/cron", AppHandler(digestCronHandler))
|
||||||
|
|
||||||
router.Handle("/account/settings", AppHandler(settingsHandler)).Name("settings").Methods("GET")
|
router.Handle("/account/settings", SignedInAppHandler(settingsHandler)).Name("settings").Methods("GET")
|
||||||
router.Handle("/account/settings", AppHandler(saveSettingsHandler)).Name("save-settings").Methods("POST")
|
router.Handle("/account/settings", SignedInAppHandler(saveSettingsHandler)).Name("save-settings").Methods("POST")
|
||||||
router.Handle("/account/set-initial-timezone", AppHandler(setInitialTimezoneHandler)).Name("set-initial-timezone").Methods("POST")
|
router.Handle("/account/set-initial-timezone", SignedInAppHandler(setInitialTimezoneHandler)).Name("set-initial-timezone").Methods("POST")
|
||||||
router.Handle("/account/delete", AppHandler(deleteAccountHandler)).Name("delete-account").Methods("POST")
|
router.Handle("/account/delete", SignedInAppHandler(deleteAccountHandler)).Name("delete-account").Methods("POST")
|
||||||
|
|
||||||
router.Handle("/admin/users", AppHandler(usersAdminHandler))
|
router.Handle("/admin/users", AppHandler(usersAdminHandler))
|
||||||
router.Handle("/admin/digest", AppHandler(digestAdminHandler)).Name("digest-admin")
|
router.Handle("/admin/digest", AppHandler(digestAdminHandler)).Name("digest-admin")
|
||||||
|
|
@ -183,20 +183,9 @@ func signOutHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
||||||
return RedirectToRoute("index")
|
return RedirectToRoute("index")
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewDigestHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
func viewDigestHandler(w http.ResponseWriter, r *http.Request, state *AppSignedInState) *AppError {
|
||||||
session, _ := sessionStore.Get(r, sessionConfig.CookieName)
|
|
||||||
userId := session.Values[sessionConfig.UserIdKey].(int)
|
|
||||||
c := appengine.NewContext(r)
|
c := appengine.NewContext(r)
|
||||||
account, err := getAccount(c, userId)
|
digest, err := newDigest(c, state.GitHubClient, state.Account)
|
||||||
if err != nil {
|
|
||||||
return InternalError(err, "Could not look up account")
|
|
||||||
}
|
|
||||||
|
|
||||||
oauthTransport := githubOAuthTransport(c)
|
|
||||||
oauthTransport.Token = &account.OAuthToken
|
|
||||||
githubClient := github.NewClient(oauthTransport.Client())
|
|
||||||
|
|
||||||
digest, err := newDigest(c, githubClient, account)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitHubFetchError(err, "digest")
|
return GitHubFetchError(err, "digest")
|
||||||
}
|
}
|
||||||
|
|
@ -206,26 +195,18 @@ func viewDigestHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
||||||
return templates["digest-page"].Render(w, data)
|
return templates["digest-page"].Render(w, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendDigestHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
func sendDigestHandler(w http.ResponseWriter, r *http.Request, state *AppSignedInState) *AppError {
|
||||||
session, _ := sessionStore.Get(r, sessionConfig.CookieName)
|
|
||||||
userId := session.Values[sessionConfig.UserIdKey].(int)
|
|
||||||
c := appengine.NewContext(r)
|
c := appengine.NewContext(r)
|
||||||
account, err := getAccount(c, userId)
|
sent, err := sendDigestForAccount(state.Account, c)
|
||||||
if err != nil {
|
|
||||||
return InternalError(err, "Could not look up account")
|
|
||||||
}
|
|
||||||
|
|
||||||
sent, err := sendDigestForAccount(account, c)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InternalError(err, "Could not send digest")
|
return InternalError(err, "Could not send digest")
|
||||||
}
|
}
|
||||||
|
|
||||||
if sent {
|
if sent {
|
||||||
session.AddFlash("Digest emailed!")
|
state.AddFlash("Digest emailed!")
|
||||||
} else {
|
} else {
|
||||||
session.AddFlash("No digest was sent, it was empty or disabled.")
|
state.AddFlash("No digest was sent, it was empty or disabled.")
|
||||||
}
|
}
|
||||||
session.Save(r, w)
|
|
||||||
return RedirectToRoute("index")
|
return RedirectToRoute("index")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,31 +327,19 @@ func githubOAuthCallbackHandler(w http.ResponseWriter, r *http.Request) *AppErro
|
||||||
return RedirectToUrl(continueUrl)
|
return RedirectToUrl(continueUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func settingsHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
func settingsHandler(w http.ResponseWriter, r *http.Request, state *AppSignedInState) *AppError {
|
||||||
session, _ := sessionStore.Get(r, sessionConfig.CookieName)
|
|
||||||
userId := session.Values[sessionConfig.UserIdKey].(int)
|
|
||||||
c := appengine.NewContext(r)
|
c := appengine.NewContext(r)
|
||||||
account, err := getAccount(c, userId)
|
user, _, err := state.GitHubClient.Users.Get("")
|
||||||
if err != nil {
|
|
||||||
// TODO: redirect to sign in again
|
|
||||||
return InternalError(err, "Could not look up account")
|
|
||||||
}
|
|
||||||
|
|
||||||
oauthTransport := githubOAuthTransport(c)
|
|
||||||
oauthTransport.Token = &account.OAuthToken
|
|
||||||
githubClient := github.NewClient(oauthTransport.Client())
|
|
||||||
|
|
||||||
user, _, err := githubClient.Users.Get("")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitHubFetchError(err, "user")
|
return GitHubFetchError(err, "user")
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, err := getRepos(c, githubClient, account, user)
|
repos, err := getRepos(c, state.GitHubClient, state.Account, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitHubFetchError(err, "repositories")
|
return GitHubFetchError(err, "repositories")
|
||||||
}
|
}
|
||||||
|
|
||||||
emails, _, err := githubClient.Users.ListEmails(nil)
|
emails, _, err := state.GitHubClient.Users.ListEmails(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitHubFetchError(err, "emails")
|
return GitHubFetchError(err, "emails")
|
||||||
}
|
}
|
||||||
|
|
@ -378,18 +347,15 @@ func settingsHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
||||||
for i := range emails {
|
for i := range emails {
|
||||||
emailAddresses[i] = *emails[i].Email
|
emailAddresses[i] = *emails[i].Email
|
||||||
}
|
}
|
||||||
accountEmailAddress, err := account.GetDigestEmailAddress(githubClient)
|
accountEmailAddress, err := state.Account.GetDigestEmailAddress(state.GitHubClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitHubFetchError(err, "emails")
|
return GitHubFetchError(err, "emails")
|
||||||
}
|
}
|
||||||
|
|
||||||
flashes := session.Flashes()
|
flashes := state.Flashes()
|
||||||
if len(flashes) > 0 {
|
|
||||||
session.Save(r, w)
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = map[string]interface{}{
|
var data = map[string]interface{}{
|
||||||
"Account": account,
|
"Account": state.Account,
|
||||||
"User": user,
|
"User": user,
|
||||||
"Timezones": timezones,
|
"Timezones": timezones,
|
||||||
"Repos": repos,
|
"Repos": repos,
|
||||||
|
|
@ -400,25 +366,16 @@ func settingsHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
||||||
return templates["settings"].Render(w, data)
|
return templates["settings"].Render(w, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveSettingsHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
func saveSettingsHandler(w http.ResponseWriter, r *http.Request, state *AppSignedInState) *AppError {
|
||||||
session, _ := sessionStore.Get(r, sessionConfig.CookieName)
|
|
||||||
userId := session.Values[sessionConfig.UserIdKey].(int)
|
|
||||||
c := appengine.NewContext(r)
|
c := appengine.NewContext(r)
|
||||||
account, err := getAccount(c, userId)
|
account := state.Account
|
||||||
if err != nil {
|
|
||||||
// TODO: redirect to sign in again
|
|
||||||
return InternalError(err, "Could not look up account")
|
|
||||||
}
|
|
||||||
oauthTransport := githubOAuthTransport(c)
|
|
||||||
oauthTransport.Token = &account.OAuthToken
|
|
||||||
githubClient := github.NewClient(oauthTransport.Client())
|
|
||||||
|
|
||||||
user, _, err := githubClient.Users.Get("")
|
user, _, err := state.GitHubClient.Users.Get("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitHubFetchError(err, "user")
|
return GitHubFetchError(err, "user")
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, err := getRepos(c, githubClient, account, user)
|
repos, err := getRepos(c, state.GitHubClient, account, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitHubFetchError(err, "repos")
|
return GitHubFetchError(err, "repos")
|
||||||
}
|
}
|
||||||
|
|
@ -453,23 +410,16 @@ func saveSettingsHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
||||||
return InternalError(err, "Could not save user")
|
return InternalError(err, "Could not save user")
|
||||||
}
|
}
|
||||||
|
|
||||||
session.AddFlash("Settings saved.")
|
state.AddFlash("Settings saved.")
|
||||||
session.Save(r, w)
|
|
||||||
return RedirectToRoute("settings")
|
return RedirectToRoute("settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
func setInitialTimezoneHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
func setInitialTimezoneHandler(w http.ResponseWriter, r *http.Request, state *AppSignedInState) *AppError {
|
||||||
session, _ := sessionStore.Get(r, sessionConfig.CookieName)
|
|
||||||
userId := session.Values[sessionConfig.UserIdKey].(int)
|
|
||||||
c := appengine.NewContext(r)
|
c := appengine.NewContext(r)
|
||||||
account, err := getAccount(c, userId)
|
account := state.Account
|
||||||
if err != nil {
|
|
||||||
// TODO: redirect to sign in again
|
|
||||||
return InternalError(err, "Could not look up account")
|
|
||||||
}
|
|
||||||
|
|
||||||
timezoneName := r.FormValue("timezone_name")
|
timezoneName := r.FormValue("timezone_name")
|
||||||
_, err = time.LoadLocation(timezoneName)
|
_, err := time.LoadLocation(timezoneName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return BadRequest(err, "Malformed timezone_name value")
|
return BadRequest(err, "Malformed timezone_name value")
|
||||||
}
|
}
|
||||||
|
|
@ -512,21 +462,10 @@ var cacheDigestForAccountFunc = delay.Func(
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
func deleteAccountHandler(w http.ResponseWriter, r *http.Request) *AppError {
|
func deleteAccountHandler(w http.ResponseWriter, r *http.Request, state *AppSignedInState) *AppError {
|
||||||
session, _ := sessionStore.Get(r, sessionConfig.CookieName)
|
|
||||||
userId := session.Values[sessionConfig.UserIdKey].(int)
|
|
||||||
c := appengine.NewContext(r)
|
c := appengine.NewContext(r)
|
||||||
account, err := getAccount(c, userId)
|
state.Account.Delete(c)
|
||||||
if err != nil {
|
state.ClearSession()
|
||||||
// TODO: redirect to sign in again
|
|
||||||
return InternalError(err, "Could not look up account")
|
|
||||||
}
|
|
||||||
|
|
||||||
account.Delete(c)
|
|
||||||
session.Options.MaxAge = -1
|
|
||||||
session.Save(r, w)
|
|
||||||
|
|
||||||
// TODO: add a flash message saying that the account was deleted.
|
|
||||||
return RedirectToRoute("index")
|
return RedirectToRoute("index")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue