func NewHttpStartStop(req *http.Request, statusCode int, contentLength int64, peerType events.PeerType, requestId *uuid.UUID) *events.HttpStartStop { now := proto.Int64(time.Now().UnixNano()) httpStartStop := &events.HttpStartStop{ StartTimestamp: now, StopTimestamp: now, RequestId: NewUUID(requestId), PeerType: &peerType, Method: events.Method(events.Method_value[req.Method]).Enum(), Uri: proto.String(fmt.Sprintf("%s://%s%s", scheme(req), req.Host, req.URL.Path)), RemoteAddress: proto.String(req.RemoteAddr), UserAgent: proto.String(req.UserAgent()), StatusCode: proto.Int(statusCode), ContentLength: proto.Int64(contentLength), } if applicationId, err := uuid.ParseHex(req.Header.Get("X-CF-ApplicationID")); err == nil { httpStartStop.ApplicationId = NewUUID(applicationId) } if instanceIndex, err := strconv.Atoi(req.Header.Get("X-CF-InstanceIndex")); err == nil { httpStartStop.InstanceIndex = proto.Int(instanceIndex) } if instanceId := req.Header.Get("X-CF-InstanceID"); instanceId != "" { httpStartStop.InstanceId = proto.String(instanceId) } allForwards := req.Header[http.CanonicalHeaderKey("X-Forwarded-For")] for _, forwarded := range allForwards { httpStartStop.Forwarded = append(httpStartStop.Forwarded, parseXForwarded(forwarded)...) } return httpStartStop }
func NewHttpStart(req *http.Request, peerType events.PeerType, requestId *uuid.UUID) *events.HttpStart { httpStart := &events.HttpStart{ Timestamp: proto.Int64(time.Now().UnixNano()), RequestId: NewUUID(requestId), PeerType: &peerType, Method: events.HttpStart_Method(events.HttpStart_Method_value[req.Method]).Enum(), Uri: proto.String(fmt.Sprintf("%s%s", req.Host, req.URL.Path)), RemoteAddress: proto.String(req.RemoteAddr), UserAgent: proto.String(req.UserAgent()), } if applicationId, err := uuid.ParseHex(req.Header.Get("X-CF-ApplicationID")); err == nil { httpStart.ApplicationId = NewUUID(applicationId) } if instanceIndex, err := strconv.Atoi(req.Header.Get("X-CF-InstanceIndex")); err == nil { httpStart.InstanceIndex = proto.Int(instanceIndex) } if instanceId := req.Header.Get("X-CF-InstanceID"); instanceId != "" { httpStart.InstanceId = &instanceId } return httpStart }
func (this *UdpSessionList) PushMsg(did int64, msg []byte) error { sid, err := GetDeviceSid(did) if err != nil { return fmt.Errorf("[udp:err] get session of device [%d] error: %v", did, err) } locker := NewDeviceSessionLocker(sid) err = locker.Lock() if err != nil { return fmt.Errorf("lock session id [%s] failed: %v", sid, err) } defer locker.Unlock() i, err := uuid.ParseHex(sid) if err != nil { return fmt.Errorf("wrong session id format: %v", err) } sess, err := this.GetSession(i) if err != nil { return fmt.Errorf("get session %s error: %v", sid, err) } sess.Sidx++ binary.LittleEndian.PutUint16(msg[2:4], sess.Sidx) copy(msg[FrameHeaderLen:FrameHeaderLen+kSidLen], i[:]) //hcIndex := FrameHeaderLen + kSidLen + FrameHeaderLen + kHeaderCheckPosInDataHeader //glog.Infoln("PushMsg----------sess:", sess) //msg[hcIndex] = msgs.ChecksumHeader(msg, hcIndex) //glog.Infoln("PushMsg:",did,len(msg),msg,hcIndex) this.server.Send(sess.Addr, msg) this.SaveSession(i, sess) return nil }
/* Wraps the RoundTrip function of the given RoundTripper. Will provide accounting metrics for the http.Request / http.Response life-cycle Callers of RoundTrip are responsible for setting the ‘X-CF-RequestID’ field in the request header if they have one. Callers are also responsible for setting the ‘X-CF-ApplicationID’ and ‘X-CF-InstanceIndex’ fields in the request header if they are known. */ func (irt *instrumentedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { requestId, err := GenerateUuid() if err != nil { log.Printf("failed to generated request ID: %v\n", err) requestId = &uuid.UUID{} } startTime := time.Now() parentRequestId := req.Header.Get("X-CF-RequestID") req.Header.Set("X-CF-RequestID", requestId.String()) resp, roundTripErr := irt.roundTripper.RoundTrip(req) var statusCode int var contentLength int64 if roundTripErr == nil { statusCode = resp.StatusCode contentLength = resp.ContentLength } httpStartStop := factories.NewHttpStartStop(req, statusCode, contentLength, events.PeerType_Client, requestId) if parentRequestId != "" { if id, err := uuid.ParseHex(parentRequestId); err == nil { httpStartStop.ParentRequestId = factories.NewUUID(id) } } httpStartStop.StartTimestamp = proto.Int64(startTime.UnixNano()) err = irt.emitter.Emit(httpStartStop) if err != nil { log.Printf("failed to emit startstop event: %v\n", err) } return resp, roundTripErr }
func (this *UdpSessionList) PushCommonMsg(msgId uint16, did int64, msgBody []byte) error { msg := msgs.NewMsg(msgBody, nil) msg.FrameHeader.Opcode = 2 msg.DataHeader.MsgId = msgId msg.FrameHeader.DstId = did sid, err := GetDeviceSid(did) if err != nil { return fmt.Errorf("[udp:err] get session of device [%d] error: %v", did, err) } locker := NewDeviceSessionLocker(sid) err = locker.Lock() if err != nil { return fmt.Errorf("[udp:err] lock session id [%s] failed: %v", sid, err) } defer locker.Unlock() i, err := uuid.ParseHex(sid) if err != nil { return fmt.Errorf("[udp:err] wrong session id format: %v", err) } sess, err := this.GetSession(i) if err != nil { return fmt.Errorf("[udp:err] get session %s error: %v", sid, err) } sess.Sidx++ msg.FrameHeader.Sequence = sess.Sidx msgBytes := msg.MarshalBytes() this.server.Send(sess.Addr, msgBytes) this.SaveSession(i, sess) return nil }
/* Wraps the given http.Handler ServerHTTP function Will provide accounting metrics for the http.Request / http.Response life-cycle */ func (ih *instrumentedHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { requestId, err := uuid.ParseHex(req.Header.Get("X-Vcap-Request-Id")) if err != nil { requestId, err = GenerateUuid() if err != nil { log.Printf("failed to generated request ID: %v\n", err) requestId = &uuid.UUID{} } req.Header.Set("X-Vcap-Request-Id", requestId.String()) } rw.Header().Set("X-Vcap-Request-Id", requestId.String()) startTime := time.Now() instrumentedWriter := &instrumentedResponseWriter{writer: rw, statusCode: 200} ih.handler.ServeHTTP(instrumentedWriter, req) startStopEvent := factories.NewHttpStartStop(req, instrumentedWriter.statusCode, instrumentedWriter.contentLength, events.PeerType_Server, requestId) startStopEvent.StartTimestamp = proto.Int64(startTime.UnixNano()) err = ih.emitter.Emit(startStopEvent) if err != nil { log.Printf("failed to emit startstop event: %v\n", err) } }
func main() { u, err := uuid.ParseHex("6ba7b810-9dad-11d1-80b4-00c04fd430c8") if err != nil { fmt.Println("error:", err) return } fmt.Println(u) }
func main() { fmt.Print("hello, world\n") ID, err := uuid.ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8") fmt.Println(ID) if err != nil { fmt.Println(err) } }
func (this *UdpSessionList) UpdateIds(deviceId int64, userId int64, bindType bool) { sid, err := GetDeviceSid(deviceId) if err != nil { glog.Errorf("get session of device [%d] error: %v", deviceId, err) return } locker := NewDeviceSessionLocker(sid) err = locker.Lock() if err != nil { glog.Errorf("lock session id [%s] failed: %v", sid, err) return } defer locker.Unlock() i, err := uuid.ParseHex(sid) if err != nil { glog.Errorf("wrong session id format: %v", err) return } sess, err := this.GetSession(i) if err != nil { glog.Errorf("get session %s error: %v", sid, err) return } if bindType { // 绑定 sess.BindedUsers = append(sess.BindedUsers, userId) glog.Infof("[bind|bind] deviceId %d add userId %d", deviceId, userId) } else { // 解绑 for k, v := range sess.BindedUsers { if v != userId { continue } lastIndex := len(sess.BindedUsers) - 1 sess.BindedUsers[k] = sess.BindedUsers[lastIndex] sess.BindedUsers = sess.BindedUsers[:lastIndex] glog.Infof("[bind|unbind] deviceId %d remove userId %d", deviceId, userId) break } } this.SaveSession(i, sess) go func() { mids := TransId(userId) if bindType { GMsgBusManager.NotifyBindedIdChanged(deviceId, mids, nil) } else { GMsgBusManager.NotifyBindedIdChanged(deviceId, nil, mids) } }() }
func NewHttpStop(req *http.Request, statusCode int, contentLength int64, peerType events.PeerType, requestId *uuid.UUID) *events.HttpStop { httpStop := &events.HttpStop{ Timestamp: proto.Int64(time.Now().UnixNano()), Uri: proto.String(fmt.Sprintf("%s%s", req.Host, req.URL.Path)), RequestId: NewUUID(requestId), PeerType: &peerType, StatusCode: proto.Int(statusCode), ContentLength: proto.Int64(contentLength), } if applicationId, err := uuid.ParseHex(req.Header.Get("X-CF-ApplicationID")); err == nil { httpStop.ApplicationId = NewUUID(applicationId) } return httpStop }
func (csi *ClearSessionId) EncryptToken() (SessionId string, err error) { // validate the session token by parsing it _, err = uuid.ParseHex(csi.SessionToken) if err != nil { err = fmt.Errorf("SessionToken (%s) is not a UUID", csi.SessionToken) return "", err } if csi.Salt == "" { err = fmt.Errorf("Salt is missing") return "", err } if len(csi.Salt) != 64 { err = fmt.Errorf("Salt must be 32 bytes but was %d bytes", len(csi.Salt)/2) return "", err } // scrypt is slow and good for passwords // sha512 is faster and good for sessions saltBytes, err := hex.DecodeString(csi.Salt) if err != nil { glog.Errorf("Undecodable salt (%s)", csi.Salt) return "", err } combined := make([]byte, 64+32+36) _ = copy(combined[0:64], Conf.ServerKey) _ = copy(combined[64:96], saltBytes) _ = copy(combined[96:], []byte(csi.SessionToken)) sum512 := sha512.Sum512(combined) SessionId = hex.EncodeToString(sum512[:]) return SessionId, nil }
/* Wraps the RoundTrip function of the given RoundTripper. Will provide accounting metrics for the http.Request / http.Response life-cycle Callers of RoundTrip are responsible for setting the ‘X-CF-RequestID’ field in the request header if they have one. Callers are also responsible for setting the ‘X-CF-ApplicationID’ and ‘X-CF-InstanceIndex’ fields in the request header if they are known. */ func (irt *instrumentedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { requestId, err := GenerateUuid() if err != nil { log.Printf("failed to generated request ID: %v\n", err) requestId = &uuid.UUID{} } httpStart := factories.NewHttpStart(req, events.PeerType_Client, requestId) parentRequestId, err := uuid.ParseHex(req.Header.Get("X-CF-RequestID")) if err == nil { httpStart.ParentRequestId = factories.NewUUID(parentRequestId) } req.Header.Set("X-CF-RequestID", requestId.String()) err = irt.emitter.Emit(httpStart) if err != nil { log.Printf("failed to emit start event: %v\n", err) } resp, roundTripErr := irt.roundTripper.RoundTrip(req) var httpStop *events.HttpStop if roundTripErr != nil { httpStop = factories.NewHttpStop(req, 0, 0, events.PeerType_Client, requestId) } else { httpStop = factories.NewHttpStop(req, resp.StatusCode, resp.ContentLength, events.PeerType_Client, requestId) } err = irt.emitter.Emit(httpStop) if err != nil { log.Printf("failed to emit stop event: %v\n", err) } return resp, roundTripErr }
/* RoundTrip wraps the RoundTrip function of the given RoundTripper. Will provide accounting metrics for the http.Request / http.Response life-cycle Callers of RoundTrip are responsible for setting the ‘X-Vcap-Request-Id’ field in the request header if they have one. Callers are also responsible for setting the ‘X-CF-ApplicationID’ and ‘X-CF-InstanceIndex’ fields in the request header if they are known. */ func (irt *instrumentedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { startTime := time.Now() requestId := req.Header.Get("X-Vcap-Request-Id") if requestId == "" { requestIdGuid, err := uuid.NewV4() if err != nil { return nil, err } requestId = requestIdGuid.String() } req.Header.Set("X-Vcap-Request-Id", requestId) resp, roundTripErr := irt.roundTripper.RoundTrip(req) var statusCode int var contentLength int64 if roundTripErr == nil { statusCode = resp.StatusCode contentLength = resp.ContentLength } id, err := uuid.ParseHex(requestId) if err != nil { return nil, err } httpStartStop := factories.NewHttpStartStop(req, statusCode, contentLength, events.PeerType_Client, id) httpStartStop.StartTimestamp = proto.Int64(startTime.UnixNano()) err = irt.emitter.Emit(httpStartStop) if err != nil { log.Printf("failed to emit startstop event: %v\n", err) } return resp, roundTripErr }
func (this *UdpSessionList) GetDeviceAddr(id int64) (string, error) { glog.Infoln("GetDeviceAddr ", id) sid, err := GetDeviceSid(id) if err != nil { return "", fmt.Errorf("get session of device [%d] error: %v", id, err) } locker := NewDeviceSessionLocker(sid) err = locker.Lock() if err != nil { return "", fmt.Errorf("lock session id [%s] failed: %v", sid, err) } defer locker.Unlock() i, err := uuid.ParseHex(sid) if err != nil { return "", fmt.Errorf("wrong session id format: %v", err) } sess, err := this.GetSession(i) if err != nil { return "", fmt.Errorf("get session %s error: %v", sid, err) } return sess.Addr.String(), nil }
// useResetToken creates a login session and returns the session cookies so that a user can change their password, for valid reset tokens only (also verifies email address) func useResetToken(rw http.ResponseWriter, req *http.Request) { localPrefix := fmt.Sprintf("useReset-%s:", context.Get(req, RequestLogIdKey)) if glog.V(2) { glog.Infof("%s handling begins: %s (%d bytes)", localPrefix, req.URL, req.ContentLength) } vars := mux.Vars(req) inEmailAddr := strings.TrimSpace(strings.ToLower(vars["EmailAddr"])) inResetToken := vars["Token"] response := DefaultLoginResponse(localPrefix) response.ValidationResult.Message = "Reset failed" var err error defer func() { // encode response to json and write the response setSessionCookies(rw, response) enc := json.NewEncoder(rw) rw.Header().Add("Content-Type", "application/json") err = enc.Encode(response) if err != nil { glog.Errorf("%s Failed to encode response into json", localPrefix) } if glog.V(2) { glog.Infof("%s handling ends with result message: %s", localPrefix, response.ValidationResult.Message) } glog.Flush() }() // check if email matches the pattern if isMatched, _ := regexp.MatchString(emailRegex, inEmailAddr); !isMatched { response.ValidationResult.PropInError = "EmailAddr" response.ValidationResult.PropErrorMsg = "Not a valid email address" return } // validate the token by parsing it _, err = uuid.ParseHex(inResetToken) if err != nil { response.ValidationResult.PropInError = "ResetToken" response.ValidationResult.PropErrorMsg = "Not a valid reset token" return } // fetch the user userRow, err := SelectUser(inEmailAddr) if err != nil { if glog.V(2) { glog.Infof("%s SelectUser err: %s", localPrefix, err) } return } // token in db must be there (obviously) if userRow.reset_token == "" { if glog.V(2) { glog.Infof("%s No reset token in database", localPrefix) } return } // token must be active not expired (if reset_token is not blank then reset_expires should // be a valid timestamp, so no need to check that) if userRow.reset_expires.Before(time.Now()) { if glog.V(2) { glog.Infof("%s Reset token is expired", localPrefix) } return } // Check if login allowed if !userRow.login_allowed { if glog.V(2) { glog.Infof("%s login_allowed is false", localPrefix) } return } // tokens must match cryptToken, err := encryptResetToken(inResetToken, userRow.SysUserId) if err != nil { if glog.V(2) { glog.Infof("%s encryptResetToken err: %s", localPrefix, err) } return } if cryptToken != userRow.reset_token { if glog.V(2) { glog.Infof("%s Given token does not match the token on record", localPrefix) } return } if err = userRow.RemoveResetToken(); err != nil { if glog.V(2) { glog.Infof("%s RemoveResetToken err: %s", localPrefix, err) } return } // according to doc req.RemoteAddr has no defined format. we assume the first part to : is IP addr suppliedIP := req.RemoteAddr[:strings.Index(req.RemoteAddr, ":")] // Create a new session var sr = new(SessionDbRow) sr.SysUserId = userRow.SysUserId sr.IpAddr = suppliedIP sr.UserAgent = req.Header.Get("User-Agent") csi, err := sr.InsertSession() if err != nil { response.ValidationResult.Message = "System error prevented session token creation" return } response.SessionToken = csi.SessionToken response.Salt = csi.Salt response.setUserData(*userRow) response.ValidationResult.Message = "Reset request is valid" response.ValidationResult.Status = StatusOK if glog.V(1) { glog.Infof("%s Reset request is valid for email %s (SysUserId %s)", localPrefix, inEmailAddr, response.SysUserId) } }
func verifyEmail(rw http.ResponseWriter, req *http.Request) { localPrefix := fmt.Sprintf("verifyEmail-%s:", context.Get(req, RequestLogIdKey)) if glog.V(2) { glog.Infof("%s handling begins: %s (%d bytes)", localPrefix, req.URL, req.ContentLength) } vars := mux.Vars(req) var response VerifyResponse response.EmailAddr = strings.TrimSpace(strings.ToLower(vars["EmailAddr"])) response.Token = vars["Token"] response.ValidationResult.Message = "Verification failed" response.ValidationResult.Status = StatusInvalid response.ValidationResult.SystemRef = localPrefix var err error defer func() { // encode response to json and write the response enc := json.NewEncoder(rw) rw.Header().Add("Content-Type", "application/json") err = enc.Encode(response) if err != nil { glog.Errorf("%s Failed to encode response into json", localPrefix) } if glog.V(2) { glog.Infof("%s handling ends with result message: %s", localPrefix, response.ValidationResult.Message) } glog.Flush() }() // check if email matches the pattern if isMatched, _ := regexp.MatchString(emailRegex, response.EmailAddr); !isMatched { response.ValidationResult.PropInError = "EmailAddr" response.ValidationResult.PropErrorMsg = "Not a valid email address" return } // validate the token by parsing it _, err = uuid.ParseHex(response.Token) if err != nil { response.ValidationResult.PropInError = "Token" response.ValidationResult.PropErrorMsg = "Not a valid token" return } // check the database const sql = "update session.user set verify_token = null, EmailVerified = true where EmailAddr = $1 and verify_token = $2" result, err := Conf.DatabaseHandle.Exec(sql, response.EmailAddr, response.Token) if err != nil { if glog.V(2) { glog.Infof("%s Attempt to verify failed: %s", localPrefix, err) } return } rows, err := result.RowsAffected() if err != nil { glog.Errorf("%s Error while calling RowsAffected: %s", localPrefix, err) return } if rows > 0 { if glog.V(1) { glog.Infof("%s Email verification of %s. (%d rows updated)", localPrefix, response.EmailAddr, rows) } response.ValidationResult.Message = "Verification successful" response.ValidationResult.Status = StatusOK } }
func validUserRequest(uReq *UserRequest, doingInsert bool, givenSysUserId string, vResult *Result) bool { var err error uReq.EmailAddr = strings.TrimSpace(uReq.EmailAddr) uReq.EmailAddr = strings.ToLower(uReq.EmailAddr) uReq.UserId = strings.TrimSpace(uReq.UserId) uReq.UserId = strings.ToLower(uReq.UserId) uReq.FirstName = strings.TrimSpace(uReq.FirstName) uReq.LastName = strings.TrimSpace(uReq.LastName) uReq.TzName = strings.TrimSpace(uReq.TzName) if !doingInsert { _, err = uuid.ParseHex(uReq.SysUserId) if err != nil { vResult.PropInError = "SysUserId" vResult.PropErrorMsg = "Not a valid UUID" return false } _, err = uuid.ParseHex(givenSysUserId) if err != nil { vResult.PropInError = "SysUserId" vResult.PropErrorMsg = "Not a valid UUID in URL" return false } if uReq.SysUserId != givenSysUserId { vResult.PropInError = "SysUserId" vResult.PropErrorMsg = "Does not match UUID in URL" return false } } if uReq.EmailAddr == "" { vResult.PropInError = "EmailAddr" vResult.PropErrorMsg = "Missing data" return false } if isMatched, _ := regexp.MatchString(emailRegex, uReq.EmailAddr); !isMatched { vResult.PropInError = "EmailAddr" vResult.PropErrorMsg = "Not a valid email address" return false } if uReq.UserId == "" { vResult.PropInError = "UserId" vResult.PropErrorMsg = "Missing data" return false } if strings.Index(uReq.UserId, "@") >= 0 && uReq.UserId != uReq.EmailAddr { vResult.PropInError = "UserId" vResult.PropErrorMsg = "Must match email address if it contains @" return false } if uReq.FirstName == "" { vResult.PropInError = "FirstName" vResult.PropErrorMsg = "Missing data" return false } if uReq.LastName == "" { vResult.PropInError = "LastName" vResult.PropErrorMsg = "Missing data" return false } if uReq.TzName == "" { vResult.PropInError = "TzName" vResult.PropErrorMsg = "Missing data" return false } if doingInsert || uReq.ClearPassword != "" || uReq.ConfirmPassword != "" { if uReq.ClearPassword == "" { vResult.PropInError = "ClearPassword" vResult.PropErrorMsg = "Missing data" return false } if len(uReq.ClearPassword) < 10 { vResult.PropInError = "ClearPassword" vResult.PropErrorMsg = "Too short, at least 10 chars" return false } if uReq.ConfirmPassword == "" { vResult.PropInError = "ConfirmPassword" vResult.PropErrorMsg = "Missing data" return false } if uReq.ConfirmPassword != uReq.ClearPassword { vResult.PropInError = "ConfirmPassword" vResult.PropErrorMsg = "Passwords did not match" return false } } // lookup TzName const tzLookupSql = `select count(*) as cnt from pg_timezone_names where left(name,5) != 'posix' and left(name,3) != 'Etc' and length(name) > 3 and left(name,3) != 'US/' and left(name,3) != 'GMT' and name = $1` var count int err = Conf.DatabaseHandle.QueryRow(tzLookupSql, uReq.TzName).Scan(&count) switch { case err == sql.ErrNoRows: { vResult.PropInError = "TzName" vResult.PropErrorMsg = "System error" return false } case err != nil: { vResult.PropInError = "TzName" vResult.PropErrorMsg = fmt.Sprintf("System error %s", err) glog.Errorf("Error while executing %s\n($1=%s)\nerr=%s", tzLookupSql, uReq.TzName, err) return false } default: { if count == 0 { vResult.PropInError = "TzName" vResult.PropErrorMsg = "Invalid time zone name" return false } } } // verify EmailAddr unique lookupSql := "select count(*) as cnt from session.user where EmailAddr = $1 and SysUserId != $2" err = Conf.DatabaseHandle.QueryRow(lookupSql, uReq.EmailAddr, uReq.SysUserId).Scan(&count) switch { case err == sql.ErrNoRows: { vResult.PropInError = "EmailAddr" vResult.PropErrorMsg = "System error" return false } case err != nil: { vResult.PropInError = "EmailAddr" vResult.PropErrorMsg = fmt.Sprintf("System error %s", err) glog.Errorf("Error while executing %s\n($1=%s)\nerr=%s", lookupSql, uReq.EmailAddr, err) return false } default: { if count > 0 { vResult.PropInError = "EmailAddr" vResult.PropErrorMsg = "Already associated with a user" return false } } } // verify UserId unique lookupSql = "select count(*) as cnt from session.user where UserId = $1 and SysUserId != $2" err = Conf.DatabaseHandle.QueryRow(lookupSql, uReq.UserId, uReq.SysUserId).Scan(&count) switch { case err == sql.ErrNoRows: { vResult.PropInError = "UserId" vResult.PropErrorMsg = "System error" return false } case err != nil: { vResult.PropInError = "UserId" vResult.PropErrorMsg = fmt.Sprintf("System error %s", err) glog.Errorf("Error while executing %s\n($1=%s)\nerr=%s", lookupSql, uReq.UserId, err) return false } default: { if count > 0 { vResult.PropInError = "UserId" vResult.PropErrorMsg = "Not available" return false } } } return true }
// SelectUser attempts to read a session.user from the database, it interprets UserIdentifier in three different ways, as a SysUserId, EmailAddr or UserId. It returns an error if not found and a db row otherwise. func SelectUser(UserIdentifier string) (rw *UserDbRow, err error) { rw = new(UserDbRow) var nullable UserNullables const sqlfmt = `SELECT SysUserId, EmailAddr, EmailVerified, verify_token, UserId, pw_salt, pw_crypt, FirstName, LastName, created_dt, login_allowed, reset_token, reset_expires, TzName FROM session.user WHERE %s = $1` // UserIdentifier is not SysUserId if it does not parse as a uuid _, err = uuid.ParseHex(UserIdentifier) if err == nil { // 1. try by SysUserId err = Conf.DatabaseHandle.QueryRow(fmt.Sprintf(sqlfmt, "SysUserId"), UserIdentifier).Scan( &rw.SysUserId, &rw.EmailAddr, &rw.EmailVerified, &nullable.verify_token, &rw.UserId, &rw.pw_salt, &rw.pw_crypt, &rw.FirstName, &rw.LastName, &rw.created_dt, &rw.login_allowed, &nullable.reset_token, &nullable.reset_expires, &rw.TzName) if err == nil { rw.SetNullables(nullable) return rw, err } else if err != sql.ErrNoRows { glog.Errorf("SelectUser failed: %s", err) return nil, err } } // UserIdentifier is not EmailAddr if it does not contain @ if strings.Index(UserIdentifier, "@") < 0 { // 2. try by UserId err = Conf.DatabaseHandle.QueryRow(fmt.Sprintf(sqlfmt, "UserId"), UserIdentifier).Scan( &rw.SysUserId, &rw.EmailAddr, &rw.EmailVerified, &nullable.verify_token, &rw.UserId, &rw.pw_salt, &rw.pw_crypt, &rw.FirstName, &rw.LastName, &rw.created_dt, &rw.login_allowed, &nullable.reset_token, &nullable.reset_expires, &rw.TzName) if err == nil { rw.SetNullables(nullable) return rw, err } else if err != sql.ErrNoRows { glog.Errorf("SelectUser failed: %s", err) return nil, err } } // 3. try by EmailAddr err = Conf.DatabaseHandle.QueryRow(fmt.Sprintf(sqlfmt, "EmailAddr"), UserIdentifier).Scan( &rw.SysUserId, &rw.EmailAddr, &rw.EmailVerified, &nullable.verify_token, &rw.UserId, &rw.pw_salt, &rw.pw_crypt, &rw.FirstName, &rw.LastName, &rw.created_dt, &rw.login_allowed, &nullable.reset_token, &nullable.reset_expires, &rw.TzName) if err == nil { rw.SetNullables(nullable) return rw, err } else if err != sql.ErrNoRows { glog.Errorf("SelectUser failed: %s", err) return nil, err } return }