<commit_before>package stack

import (
	"koding/db/models"
	"koding/db/mongodb/modelhelper"

	"github.com/koding/kite"
)

// LoginRequest represents a request model for "auth.login"
// kloud's kite method.
type LoginRequest struct {
	// GroupName is a team name, which we're going to log in to.
	//
	// If empty, default team is going to be used
	// instead and its name can be read from response value.
	GroupName string `json:"groupName"`
}

// LoginResponse represents a response model for "auth.login"
// kloud's kite method.
type LoginResponse struct {
	// ClientID represents a session ID used for
	// authentication with remote.api and Social API.
	ClientID string `json:"clientID"`

	// GroupName is a team name, which we have just logged in to.
	GroupName string `json:"groupName"`
}

// Pinger send ping requests for presence.
type Pinger interface {
	Ping(string, string) error
}

// AuthLogin creates a jSession for the given username and team.
//
// If a session already exists, the method is a nop and returns
// already existing one.
//
// TODO(rjeczalik): Add AuthLogout to force creation of a new
// session.
func (k *Kloud) AuthLogin(p Pinger) func(r *kite.Request) (interface{}, error) {
	return func(r *kite.Request) (interface{}, error) {
		k.Log.Debug("auth login called by %q with %q", r.Username, r.Args.Raw)

		req, err := getLoginReq(r)
		if err != nil {
			return nil, err
		}

		ses, err := modelhelper.UserLogin(r.Username, req.GroupName)
		if err != nil {
			return nil, NewError(ErrInternalServer)
		}

		if err := p.Ping(r.Username, req.GroupName); err != nil {
			// we dont need to block user login if there is something wrong with socialapi.
			k.Log.Error("sendPresenceRequest failed with & for", err.Error(), r.Username)
		}<commit_msg>kloud/stack: add better error handling & logging<commit_after>package stack

import (
	"koding/db/models"
	"koding/db/mongodb/modelhelper"

	mgo "gopkg.in/mgo.v2"

	"github.com/koding/kite"
)

// LoginRequest represents a request model for "auth.login"
// kloud's kite method.
type LoginRequest struct {
	// GroupName is a team name, which we're going to log in to.
	//
	// If empty, default team is going to be used
	// instead and its name can be read from response value.
	GroupName string `json:"groupName"`
}

// LoginResponse represents a response model for "auth.login"
// kloud's kite method.
type LoginResponse struct {
	// ClientID represents a session ID used for
	// authentication with remote.api and Social API.
	ClientID string `json:"clientID"`

	// GroupName is a team name, which we have just logged in to.
	GroupName string `json:"groupName"`
}

// Pinger send ping requests for presence.
type Pinger interface {
	Ping(string, string) error
}

// AuthLogin creates a jSession for the given username and team.
//
// If a session already exists, the method is a nop and returns
// already existing one.
//
// TODO(rjeczalik): Add AuthLogout to force creation of a new
// session.
func (k *Kloud) AuthLogin(p Pinger) func(r *kite.Request) (interface{}, error) {
	return func(r *kite.Request) (interface{}, error) {
		k.Log.Debug("AuthLogin called by %q with %q", r.Username, r.Args.Raw)

		req, err := getLoginReq(r)
		if err != nil {
			return nil, err
		}

		ses, err := modelhelper.UserLogin(r.Username, req.GroupName)
		switch err {
		case nil:
		case mgo.ErrNotFound:
			return nil, NewError(ErrBadRequest)
		case modelhelper.ErrNotParticipant:
			return nil, NewError(ErrNotAuthorized)
		default:
			k.Log.Debug("Got generic error for UserLogin, username: %q, err: %q, args: %q", r.Username, err.Error(), r.Args.Raw)
			return nil, NewError(ErrInternalServer)
		}

		if err := p.Ping(r.Username, req.GroupName); err != nil {
			// we dont need to block user login if there is something wrong with socialapi.
			k.Log.Error("Ping failed with %q for user %q", err.Error(), r.Username)
		}
{'fraction_non_alphanumeric': 0.11466116980159753, 'fraction_numerical': 0.0002576655501159495, 'mean_word_length': 3.6104513064133017, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6424951', 'n_tokens_mistral': 1293, 'n_tokens_neox': 1222, 'n_words': 459}