diff --git a/apiV1login.go b/apiV1login.go index ed78c32..d78733f 100644 --- a/apiV1login.go +++ b/apiV1login.go @@ -2,6 +2,7 @@ package main import ( "biukop/sfm/loan" + "database/sql" log "github.com/sirupsen/logrus" "net/http" "time" @@ -21,23 +22,38 @@ func apiV1Login(w http.ResponseWriter, r *http.Request, ss *loan.Session) { l := login{} e := l.initRequest(r) - apiV1ErrorCheck(e) - - res.add("user", l.user) - res.add("pass", l.pass) - res.add("buser", l.buser) - res.add("bpass", l.bpass) - - bs := r.Header.Get("Biukop-Session") - bst := r.Header.Get("Biukop-Session-Token") - bse := r.Header.Get("Biukop-Session-Expire") - - res.add("bs", bs) - res.add("bse", bse) - res.add("bst", bst) + if e != nil { + log.Warn("Failed login - cannot analyze request " + e.Error()) + res.add("login", false) + res.add("reason", "incomplete request") + res.sendJson(w) + return + } + e = ss.Login(l.user, l.pass) + if e == sql.ErrNoRows { //not found + log.Warnf("Failed login - user not found %+v, error=%s", l, e.Error()) + res.add("login", false) + res.add("reason", "User not found") + res.sendJson(w) + return + } else if e != nil { + log.Warn("Failed login - cannot init session " + e.Error()) + res.add("login", false) + res.add("reason", "either user name or password is not right") + res.sendJson(w) + return + } + //log in user + ss.InitForUser(ss.User, time.Now().Add(loan.DefaultSessionDuration)) + res.add("auth", ss.Token) + res.add("session_id", ss.Id) + res.add("session_expire", ss.Expire.Format(time.RFC1123)) + res.add("session_user", ss.User) + res.add("buser", ss.User) + res.add("bpass", ss.CheckSum()) + //send out res.sendJson(w) - } func (m *login) initRequest(r *http.Request) (e error) { diff --git a/apiv1.go b/apiv1.go index 9c9a9a8..4cbc0c2 100644 --- a/apiv1.go +++ b/apiv1.go @@ -2,8 +2,13 @@ package main import ( "biukop/sfm/loan" + "database/sql" + "fmt" + log "github.com/sirupsen/logrus" "net/http" "net/http/httputil" + "strings" + "time" ) const apiV1Prefix = "/api/v1/" @@ -24,14 +29,27 @@ var apiV1Handler = []apiV1HandlerMap{ func apiV1Main(w http.ResponseWriter, r *http.Request) { logRequestDebug(httputil.DumpRequest(r, true)) w.Header().Set("Content-Type", "application/json;charset=UTF-8") - path := r.URL.Path[len(apiV1Prefix):] //strip API prefix - session := loan.Session{} - session.Retrieve(r) //TODO: check remote_addr changes in DB, to prevent possible Hack + //try session login first, if not an empty session will be created + session, e := apiV1InitSession(r) + if e != nil { + log.Warn("Fail to InitSession %+v", session) + apiV1ServerError(w, r) + return + } + session.RenewIfExpireSoon() + session.SetRemote(r) + //we have a session now, either guest or valid user + //search through handler + path := r.URL.Path[len(apiV1Prefix):] //strip API prefix for _, node := range apiV1Handler { if r.Method == node.Method && path == node.Path { node.Handler(w, r, &session) + e = session.Write() //finish this session to DB + if e != nil { + log.Warnf("Failed to Save Session %+v \n reason \n%s\n", session, e.Error()) + } return } } @@ -39,8 +57,39 @@ func apiV1Main(w http.ResponseWriter, r *http.Request) { apiV1DumpRequest(w, r, &session) } +func apiV1InitSession(r *http.Request) (session loan.Session, e error) { + session = loan.Session{} + sid := r.Header.Get("Biukop-Session") + e = session.Retrieve(r) + if e == nil { //we got existing session + e = session.ValidateRequest(r) + if e != nil { // not successfully validated + log.Warn("failed session login %+v, %s", session, time.Now().Format("RFC1132")) + } //else, we have logged this user in + } else if e == sql.ErrNoRows { + log.Warn("DB has no corresponding session ", sid) + session.InitGuest(time.Now().Add(loan.DefaultSessionDuration)) + e = nil //we try to init an empty one + } else { + log.Warn("Retrieve Session %s encountered error %s", sid, e.Error()) + } + session.SetRemote(r) //make sure they are using latest remote + return +} + func apiV1ErrorCheck(e error) { if nil != e { - panic(e.Error()) + panic(e.Error()) //TODO: detailed error check, truck all caller } } + +func apiV1ServerError(w http.ResponseWriter, r *http.Request) { + + w.WriteHeader(500) + fmt.Fprintf(w, "Server Internal Error "+time.Now().Format("RFC1132")) + + //write log + dump := logRequestDebug(httputil.DumpRequest(r, true)) + dump = strings.TrimSpace(dump) + log.Warn("Unhandled Protocol = %s path= %s", r.Method, r.URL.Path) +}