Example #1
0
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
}
Example #2
0
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
}
Example #3
0
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
}
Example #5
0
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)
	}
}
Example #7
0
func main() {
	u, err := uuid.ParseHex("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(u)
}
Example #8
0
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)
	}

}
Example #9
0
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)
		}
	}()
}
Example #10
0
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
}
Example #11
0
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
}
Example #14
0
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
}
Example #15
0
// 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)
	}
}
Example #16
0
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
	}
}
Example #17
0
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
}
Example #18
0
// 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
}