Skip to content

Commit

Permalink
Merge pull request #11 from tidepool-org/jhbate/auth
Browse files Browse the repository at this point in the history
Jhbate/auth
  • Loading branch information
jh-bate committed Jan 21, 2015
2 parents abffeee + b1a5b44 commit 7650361
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 199 deletions.
2 changes: 1 addition & 1 deletion Comedeps
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ labix.org/v2/mgo bzr https://launchpad.net/mgo/v2 287
github.com/gorilla/mux git https://github.com/gorilla/mux.git 14cafe28513321476c73967a5a4f3454b6129c46
github.com/gorilla/context git https://github.com/gorilla/context.git 14f550f51af52180c2eefed15e5fd18d63c0a64a
github.com/dgrijalva/jwt-go git https://github.com/dgrijalva/jwt-go.git v1.0.1
github.com/tidepool-org/go-common git https://github.com/tidepool-org/go-common.git v0.0.8
github.com/tidepool-org/go-common git https://github.com/tidepool-org/go-common.git v0.0.9
178 changes: 178 additions & 0 deletions api/helpers.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package api

import (
"encoding/base64"
"encoding/json"
"log"
"net/http"
"strconv"
"strings"

"./../models"
"github.com/tidepool-org/go-common/clients/status"
)

const (
Expand All @@ -24,3 +30,175 @@ func tokenDuration(req *http.Request) (dur float64) {

return dur
}

//Docode the http.Request parsing out the user details
func getUserDetail(req *http.Request) (ud *models.UserDetail) {
if req.ContentLength > 0 {
if err := json.NewDecoder(req.Body).Decode(&ud); err != nil {
log.Println("error trying to decode user detail ", err)
return ud
}
}
log.Printf("User details [%v]", ud)
return ud
}

//Docode the http.Request parsing out the user details
func getGivenDetail(req *http.Request) (d map[string]string) {
if req.ContentLength > 0 {
if err := json.NewDecoder(req.Body).Decode(&d); err != nil {
log.Println("error trying to decode user detail ", err)
return nil
}
}
return d
}

// Extract the username and password from the authorization
// line of an HTTP header. This function will handle the
// parsing and decoding of the line.
func unpackAuth(authLine string) (usr *models.User, pw string) {
if authLine != "" {
parts := strings.SplitN(authLine, " ", 2)
payload := parts[1]
if decodedPayload, err := base64.URLEncoding.DecodeString(payload); err != nil {
log.Print("Error unpacking authorization header [%s]", err.Error())
} else {
details := strings.Split(string(decodedPayload), ":")
if details[0] != "" || details[1] != "" {
//Note the incoming `name` could infact be id, email or the username
return models.UserFromDetails(&models.UserDetail{Id: details[0], Name: details[0], Emails: []string{details[0]}}), details[1]
}
}
}
return nil, ""
}

func sendModelsAsRes(res http.ResponseWriter, models ...interface{}) {

res.Header().Set("content-type", "application/json")
res.WriteHeader(http.StatusOK)

res.Write([]byte("["))
for i := range models {
if jsonDetails, err := json.Marshal(models[i]); err != nil {
log.Println(err)
} else {
res.Write(jsonDetails)
}
}
res.Write([]byte("]"))
return
}

func sendModelAsRes(res http.ResponseWriter, model interface{}) {
sendModelAsResWithStatus(res, model, http.StatusOK)
return
}

func sendModelAsResWithStatus(res http.ResponseWriter, model interface{}, statusCode int) {
res.Header().Set("content-type", "application/json")
res.WriteHeader(statusCode)

if jsonDetails, err := json.Marshal(model); err != nil {
log.Println(err)
} else {
res.Write(jsonDetails)
}
return
}

func (a *Api) hasServerToken(tokenString string) bool {

if td := a.getUnpackedToken(tokenString); td != nil {
return td.IsServer
}
return false
}

//send metric
func (a *Api) logMetric(name, token string, params map[string]string) {
if token == "" {
log.Println("Missing token so couldn't log metric")
return
}
if params == nil {
params = make(map[string]string)
}
log.Printf("log metric name[%s] params[%v]", name, params)
//a.metrics.PostThisUser(name, token, params)
return
}

//send metric
func (a *Api) logMetricAsServer(name, token string, params map[string]string) {
if token == "" {
log.Println("Missing token so couldn't log metric")
return
}
if params == nil {
params = make(map[string]string)
}
log.Printf("log metric as server name[%s] params[%v]", name, params)
//a.metrics.PostServer(name, token, params)
return
}

//send metric
func (a *Api) logMetricForUser(id, name, token string, params map[string]string) {
if token == "" {
log.Println("Missing token so couldn't log metric")
return
}
if params == nil {
params = make(map[string]string)
}
log.Printf("log metric id[%s] name[%s] params[%v]", id, name, params)
//a.metrics.PostWithUser(id, name, token, params)
return
}

//get the token from the req header
func (a *Api) getUnpackedToken(tokenString string) *models.TokenData {
if st := models.GetSessionToken(tokenString); st.Id != "" {
if td := st.UnpackAndVerify(a.Config.Secret); td != nil && td.Valid == true {
return td
}
}
return nil
}

func (a *Api) addUserAndSendStatus(user *models.User, res http.ResponseWriter, req *http.Request) {
if err := a.Store.UpsertUser(user); err != nil {
log.Printf("addUserAndSendStatus %s err[%s]", STATUS_ERR_CREATING_USR, err.Error())
sendModelAsResWithStatus(res, status.NewStatus(http.StatusInternalServerError, STATUS_ERR_CREATING_USR), http.StatusInternalServerError)
return
}
if sessionToken, err := a.createAndSaveToken(tokenDuration(req), user.Id, false); err != nil {
log.Printf("addUserAndSendStatus %s err[%s]", STATUS_ERR_GENERATING_TOKEN, err.Error())
sendModelAsResWithStatus(res, status.NewStatus(http.StatusInternalServerError, STATUS_ERR_GENERATING_TOKEN), http.StatusInternalServerError)
return
} else {
a.logMetric("usercreated", sessionToken.Id, nil)
res.Header().Set(TP_SESSION_TOKEN, sessionToken.Id)
sendModelAsResWithStatus(res, user, http.StatusCreated)
return
}
}

func (a *Api) createAndSaveToken(dur float64, id string, isServer bool) (*models.SessionToken, error) {
sessionToken, _ := models.NewSessionToken(
&models.TokenData{
UserId: id,
IsServer: isServer,
DurationSecs: dur,
},
a.Config.Secret,
)

if err := a.Store.AddToken(sessionToken); err == nil {
return sessionToken, nil
} else {
return nil, err
}
}
Loading

0 comments on commit 7650361

Please sign in to comment.