fleet/server/service_sessions.go
Zachary Wasserman 885db1a597 Refactoring for config patterns (#159)
This PR refactors most of the codebase to use the new config patterns implemented in #149. Now the core service keeps a copy of the KolideConfig struct, and service methods can reference the configuration in that struct when they need it. The most significant refactoring is in the sessions code, separating the business logic from the storage layer.
2016-09-14 09:11:06 -07:00

164 lines
3.6 KiB
Go

package server
import (
"crypto/rand"
"encoding/base64"
"fmt"
"time"
"github.com/kolide/kolide-ose/datastore"
"github.com/kolide/kolide-ose/kolide"
"golang.org/x/net/context"
)
func (svc service) Login(ctx context.Context, username, password string) (*kolide.User, string, error) {
user, err := svc.ds.User(username)
switch err {
case nil:
case datastore.ErrNotFound:
return nil, "", authError{
message: fmt.Sprintf("user %s not found", username),
}
default:
return nil, "", err
}
if !user.Enabled {
return nil, "", authError{
message: fmt.Sprintf("account disabled %s", username),
}
}
if err := user.ValidatePassword(password); err != nil {
return nil, "", authError{
message: fmt.Sprintf("invalid password for user %s", username),
}
}
token, err := svc.makeSession(user.ID)
if err != nil {
return nil, "", err
}
return user, token, nil
}
// makeSession is a helper that creates a new session after authentication
func (svc service) makeSession(id uint) (string, error) {
sessionKeySize := svc.config.Session.KeySize
key := make([]byte, sessionKeySize)
_, err := rand.Read(key)
if err != nil {
return "", err
}
session := &kolide.Session{
UserID: id,
Key: base64.StdEncoding.EncodeToString(key),
}
session, err = svc.ds.NewSession(session)
if err != nil {
return "", err
}
tokenString, err := kolide.GenerateJWT(session.Key, svc.config.Auth.JwtKey)
if err != nil {
return "", err
}
return tokenString, nil
}
func (svc service) Logout(ctx context.Context) error {
// this should not return an error if the user wasn't logged in
return svc.DestroySession(ctx)
}
func (svc service) DestroySession(ctx context.Context) error {
vc, err := viewerContextFromContext(ctx)
if err != nil {
return err
}
session, err := svc.ds.FindSessionByID(vc.SessionID())
if err != nil {
return err
}
return svc.ds.DestroySession(session)
}
func (svc service) GetInfoAboutSessionsForUser(ctx context.Context, id uint) ([]*kolide.Session, error) {
var validatedSessions []*kolide.Session
sessions, err := svc.ds.FindAllSessionsForUser(id)
if err != nil {
return validatedSessions, err
}
for _, session := range sessions {
if svc.validateSession(session) == nil {
validatedSessions = append(validatedSessions, session)
}
}
return validatedSessions, nil
}
func (svc service) DeleteSessionsForUser(ctx context.Context, id uint) error {
return svc.ds.DestroyAllSessionsForUser(id)
}
func (svc service) GetInfoAboutSession(ctx context.Context, id uint) (*kolide.Session, error) {
session, err := svc.ds.FindSessionByID(id)
if err != nil {
return nil, err
}
err = svc.validateSession(session)
if err != nil {
return nil, err
}
return session, nil
}
func (svc service) GetSessionByKey(ctx context.Context, key string) (*kolide.Session, error) {
session, err := svc.ds.FindSessionByKey(key)
if err != nil {
return nil, err
}
err = svc.validateSession(session)
if err != nil {
return nil, err
}
return session, nil
}
func (svc service) DeleteSession(ctx context.Context, id uint) error {
session, err := svc.ds.FindSessionByID(id)
if err != nil {
return err
}
return svc.ds.DestroySession(session)
}
func (svc service) validateSession(session *kolide.Session) error {
if session == nil {
return kolide.ErrNoActiveSession
}
sessionDuration := svc.config.Session.Duration
// duration 0 = unlimited
if sessionDuration != 0 && time.Since(session.AccessedAt) >= sessionDuration {
err := svc.ds.DestroySession(session)
if err != nil {
return err
}
return kolide.ErrSessionExpired
}
return svc.ds.MarkSessionAccessed(session)
}