From 317ee6e075dadb2e2d21efe6ae33bc8fd30e95cf Mon Sep 17 00:00:00 2001 From: Gregory Eremin Date: Thu, 5 Mar 2015 22:04:44 +0700 Subject: [PATCH] Sessions --- db/token.go | 14 +++++++++++-- db/user.go | 24 +++++++++++++++++++++ server/auth.go | 13 +++++++----- server/server.go | 24 --------------------- server/session.go | 50 ++++++++++++++++++++++++++++++++++++++++++++ task/access_token.go | 36 +++++++++++++++++++++++++++++-- task/common.go | 5 +++-- 7 files changed, 131 insertions(+), 35 deletions(-) create mode 100644 db/user.go create mode 100644 server/session.go diff --git a/db/token.go b/db/token.go index fd47dc2..5bceb26 100644 --- a/db/token.go +++ b/db/token.go @@ -7,7 +7,7 @@ import ( type ( Token struct { ID int - Owner string + User string Token string Limit int Remaining int @@ -16,6 +16,16 @@ type ( } ) -func UpdateToken(t *Token) { +const ( + saveTokenQuery = "" + + "insert into tokens (`user`, token, `limit`, remaining, reset_at, created_at) " + + "values (?, ?, ?, ?, ?, now()) " + + "on duplicate key update " + + "`limit` = values(`limit`), remaining = values(remaining), reset_at = values(reset_at)" +) +func (t *Token) Save() { + if _, err := stmt(saveTokenQuery).Exec(t.User, t.Token, t.Limit, t.Remaining, t.ResetAt); err != nil { + panic(err) + } } diff --git a/db/user.go b/db/user.go new file mode 100644 index 0000000..f6cea6c --- /dev/null +++ b/db/user.go @@ -0,0 +1,24 @@ +package db + +type ( + User struct { + Login string `json:"login"` + Name string `json:"name"` + ID int64 `json:"id"` + AvatarURL string `json:"avatar_url"` + } +) + +const ( + saveUserQuery = "" + + "insert into users (login, name, id, avatar_url) " + + "values (?, ?, ?, ?) " + + "on duplicate key update " + + "login=values(login), name=values(name), avatar_url=values(avatar_url)" +) + +func (u *User) Save() { + if _, err := stmt(saveUserQuery).Exec(u.Login, u.Name, u.ID, u.AvatarURL); err != nil { + panic(err) + } +} diff --git a/server/auth.go b/server/auth.go index 518d94c..bcb6b86 100644 --- a/server/auth.go +++ b/server/auth.go @@ -12,6 +12,10 @@ import ( ) func authHelloHandler(w http.ResponseWriter, r *http.Request) { + if currentUser(r) != "" { + http.Redirect(w, r, "/app", 302) + return + } w.Header().Set("Content-Type", "text/html; charset=utf8") helloTmpl.ExecuteTemplate(w, "hello", map[string]interface{}{}) } @@ -20,7 +24,7 @@ func authSigninHandler(w http.ResponseWriter, r *http.Request) { params := url.Values{} params.Set("client_id", config.C().ClientID) params.Set("redirect_uri", config.C().RedirectURI) - params.Set("scope", "repo") + params.Set("scope", "read:org, repo, admin:org_hook") http.Redirect(w, r, config.C().AuthURL+"?"+params.Encode(), 302) } @@ -38,11 +42,10 @@ func authCallbackHandler(w http.ResponseWriter, r *http.Request) { Task: &db.Task{}, }) - if token, ok := <-res; ok { - fmt.Println("Got access token: ", token) - w.Write([]byte(token)) + if login, ok := <-res; ok { + authorize(r, login) } else { - panic("Failed to fetch token") + panic("Failed to access token or user info") } } } diff --git a/server/server.go b/server/server.go index 27ac7cb..b8549d6 100644 --- a/server/server.go +++ b/server/server.go @@ -4,16 +4,10 @@ import ( "fmt" "html/template" "net/http" - "time" - "code.google.com/p/go-uuid/uuid" "github.com/GeertJohan/go.rice" ) -const ( - sessionCookie = "session_id" -) - var ( helloTmpl = template.New("hello") ) @@ -34,21 +28,3 @@ func Start() { fmt.Println("Starting server at http://localhost:8080") http.ListenAndServe(":8080", nil) } - -func sessionHandler(w http.ResponseWriter, r *http.Request) { - if cook, err := r.Cookie(sessionCookie); err != nil { - cook = &http.Cookie{ - Name: sessionCookie, - Value: uuid.New(), - Path: "/", - Expires: time.Now().Add(365 * 24 * time.Hour), - HttpOnly: true, - } - http.SetCookie(w, cook) - } -} - -func sessionID(r *http.Request) string { - cook, _ := r.Cookie(sessionCookie) - return cook.Value -} diff --git a/server/session.go b/server/session.go new file mode 100644 index 0000000..aa90cca --- /dev/null +++ b/server/session.go @@ -0,0 +1,50 @@ +package server + +import ( + "net/http" + "time" + + "code.google.com/p/go-uuid/uuid" + "github.com/garyburd/redigo/redis" +) + +const ( + sessionCookie = "session_id" +) + +var ( + redisC = redis.NewPool(dialRedis, 10) +) + +func dialRedis() (redis.Conn, error) { + return redis.Dial("tcp", ":6379") +} + +func sessionHandler(w http.ResponseWriter, r *http.Request) { + if cook, err := r.Cookie(sessionCookie); err != nil { + cook = &http.Cookie{ + Name: sessionCookie, + Value: uuid.New(), + Path: "/", + Expires: time.Now().Add(365 * 24 * time.Hour), + HttpOnly: true, + } + http.SetCookie(w, cook) + } +} + +func sessionID(r *http.Request) string { + cook, _ := r.Cookie(sessionCookie) + return cook.Value +} + +func currentUser(r *http.Request) string { + conn := redisC.Get() + login, _ := redis.String(conn.Do("HGET", "sessions", sessionID(r))) + + return login +} + +func authorize(r *http.Request, login string) { + redisC.Get().Do("HSET", "sessions", sessionID(r), login) +} diff --git a/task/access_token.go b/task/access_token.go index 2b4a0e8..87987e1 100644 --- a/task/access_token.go +++ b/task/access_token.go @@ -2,6 +2,8 @@ package task import ( "bytes" + "encoding/json" + "fmt" "io/ioutil" "net/http" "net/url" @@ -27,6 +29,7 @@ func FetchAccessToken(tk Tasker) { payload.Set("redirect_uri", config.C().RedirectURI) buf := bytes.NewBuffer([]byte(payload.Encode())) + fmt.Println("Requesting token") resp, err := http.Post(config.C().AccessTokenURL, "application/x-www-form-urlencoded", buf) if err != nil { panic(err) @@ -38,7 +41,36 @@ func FetchAccessToken(tk Tasker) { panic(err) } - pairs, _ := url.ParseQuery(string(body)) + fmt.Println(string(body)) - t.Result <- pairs.Get("access_token") + pairs, _ := url.ParseQuery(string(body)) + token := pairs.Get("access_token") + fmt.Println("Got token: " + token) + + fmt.Println("Requesting info") + resp, err = http.Get("https://api.github.com/user?access_token=" + token) + if err != nil { + panic(err) + } + + defer resp.Body.Close() + body, err = ioutil.ReadAll(resp.Body) + if err != nil { + panic(err) + } + fmt.Println(string(body)) + + user := &db.User{} + json.Unmarshal(body, &user) + user.Save() + fmt.Println("Saving user", user) + + tok := &db.Token{ + User: user.Login, + Token: token, + } + fmt.Println("Saving token", tok) + tok.Save() + + t.Result <- user.Login } diff --git a/task/common.go b/task/common.go index 18b394a..dcee152 100644 --- a/task/common.go +++ b/task/common.go @@ -24,10 +24,11 @@ func saveResponseMeta(token string, res *github.Response) { if res == nil { return } - db.UpdateToken(&db.Token{ + tok := &db.Token{ Token: token, Limit: res.Limit, Remaining: res.Remaining, ResetAt: res.Reset.Time, - }) + } + tok.Save() }