package main import ( "context" "encoding/hex" "encoding/json" "fmt" "io/ioutil" "log" "net/http" _ "github.com/lib/pq" ) type UserInfo struct { Sub string `json:"sub"` UserName string `json:"given_name"` Email string `json:"email"` } type UserSession struct { Id string UserId int UserName string } func (app *App) login(w http.ResponseWriter, r *http.Request) { state := hex.EncodeToString(genKey(32)) if err := app.SetCookie(w, "state", state, 120); err != nil { log.Panic(err) } url := app.Config.OAuth.AuthCodeURL(state) app.Template.ExecuteTemplate(w, "login.tmpl", url) } func (app *App) root(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } se := new(UserSession) err := app.GetCookie(r, "session", se) if err != nil { http.Redirect(w, r, "/login", http.StatusFound) return } scrobbles := app.RecentScrobbles(se.UserId) app.Template.ExecuteTemplate(w, "index.tmpl", struct { Session *UserSession Scrobbles []*Scrobble }{se, scrobbles}) } func (app *App) callback(w http.ResponseWriter, r *http.Request) { defer func() { if rec := recover(); rec != nil { http.Redirect(w, r, "/login", http.StatusFound) log.Println(rec) } }() var state string app.GetCookie(r, "state", &state) if state == "" || state != r.FormValue("state") { panic(fmt.Errorf("state")) } code := r.FormValue("code") tok, _ := app.Config.OAuth.Exchange(context.Background(), code) client := app.Config.OAuth.Client(context.Background(), 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) 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 { http.Redirect(w, r, "/settings", http.StatusTemporaryRedirect) return } http.Redirect(w, r, "/", http.StatusFound) } func (app *App) settings(w http.ResponseWriter, r *http.Request) { se := new(UserSession) err := app.GetCookie(r, "session", se) if err != nil { http.Redirect(w, r, "/login", http.StatusFound) return } 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 { log.Println(err) } se.UserName = r.FormValue("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}) }