diff --git a/app/githop.go b/app/githop.go index 9654bd2..1638806 100644 --- a/app/githop.go +++ b/app/githop.go @@ -1,61 +1,80 @@ package githop import ( + "encoding/base64" "encoding/json" "html/template" "io/ioutil" + "log" "net/http" + "net/url" "appengine" "appengine/urlfetch" "code.google.com/p/goauth2/oauth" "github.com/google/go-github/github" + "github.com/gorilla/mux" ) +var router *mux.Router +var githubOauthConfig oauth.Config + +func initGithubOAuthConfig() { + path := "config/github-oauth" + if appengine.IsDevAppServer() { + path += "-dev" + } + path += ".json" + configBytes, err := ioutil.ReadFile(path) + if err != nil { + log.Panicf("Could not read GitHut OAuth config from %s: %s", path, err.Error()) + } + err = json.Unmarshal(configBytes, &githubOauthConfig) + if err != nil { + log.Panicf("Could not parse GitHut OAuth %s", err.Error()) + } + githubOauthConfig.Scope = "repo" + githubOauthConfig.AuthURL = "https://github.com/login/oauth/authorize" + githubOauthConfig.TokenURL = "https://github.com/login/oauth/access_token" +} + func init() { - http.HandleFunc("/", index) + initGithubOAuthConfig() + + router = mux.NewRouter() + router.HandleFunc("/", indexHandler).Name("index") + router.HandleFunc("/github/callback", githubOAuthCallbackHandler) + http.Handle("/", router) } var indexTemplate = template.Must(template.ParseFiles("templates/index.html")) -func index(w http.ResponseWriter, r *http.Request) { - // TODO: Don't do this every request - github_oauth_config_path := "config/github-oauth" - if appengine.IsDevAppServer() { - github_oauth_config_path += "-dev" +func indexHandler(w http.ResponseWriter, r *http.Request) { + tokenEncoded := r.FormValue("token") + if tokenEncoded == "" { + http.Redirect(w, r, githubOauthConfig.AuthCodeURL(""), http.StatusFound) + return } - github_oauth_config_path += ".json" - github_oauth_config_bytes, err := ioutil.ReadFile(github_oauth_config_path) + tokenBytes, err := base64.URLEncoding.DecodeString(tokenEncoded) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - var github_oauth_config oauth.Config - err = json.Unmarshal(github_oauth_config_bytes, &github_oauth_config) + var token oauth.Token + err = json.Unmarshal(tokenBytes, &token) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - github_oauth_config.Scope = "repo" - github_oauth_config.AuthURL = "https://github.com/login/oauth/authorize" - github_oauth_config.TokenURL = "https://github.com/login/oauth/access_token" - - code := r.FormValue("code") - if code == "" { - http.Redirect(w, r, github_oauth_config.AuthCodeURL(""), http.StatusFound) - return + appengineContext := appengine.NewContext(r) + oauthTransport := &oauth.Transport{ + Config: &githubOauthConfig, + Transport: &urlfetch.Transport{Context: appengineContext}, + Token: &token, } - appengine_context := appengine.NewContext(r) - oauth_transport := &oauth.Transport{ - Config: &github_oauth_config, - Transport: &urlfetch.Transport{Context: appengine_context}, - } - token, _ := oauth_transport.Exchange(code) - oauth_transport.Token = token - - github_client := github.NewClient(oauth_transport.Client()) - events, _, err := github_client.Activity.ListEventsPerformedByUser("mihaip", false, nil) + githubClient := github.NewClient(oauthTransport.Client()) + events, _, err := githubClient.Activity.ListEventsPerformedByUser("mihaip", false, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -64,3 +83,28 @@ func index(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) } } + +func githubOAuthCallbackHandler(w http.ResponseWriter, r *http.Request) { + code := r.FormValue("code") + appengineContext := appengine.NewContext(r) + oauthTransport := &oauth.Transport{ + Config: &githubOauthConfig, + Transport: &urlfetch.Transport{Context: appengineContext}, + } + token, err := oauthTransport.Exchange(code) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + tokenBytes, err := json.Marshal(token) + tokenEncoded := base64.StdEncoding.EncodeToString(tokenBytes) + redirectUrl, err := router.GetRoute("index").URL() + redirectParams := url.Values{} + redirectParams.Add("token", tokenEncoded) + redirectUrl.RawQuery = redirectParams.Encode() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + http.Redirect(w, r, redirectUrl.String(), http.StatusFound) +}