Exemple #1
0
func Login(ctx *rpc.Context, req *LoginInfo) (string, error) {
	if req.Login == "" {
		return "", ErrEmptyLogin
	}
	if req.Passphrase == "" {
		return "", ErrEmptyPassphrase
	}
	var loginID int64
	if strings.Contains(req.Login, "@") {
		email := strings.ToLower(req.Login)
		var meta db.LoginEmail
		err := ctx.Get(ctx.StrKey("LE", email, nil), &meta)
		if err != nil {
			if err == datastore.ErrNoSuchEntity {
				return "", ErrInvalidLogin
			}
			return "", err
		}
		loginID = meta.Login
	} else {
		username, ok := ident.Username(req.Login)
		if !ok {
			return "", ErrInvalidLogin
		}
		var meta db.LoginUsername
		err := ctx.Get(ctx.StrKey("LU", username, nil), &meta)
		if err != nil {
			if err == datastore.ErrNoSuchEntity {
				return "", ErrInvalidLogin
			}
			return "", err
		}
		loginID = meta.Login
	}
	var login db.Login
	loginKey := ctx.IntKey("L", loginID, nil)
	err := ctx.Get(loginKey, &login)
	if err != nil {
		if err == datastore.ErrNoSuchEntity {
			return "", ErrInvalidLogin
		}
		return "", err
	}
	s := login.Scrypt
	derived, err := scrypt.Key([]byte(req.Passphrase), s.Salt, s.Iterations, s.BlockSize, s.Parallelisation, s.Length)
	if err != nil {
		return "", err
	}
	if subtle.ConstantTimeCompare(derived, login.Passphrase) != 1 {
		return "", ErrInvalidLogin
	}
	now := datetime.UTC()
	sess := &db.Session{
		Client:     req.Client,
		Expires:    datetime.From(now.Add(time.Hour)),
		Initiated:  now,
		RememberMe: req.RememberMe,
	}
	key, err := ctx.Put(ctx.NewKey("S", loginKey), sess)
	if err != nil {
		return "", err
	}
	return session.Encode(login.Username, string(sess.Expires)[1:], loginKey.IntID(), key.IntID()), nil
}