<commit_before>package flows

import (
	"github.com/skygeario/skygear-server/pkg/auth/dependency/interaction"
	"github.com/skygeario/skygear-server/pkg/auth/model"
	"github.com/skygeario/skygear-server/pkg/core/authn"
)

type AuthAPIFlow struct {
	Interactions   InteractionProvider
	UserController *UserController
}

func (f *AuthAPIFlow) LoginWithLoginIDPassword(
	clientID string, loginIDKey string, loginID string, password string,
) (*AuthResult, error) {
	i, err := f.Interactions.NewInteractionLogin(&interaction.IntentLogin{
		Identity: interaction.IdentitySpec{
			Type: authn.IdentityTypeLoginID,
			Claims: map[string]interface{}{
				interaction.IdentityClaimLoginIDKey:   loginIDKey,
				interaction.IdentityClaimLoginIDValue: loginID,
			},
		},
	}, clientID)
	if err != nil {
		return nil, err
	}

	s, err := f.Interactions.GetInteractionState(i)
	if err != nil {
		return nil, err
	} else if s.CurrentStep().Step != interaction.StepAuthenticatePrimary {
		return nil, ErrUnsupportedConfiguration
	}

	err = f.Interactions.PerformAction(
		i,
		interaction.StepAuthenticatePrimary,
		&interaction.ActionAuthenticate{
			Authenticator: interaction.AuthenticatorSpec{Type: interaction.AuthenticatorTypePassword},
			Secret:        password,
		},
	)
	if err != nil {
		return nil, err
	}

	if i.Error != nil {
		return nil, i.Error
	}

	s, err = f.Interactions.GetInteractionState(i)
	if err != nil {
		return nil, err
	}

	switch s.CurrentStep().Step {
	case interaction.StepAuthenticateSecondary, interaction.StepSetupSecondaryAuthenticator:
		panic("interaction_flow_auth_api: TODO: handle MFA")

	case interaction.StepCommit:
		attrs, err := f.Interactions.Commit(i)
		if err != nil {
			return nil, err
		}

		result, err := f.UserController.CreateSession(i, attrs, true)
		if err != nil {
			return nil, err
		}

		return result, nil

	default:
		return nil, ErrUnsupportedConfiguration
	}
}

func (f *AuthAPIFlow) SignupWithLoginIDPassword(
	clientID string,
	loginIDKey string,
	loginID string,
	password string,
	metadata map[string]interface{},
	onUserDuplicate model.OnUserDuplicate,
) (*AuthResult, error) {
	i, err := f.Interactions.NewInteractionSignup(&interaction.IntentSignup{
		Identity: interaction.IdentitySpec{
			Type: authn.IdentityTypeLoginID,
			Claims: map[string]interface{}{
				interaction.IdentityClaimLoginIDKey:   loginIDKey,
				interaction.IdentityClaimLoginIDValue: loginID,
			},
		},
		OnUserDuplicate: onUserDuplicate,
		UserMetadata:    metadata,
	}, clientID)
	if err != nil {
		return nil, err<commit_msg>Add TODO for signup auth API<commit_after>package flows

import (
	"github.com/skygeario/skygear-server/pkg/auth/dependency/interaction"
	"github.com/skygeario/skygear-server/pkg/auth/model"
	"github.com/skygeario/skygear-server/pkg/core/authn"
)

type AuthAPIFlow struct {
	Interactions   InteractionProvider
	UserController *UserController
}

func (f *AuthAPIFlow) LoginWithLoginIDPassword(
	clientID string, loginIDKey string, loginID string, password string,
) (*AuthResult, error) {
	i, err := f.Interactions.NewInteractionLogin(&interaction.IntentLogin{
		Identity: interaction.IdentitySpec{
			Type: authn.IdentityTypeLoginID,
			Claims: map[string]interface{}{
				interaction.IdentityClaimLoginIDKey:   loginIDKey,
				interaction.IdentityClaimLoginIDValue: loginID,
			},
		},
	}, clientID)
	if err != nil {
		return nil, err
	}

	s, err := f.Interactions.GetInteractionState(i)
	if err != nil {
		return nil, err
	} else if s.CurrentStep().Step != interaction.StepAuthenticatePrimary {
		return nil, ErrUnsupportedConfiguration
	}

	err = f.Interactions.PerformAction(
		i,
		interaction.StepAuthenticatePrimary,
		&interaction.ActionAuthenticate{
			Authenticator: interaction.AuthenticatorSpec{Type: interaction.AuthenticatorTypePassword},
			Secret:        password,
		},
	)
	if err != nil {
		return nil, err
	}

	if i.Error != nil {
		return nil, i.Error
	}

	s, err = f.Interactions.GetInteractionState(i)
	if err != nil {
		return nil, err
	}

	switch s.CurrentStep().Step {
	case interaction.StepAuthenticateSecondary, interaction.StepSetupSecondaryAuthenticator:
		panic("interaction_flow_auth_api: TODO: handle MFA")

	case interaction.StepCommit:
		attrs, err := f.Interactions.Commit(i)
		if err != nil {
			return nil, err
		}

		result, err := f.UserController.CreateSession(i, attrs, true)
		if err != nil {
			return nil, err
		}

		return result, nil

	default:
		return nil, ErrUnsupportedConfiguration
	}
}

// TODO(interaction): support multiple login IDs
func (f *AuthAPIFlow) SignupWithLoginIDPassword(
	clientID string,
	loginIDKey string,
	loginID string,
	password string,
	metadata map[string]interface{},
	onUserDuplicate model.OnUserDuplicate,
) (*AuthResult, error) {
	i, err := f.Interactions.NewInteractionSignup(&interaction.IntentSignup{
		Identity: interaction.IdentitySpec{
			Type: authn.IdentityTypeLoginID,
			Claims: map[string]interface{}{
				interaction.IdentityClaimLoginIDKey:   loginIDKey,
				interaction.IdentityClaimLoginIDValue: loginID,
			},
		},
		OnUserDuplicate: onUserDuplicate,
		UserMetadata:    metadata,
	}, clientID)
	if err != nil {
		return nil, err
{'fraction_non_alphanumeric': 0.10405405405405406, 'fraction_numerical': 0.0, 'mean_word_length': 4.668490153172867, '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': '6713455', 'n_tokens_mistral': 1815, 'n_tokens_neox': 1689, 'n_words': 357}