From a38f778312b392614ec0ccf14f9f2790671b63eb Mon Sep 17 00:00:00 2001 From: Thibaut Horel Date: Mon, 12 Jun 2017 23:52:26 -0400 Subject: Abstract all DB access via DataStore, fix lfm_password bug --- apiv1.go | 2 +- data.go | 59 ++++++++++++++++++++++++++++++++-- main.go | 3 -- templates/settings.tmpl | 2 +- web.go | 85 +++++++++++++++++++++++++------------------------ 5 files changed, 102 insertions(+), 49 deletions(-) diff --git a/apiv1.go b/apiv1.go index a23780b..e555a18 100644 --- a/apiv1.go +++ b/apiv1.go @@ -36,7 +36,7 @@ func (app *App) mainHandler(w http.ResponseWriter, r *http.Request) { user := r.FormValue("u") auth := r.FormValue("a") - userId, password, err := app.GetUser(user) + userId, password, err := app.GetScrobblingUser(user) if (md5hex(password+timestamp) != auth) || err != nil { fmt.Fprintln(w, "BADAUTH") return diff --git a/data.go b/data.go index 9e5f5d5..3ece80f 100644 --- a/data.go +++ b/data.go @@ -40,11 +40,17 @@ type Session struct { type DataStore interface { PutSession(*Session) error GetSession(key string) (*Session, error) - GetUser(lfmName string) (int, string, error) PutScrobbles([]Scrobble) error RecentScrobbles(userId int) []*Scrobble GetSongId(artist, album, name string) (int, error) InsertSong(s *Scrobble) (int, error) + + GetScrobblingUser(lfmName string) (int, string, error) + GetUser(u *User) error + InsertUser(u *User) error + SaveUser(u *User) error + + InsertUserSession(s *UserSession) error Api } @@ -71,7 +77,7 @@ func (store *SqlStore) GetSession(key string) (*Session, error) { return s, err } -func (store *SqlStore) GetUser(lfmName string) (int, string, error) { +func (store *SqlStore) GetScrobblingUser(lfmName string) (int, string, error) { var password string var userId int row := store.QueryRow("SELECT user_id, lfm_password FROM users WHERE lfm_name = $1", @@ -153,3 +159,52 @@ func (store *SqlStore) InsertSong(s *Scrobble) (int, error) { err := row.Scan(&id) return id, err } + +func (store *SqlStore) InsertUser(user *User) error { + query := ` + INSERT into users (type, op_id, name, email) + VALUES ($1, $2, $3, $4) RETURNING user_id` + row := store.QueryRow(query, user.Type, user.OpId, user.Name, user.Email) + return row.Scan(&user.Id) +} + +func (store *SqlStore) GetUser(user *User) error { + var query string + var row *sql.Row + if user.Id == 0 { + query = ` + SELECT user_id, name, email, lfm_name + FROM users WHERE type=$1 AND op_id=$2` + row = store.QueryRow(query, user.Type, user.OpId) + } else { + query = ` + SELECT user_id, name, email, lfm_name + FROM users WHERE user_id=$1` + row = store.QueryRow(query, user.Id) + } + return row.Scan(&user.Id, &user.Name, &user.Email, &user.LfmName) +} + +func (store *SqlStore) SaveUser(user *User) error { + var err error + var query string + if user.LfmPassword != "" { + query = ` + UPDATE users SET name=$1, email=$2, lfm_name=$3, lfm_password=$4 + WHERE user_id=$5` + _, err = store.Exec(query, user.Name, user.Email, user.LfmName, + user.LfmPassword, user.Id) + } else { + query = ` + UPDATE users SET name=$1, email=$2, lfm_name=$3 WHERE user_id=$5` + _, err = store.Exec(query, user.Name, user.Email, user.LfmName, user.Id) + + } + return err +} + +func (store *SqlStore) InsertUserSession(s *UserSession) error { + query := `INSERT into user_sessions values ($1, $2)` + _, err := store.Exec(query, &s.Id, &s.UserId) + return err +} diff --git a/main.go b/main.go index c4e5cd9..6080b69 100644 --- a/main.go +++ b/main.go @@ -19,7 +19,6 @@ type handler func(DataStore, http.ResponseWriter, *http.Request) type App struct { DataStore - DB *sql.DB Config *Config CookieHandler *securecookie.SecureCookie Template *template.Template @@ -33,7 +32,6 @@ func New() *App { if err = db.Ping(); err != nil { log.Fatal(err) } - app.DB = db app.DataStore = &SqlStore{db} hashKey, err := hex.DecodeString(config.HashKey) blockKey, err := hex.DecodeString(config.BlockKey) @@ -85,7 +83,6 @@ func (app *App) InitWebServer() *http.Server { func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) app := New() - defer app.DB.Close() apiServer := app.InitApiServer() webServer := app.InitWebServer() diff --git a/templates/settings.tmpl b/templates/settings.tmpl index 5c757ee..00b2125 100644 --- a/templates/settings.tmpl +++ b/templates/settings.tmpl @@ -4,7 +4,7 @@

Profile

- +
diff --git a/web.go b/web.go index 5e17b61..5dc2e70 100644 --- a/web.go +++ b/web.go @@ -1,7 +1,6 @@ package main import ( - "context" "encoding/hex" "encoding/json" "fmt" @@ -12,10 +11,14 @@ import ( _ "github.com/lib/pq" ) -type UserInfo struct { - Sub string `json:"sub"` - UserName string `json:"given_name"` - Email string `json:"email"` +type User struct { + Id int + Type string + OpId string `json:"sub"` + Name string `json:"given_name"` + Email string `json:"email"` + LfmName string + LfmPassword string } type UserSession struct { @@ -67,32 +70,26 @@ func (app *App) callback(w http.ResponseWriter, r *http.Request) { panic(fmt.Errorf("state")) } code := r.FormValue("code") - tok, _ := app.Config.OAuth.Exchange(context.Background(), code) - client := app.Config.OAuth.Client(context.Background(), tok) + tok, _ := app.Config.OAuth.Exchange(r.Context(), code) + client := app.Config.OAuth.Client(r.Context(), tok) resp, _ := client.Get("https://www.googleapis.com/plus/v1/people/me/openIdConnect") p, _ := ioutil.ReadAll(resp.Body) - userinfo := new(UserInfo) - json.Unmarshal(p, userinfo) + user := &User{Type: "google"} + json.Unmarshal(p, user) - se := new(UserSession) - se.Id = hex.EncodeToString(genKey(32)) - row := app.DB.QueryRow("SELECT user_id, name FROM users WHERE type='google' AND op_id=$1", - userinfo.Sub) - err := row.Scan(&se.UserId, &se.UserName) - if err != nil { - row := app.DB.QueryRow("INSERT into users (type, op_id, name, email)"+ - "values ('google', $1, $2, $3) RETURNING user_id", - userinfo.Sub, userinfo.UserName, userinfo.Email) - row.Scan(&se.UserId) - se.UserName = userinfo.UserName - } - app.DB.Exec("INSERT into user_sessions values ($1, $2)", se.Id, se.UserId) - app.SetCookie(w, "session", se, 86400*30) - if err != nil { + s := &UserSession{Id: hex.EncodeToString(genKey(32))} + if err := app.GetUser(user); err != nil { + if err := app.InsertUser(user); err != nil { + panic(err) + } http.Redirect(w, r, "/settings", http.StatusTemporaryRedirect) - return + } else { + http.Redirect(w, r, "/", http.StatusFound) } - http.Redirect(w, r, "/", http.StatusFound) + s.UserId = user.Id + s.UserName = user.Name + app.InsertUserSession(s) + app.SetCookie(w, "session", s, 86400*30) } func (app *App) settings(w http.ResponseWriter, r *http.Request) { @@ -104,25 +101,29 @@ func (app *App) settings(w http.ResponseWriter, r *http.Request) { } if r.Method == "POST" { - _, err = app.DB.Exec("UPDATE users SET name=$1, email=$2, lfm_name=$3, lfm_password=$4 WHERE user_id=$5", - r.FormValue("name"), r.FormValue("email"), r.FormValue("lfm_name"), - md5hex(r.FormValue("lfm_password")), se.UserId) - if err != nil { + u := &User{ + Id: se.UserId, + Name: r.FormValue("name"), + Email: r.FormValue("email"), + LfmName: r.FormValue("lfm_name"), + LfmPassword: md5hex(r.FormValue("lfm_password")), + } + if err := app.SaveUser(u); err != nil { log.Println(err) } - se.UserName = r.FormValue("name") + se.UserName = u.Name app.SetCookie(w, "session", se, 86400*30) } - var userName, email, lfmName, lfmPassword string - row := app.DB.QueryRow("SELECT name, email, lfm_name, lfm_password FROM users WHERE user_id=$1", - se.UserId) - row.Scan(&userName, &email, &lfmName, &lfmPassword) - app.Template.ExecuteTemplate(w, "settings.tmpl", struct { - Session *UserSession - UserName string - Email string - LfmName string - LfmPassword string - }{se, userName, email, lfmName, lfmPassword}) + user := &User{Id: se.UserId} + if err := app.GetUser(user); err != nil { + log.Println(err) + } + err = app.Template.ExecuteTemplate(w, "settings.tmpl", struct { + Session *UserSession + *User + }{Session: se, User: user}) + if err != nil { + log.Println(err) + } } -- cgit v1.2.3-70-g09d2