chipmunk/server.go
derek mcquay 4f7b61cb86 google oauth working along with clean up
cleaned up some things from starz that weren't needed any more.  Also
cleaned up the oauth process and now am storing the users emai but also
have the userInfo struct that gathers all the info that google oauth
userinfo returns
2016-08-22 13:03:23 -07:00

243 lines
6.4 KiB
Go

package chipmunk
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"log"
"net/http"
"time"
"github.com/gorilla/sessions"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
var store *sessions.CookieStore
var (
oauthConf = &oauth2.Config{
ClientID: "",
ClientSecret: "",
RedirectURL: "http://127.0.0.1:8080/api/v0/oauth_cb/",
Scopes: []string{"https://www.googleapis.com/auth/userinfo.email"},
Endpoint: google.Endpoint,
}
oauthStateString = "thisshouldberandom"
)
var Version string = "dev"
var start time.Time
type userInfo struct {
Sub string `json:"sub"`
Name string `json:"name"`
GivenName string `json:"given_name"`
FamilyName string `json:"family_name"`
Profile string `json:"profile"`
Picture string `json:"picture"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
}
type failure struct {
Success bool `json:"success"`
Error string `json:"error"`
}
func NewFailure(msg string) *failure {
return &failure{
Success: false,
Error: msg,
}
}
type Server struct {
ClientID string
ClientSecret string
CookieSecret string
}
func init() {
log.SetFlags(log.Ltime)
start = time.Now()
}
func NewServer(sm *http.ServeMux, clientId, clientSecret, cookieSecret, static string) *Server {
server := &Server{
ClientID: clientId,
ClientSecret: clientSecret,
CookieSecret: cookieSecret,
}
addRoutes(sm, server, static)
return server
}
func (s *Server) login(w http.ResponseWriter, r *http.Request) {
oauthConf.ClientID = s.ClientID
oauthConf.ClientSecret = s.ClientSecret
url := oauthConf.AuthCodeURL(oauthStateString, oauth2.AccessTypeOnline)
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}
func (s *Server) oauthCallback(w http.ResponseWriter, r *http.Request) {
state := r.FormValue("state")
if state != oauthStateString {
log.Printf("invalid oauth state, expected '%s', got '%s'\n", oauthStateString, state)
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
return
}
code := r.FormValue("code")
token, err := oauthConf.Exchange(oauth2.NoContext, code)
if err != nil {
log.Printf("oauthConf.Exchange() failed with '%s'\n", err)
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
return
}
oauthClient := oauthConf.Client(oauth2.NoContext, token)
email, err := oauthClient.Get("https://www.googleapis.com/oauth2/v3/userinfo")
if err != nil {
log.Printf("failed with getting userinfo: '%s'\n", err)
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
return
}
defer email.Body.Close()
data, _ := ioutil.ReadAll(email.Body)
u := userInfo{}
err = json.Unmarshal(data, &u)
if err != nil {
log.Printf("failed to unmarshal userinfo: '%s'\n", err)
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
return
}
session, _ := store.Get(r, "creds")
session.Values["authenticated"] = true
session.Values["uname"] = u.Email
if err := session.Save(r, w); err != nil {
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
}
http.Redirect(w, r, "/static/", http.StatusTemporaryRedirect)
}
func (s *Server) list(w http.ResponseWriter, r *http.Request) {
return
// w.Header().Set("Content-Type", "application/json")
// session, _ := store.Get(r, "creds")
// if loggedIn := session.Values["authenticated"]; loggedIn != true {
// http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
// return
// }
// switch r.Method {
// default:
// b, _ := json.Marshal(NewFailure("Allowed method: GET"))
// http.Error(w, string(b), http.StatusBadRequest)
// return
// case "GET":
// searchreq := r.URL.Path[len(prefix["list"]):]
// if len(searchreq) == 0 {
// b, _ := json.Marshal(NewFailure("url could not be parsed"))
// http.Error(w, string(b), http.StatusBadRequest)
// return
// }
// if searchreq[len(searchreq)-1] != '/' {
// http.Redirect(w, r, prefix["list"]+searchreq+"/", http.StatusMovedPermanently)
// return
// }
// searchReqParsed := strings.Split(searchreq, "/")
// client := github.NewClient(nil)
// if s.ApiToken != "" {
// ts := oauth2.StaticTokenSource(
// &oauth2.Token{AccessToken: s.ApiToken},
// )
// tc := oauth2.NewClient(oauth2.NoContext, ts)
// client = github.NewClient(tc)
// }
// opt := &github.RepositoryListOptions{}
// repos, _, err := client.Repositories.List(searchReqParsed[0], opt)
// if err != nil {
// b, _ := json.Marshal(NewFailure("user could not be found"))
// http.Error(w, string(b), http.StatusBadRequest)
// return
// }
// var items []Item
// for _, i := range repos {
// items = append(items, Item{*i.Name, *i.StargazersCount})
// }
//
// err = json.NewEncoder(w).Encode(items)
// if err != nil {
// b, _ := json.Marshal(NewFailure(err.Error()))
// http.Error(w, string(b), http.StatusInternalServerError)
// return
// }
// }
}
func (s *Server) auth(w http.ResponseWriter, r *http.Request) {
output := struct {
Auth bool `json:"auth"`
}{
Auth: false,
}
w.Header().Set("Content-Type", "application/json")
session, _ := store.Get(r, "creds")
if loggedIn := session.Values["authenticated"]; loggedIn == true {
output.Auth = true
json.NewEncoder(w).Encode(output)
return
}
b, _ := json.Marshal(output)
http.Error(w, string(b), http.StatusUnauthorized)
}
func (s *Server) logout(w http.ResponseWriter, req *http.Request) {
session, _ := store.Get(req, "creds")
delete(session.Values, "authenticated")
delete(session.Values, "uname")
session.Save(req, w)
http.Redirect(w, req, "/", http.StatusSeeOther)
}
func (s *Server) serverInfo(w http.ResponseWriter, req *http.Request) {
output := struct {
Version string `json:"version"`
Start string `json:"start"`
Uptime string `json:"uptime"`
}{
Version: Version,
Start: start.Format("2006-01-02 15:04:05"),
Uptime: time.Since(start).String(),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(output)
}
func (s *Server) plist(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "creds")
if loggedIn := session.Values["authenticated"]; loggedIn != true {
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
return
}
data, err := Asset("static/list.html")
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
req := bytes.NewReader(data)
io.Copy(w, req)
}
func (s *Server) health(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
io.WriteString(w, `{"alive": true}`)
}