workflow

package
v0.0.0-...-122f59b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 23, 2024 License: Apache-2.0 Imports: 42 Imported by: 0

Documentation

Index

Constants

Variables

View Source
var ErrEOF = errors.New("eof")

ErrEOF means end of workflow. This error originates from CanReactTo and will be propagated to public API.

View Source
var ErrIncompatibleInput = errors.New("incompatible input")

ErrIncompatibleInput means the input reactor cannot react to the input. This error can only be returned by ReactTo.

View Source
var ErrInvalidInputKind = apierrors.BadRequest.WithReason("WorkflowInvalidInputKind").New("invalid input kind")
View Source
var ErrNoChange = errors.New("no change")

ErrNoChange means the input does not cause the workflow to change. This error originates from Accept and will be propagated to public API.

View Source
var ErrSameNode = errors.New("same node")

ErrSameNode means the input is reacted to, but no node is produced. This typically means the node has performed some immediate side effects. This error can only be returned by ReactTo.

View Source
var ErrUnknownInput = apierrors.BadRequest.WithReason("WorkflowUnknownInput").New("unknown input")
View Source
var ErrUnknownIntent = apierrors.BadRequest.WithReason("WorkflowUnknownIntent").New("unknown intent")
View Source
var ErrUpdateNode = errors.New("update node")

ErrUpdateNode means the input is reacted to, but instead of producing a new node to be appended, the returned node should replace the node. This error can only be returned by ReactTo.

View Source
var ErrUserAgentUnmatched = apierrors.Forbidden.WithReason("UserAgentUnmatched").New("workflow cannot be used in other user agent")
View Source
var ErrWorkflowNotFound = apierrors.NotFound.WithReason("WorkflowNotFound").New("workflow not found")
View Source
var UserAgentIDCookieDef = &httputil.CookieDef{
	NameSuffix:        "workflow_ua_id",
	Path:              "/",
	AllowScriptAccess: false,
	SameSite:          http.SameSiteNoneMode,
}

Functions

func AsInput

func AsInput(i Input, iface interface{}) bool

func FindSingleNode

func FindSingleNode[T NodeSimple](w *Workflow) (T, bool)

func GetOAuthSessionID

func GetOAuthSessionID(ctx context.Context) string

func GetSuppressIDPSessionCookie

func GetSuppressIDPSessionCookie(ctx context.Context) bool

func GetUserIDHint

func GetUserIDHint(ctx context.Context) string

func GetWorkflowID

func GetWorkflowID(ctx context.Context) string

func NewUserAgentID

func NewUserAgentID() string

func RegisterNode

func RegisterNode(node NodeSimple)

func RegisterPrivateIntent

func RegisterPrivateIntent(intent Intent)

func RegisterPublicInput

func RegisterPublicInput(input Input)

func RegisterPublicIntent

func RegisterPublicIntent(intent Intent)

Types

type AccountMigrationService

type AccountMigrationService interface {
	Run(migrationTokenString string) (*accountmigration.HookResponse, error)
}

type AuthenticationInfoEntryGetter

type AuthenticationInfoEntryGetter interface {
	GetAuthenticationInfoEntry(ctx context.Context, deps *Dependencies, flows Workflows) *authenticationinfo.Entry
}

type AuthenticationInfoService

type AuthenticationInfoService interface {
	Save(entry *authenticationinfo.Entry) error
}

type AuthenticatorService

type AuthenticatorService interface {
	NewWithAuthenticatorID(authenticatorID string, spec *authenticator.Spec) (*authenticator.Info, error)
	Get(authenticatorID string) (*authenticator.Info, error)
	Create(authenticatorInfo *authenticator.Info, markVerified bool) error
	Update(authenticatorInfo *authenticator.Info) error
	List(userID string, filters ...authenticator.Filter) ([]*authenticator.Info, error)
	WithSpec(authenticatorInfo *authenticator.Info, spec *authenticator.Spec) (changed bool, info *authenticator.Info, err error)
	VerifyWithSpec(info *authenticator.Info, spec *authenticator.Spec, options *facade.VerifyOptions) (verifyResult *service.VerifyResult, err error)
	VerifyOneWithSpec(userID string, authenticatorType model.AuthenticatorType, infos []*authenticator.Info, spec *authenticator.Spec, options *facade.VerifyOptions) (info *authenticator.Info, verifyResult *service.VerifyResult, err error)
	ClearLockoutAttempts(userID string, usedMethods []config.AuthenticationLockoutMethod) error
}

type CaptchaService

type CaptchaService interface {
	VerifyToken(token string) error
}

type CookieGetter

type CookieGetter interface {
	GetCookies(ctx context.Context, deps *Dependencies, workflows Workflows) ([]*http.Cookie, error)
}

type CookieManager

type CookieManager interface {
	GetCookie(r *http.Request, def *httputil.CookieDef) (*http.Cookie, error)
	ValueCookie(def *httputil.CookieDef, value string) *http.Cookie
	ClearCookie(def *httputil.CookieDef) *http.Cookie
}

type CustomAttrsService

type CustomAttrsService interface {
	UpdateCustomAttributesWithList(role accesscontrol.Role, userID string, attrs attrs.List) error
}

type Dependencies

type Dependencies struct {
	Config        *config.AppConfig
	FeatureConfig *config.FeatureConfig

	Clock    clock.Clock
	RemoteIP httputil.RemoteIP

	HTTPRequest *http.Request

	Users              UserService
	Identities         IdentityService
	Authenticators     AuthenticatorService
	MFA                MFAService
	StdAttrsService    StdAttrsService
	CustomAttrsService CustomAttrsService
	OTPCodes           OTPCodeService
	OTPSender          OTPSender
	Verification       VerificationService
	ForgotPassword     ForgotPasswordService
	ResetPassword      ResetPasswordService
	AccountMigrations  AccountMigrationService
	Captcha            CaptchaService

	IDPSessions          IDPSessionService
	Sessions             SessionService
	AuthenticationInfos  AuthenticationInfoService
	SessionCookie        session.CookieDef
	MFADeviceTokenCookie mfa.CookieDef

	Cookies CookieManager

	Events         EventService
	RateLimiter    RateLimiter
	WorkflowEvents EventStore

	OfflineGrants OfflineGrantStore
}

type Effect

type Effect interface {
	// contains filtered or unexported methods
}

type EffectGetter

type EffectGetter interface {
	GetEffects(ctx context.Context, deps *Dependencies, workflows Workflows) (effs []Effect, err error)
}

type Event

type Event interface {
	// contains filtered or unexported methods
}

type EventKind

type EventKind string
const (
	// WorkflowEventKindRefresh indicates client should re-fetch current instance of workflow for updated state.
	EventKindRefresh EventKind = "refresh"
)

type EventRefresh

type EventRefresh struct {
	Kind EventKind `json:"kind"`
}

func NewEventRefresh

func NewEventRefresh() *EventRefresh

type EventService

type EventService interface {
	DispatchEventOnCommit(payload event.Payload) error
	DispatchEventImmediately(payload event.NonBlockingPayload) error
}

type EventStore

type EventStore interface {
	Publish(workflowID string, e Event) error
}

type EventStoreImpl

type EventStoreImpl struct {
	AppID       config.AppID
	RedisHandle *appredis.Handle
	Store       Store
	// contains filtered or unexported fields
}

func NewEventStore

func NewEventStore(appID config.AppID, handle *appredis.Handle, store Store) *EventStoreImpl

func (*EventStoreImpl) ChannelName

func (s *EventStoreImpl) ChannelName(workflowID string) (string, error)

func (*EventStoreImpl) Publish

func (s *EventStoreImpl) Publish(workflowID string, e Event) error

type ForgotPasswordService

type ForgotPasswordService interface {
	SendCode(loginID string, options *forgotpassword.CodeOptions) error
}

type IDPSessionService

type IDPSessionService interface {
	MakeSession(*session.Attrs) (*idpsession.IDPSession, string)
	Create(*idpsession.IDPSession) error
	Reauthenticate(idpSessionID string, amr []string) error
}

type IdentityService

type IdentityService interface {
	Get(id string) (*identity.Info, error)
	SearchBySpec(spec *identity.Spec) (exactMatch *identity.Info, otherMatches []*identity.Info, err error)
	ListByClaim(name string, value string) ([]*identity.Info, error)
	ListByUser(userID string) ([]*identity.Info, error)
	New(userID string, spec *identity.Spec, options identity.NewIdentityOptions) (*identity.Info, error)
	UpdateWithSpec(is *identity.Info, spec *identity.Spec, options identity.NewIdentityOptions) (*identity.Info, error)
	CheckDuplicated(info *identity.Info) (*identity.Info, error)
	Create(is *identity.Info) error
	Update(oldIs *identity.Info, newIs *identity.Info) error
}

type Input

type Input interface {
	Kind() string
	JSONSchema() *validation.SimpleSchema
}

func InstantiateInputFromPublicRegistry

func InstantiateInputFromPublicRegistry(j InputJSON) (Input, error)

type InputFactory

type InputFactory func() Input

type InputJSON

type InputJSON struct {
	Kind string          `json:"kind"`
	Data json.RawMessage `json:"data"`
}

type InputReactor

type InputReactor interface {
	CanReactTo(ctx context.Context, deps *Dependencies, workflows Workflows) ([]Input, error)
	ReactTo(ctx context.Context, deps *Dependencies, workflows Workflows, input Input) (*Node, error)
}

type Intent

type Intent interface {
	InputReactor
	EffectGetter
	Kind() string
	JSONSchema() *validation.SimpleSchema
	OutputData(ctx context.Context, deps *Dependencies, workflows Workflows) (interface{}, error)
}

Intent can optionally implement CookieGetter.

func InstantiateIntentFromPrivateRegistry

func InstantiateIntentFromPrivateRegistry(j IntentJSON) (Intent, error)

func InstantiateIntentFromPublicRegistry

func InstantiateIntentFromPublicRegistry(j IntentJSON) (Intent, error)

type IntentFactory

type IntentFactory func() Intent

type IntentJSON

type IntentJSON struct {
	Kind string          `json:"kind"`
	Data json.RawMessage `json:"data"`
}

type IntentOutput

type IntentOutput struct {
	Kind string      `json:"kind"`
	Data interface{} `json:"data,omitempty"`
}

type IntlMiddleware

type IntlMiddleware struct{}

func (*IntlMiddleware) Handle

func (m *IntlMiddleware) Handle(next http.Handler) http.Handler

type MFAService

type MFAService interface {
	GenerateRecoveryCodes() []string
	ReplaceRecoveryCodes(userID string, codes []string) ([]*mfa.RecoveryCode, error)
	VerifyRecoveryCode(userID string, code string) (*mfa.RecoveryCode, error)
	ConsumeRecoveryCode(c *mfa.RecoveryCode) error

	GenerateDeviceToken() string
	CreateDeviceToken(userID string, token string) (*mfa.DeviceToken, error)
	VerifyDeviceToken(userID string, deviceToken string) error
}

type Node

type Node struct {
	Type        NodeType   `json:"type"`
	Simple      NodeSimple `json:"simple,omitempty"`
	SubWorkflow *Workflow  `json:"workflow,omitempty"`
}

func NewNodeSimple

func NewNodeSimple(simple NodeSimple) *Node

func NewSubWorkflow

func NewSubWorkflow(intent Intent) *Node

func (*Node) Clone

func (n *Node) Clone() *Node

func (*Node) FindInputReactor

func (n *Node) FindInputReactor(ctx context.Context, deps *Dependencies, workflows Workflows) (*Workflow, InputReactor, error)

func (*Node) MarshalJSON

func (n *Node) MarshalJSON() ([]byte, error)

func (*Node) ToOutput

func (n *Node) ToOutput(ctx context.Context, deps *Dependencies, workflows Workflows) (*NodeOutput, error)

func (*Node) Traverse

func (n *Node) Traverse(t WorkflowTraverser, w *Workflow) error

func (*Node) UnmarshalJSON

func (n *Node) UnmarshalJSON(d []byte) (err error)

type NodeFactory

type NodeFactory func() NodeSimple

type NodeOutput

type NodeOutput struct {
	Type        NodeType          `json:"type"`
	Simple      *NodeSimpleOutput `json:"simple,omitempty"`
	SubWorkflow *WorkflowOutput   `json:"workflow,omitempty"`
}

type NodeSimple

type NodeSimple interface {
	InputReactor
	EffectGetter
	Kind() string
	OutputData(ctx context.Context, deps *Dependencies, workflows Workflows) (interface{}, error)
}

NodeSimple can optionally implement CookieGetter.

func InstantiateNode

func InstantiateNode(kind string) (NodeSimple, error)

type NodeSimpleOutput

type NodeSimpleOutput struct {
	Kind string      `json:"kind"`
	Data interface{} `json:"data,omitempty"`
}

type NodeType

type NodeType string
const (
	NodeTypeSimple      NodeType = "SIMPLE"
	NodeTypeSubWorkflow NodeType = "SUB_WORKFLOW"
)

type OTPCodeService

type OTPCodeService interface {
	GenerateOTP(kind otp.Kind, target string, form otp.Form, opt *otp.GenerateOptions) (string, error)
	VerifyOTP(kind otp.Kind, target string, otp string, opts *otp.VerifyOptions) error
	InspectState(kind otp.Kind, target string) (*otp.State, error)

	LookupCode(purpose otp.Purpose, code string) (target string, err error)
	SetSubmittedCode(kind otp.Kind, target string, code string) (*otp.State, error)
}

type OTPSender

type OTPSender interface {
	Prepare(channel model.AuthenticatorOOBChannel, target string, form otp.Form, typ otp.MessageType) (*otp.PreparedMessage, error)
	Send(msg *otp.PreparedMessage, opts otp.SendOptions) error
}

type OfflineGrantStore

type OfflineGrantStore interface {
	ListClientOfflineGrants(clientID string, userID string) ([]*oauth.OfflineGrant, error)
}

type OnCommitEffect

type OnCommitEffect func(ctx context.Context, deps *Dependencies) error

type RateLimiter

type RateLimiter interface {
	Allow(spec ratelimit.BucketSpec) error
	Reserve(spec ratelimit.BucketSpec) *ratelimit.Reservation
	Cancel(r *ratelimit.Reservation)
}

type ResetPasswordService

type ResetPasswordService interface {
	VerifyCode(code string) (state *otp.State, err error)
	ResetPassword(code string, newPassword string) error
}

type RunEffect

type RunEffect func(ctx context.Context, deps *Dependencies) error

type Service

type Service struct {
	ContextDoNotUseDirectly context.Context
	Deps                    *Dependencies
	Logger                  ServiceLogger
	Store                   Store
	Database                ServiceDatabase
	UIInfoResolver          ServiceUIInfoResolver
}

func (*Service) CreateNewWorkflow

func (s *Service) CreateNewWorkflow(intent Intent, sessionOptions *SessionOptions) (output *ServiceOutput, err error)

func (*Service) FeedInput

func (s *Service) FeedInput(workflowID string, instanceID string, userAgentID string, input Input) (output *ServiceOutput, err error)

func (*Service) Get

func (s *Service) Get(workflowID string, instanceID string, userAgentID string) (output *ServiceOutput, err error)

type ServiceDatabase

type ServiceDatabase interface {
	WithTx(do func() error) (err error)
	ReadOnly(do func() error) (err error)
}

type ServiceLogger

type ServiceLogger struct{ *log.Logger }

func NewServiceLogger

func NewServiceLogger(lf *log.Factory) ServiceLogger

type ServiceOutput

type ServiceOutput struct {
	Session        *Session
	SessionOutput  *SessionOutput
	Workflow       *Workflow
	WorkflowOutput *WorkflowOutput
	Action         *WorkflowAction
	Cookies        []*http.Cookie
}

type ServiceUIInfoResolver

type ServiceUIInfoResolver interface {
	SetAuthenticationInfoInQuery(redirectURI string, e *authenticationinfo.Entry) string
}

type Session

type Session struct {
	WorkflowID string `json:"workflow_id"`

	OAuthSessionID           string `json:"oauth_session_id,omitempty"`
	ClientID                 string `json:"client_id,omitempty"`
	RedirectURI              string `json:"redirect_uri,omitempty"`
	SuppressIDPSessionCookie bool   `json:"suppress_idp_session_cookie,omitempty"`
	State                    string `json:"state,omitempty"`
	XState                   string `json:"x_state,omitempty"`
	UILocales                string `json:"ui_locales,omitempty"`
	UserAgentID              string `json:"user_agent_id,omitempty"`
	// UserIDHint is for reauthentication.
	UserIDHint string `json:"user_id_hint,omitempty"`
}

func NewSession

func NewSession(opts *SessionOptions) *Session

func (*Session) Context

func (s *Session) Context(ctx context.Context) context.Context

func (*Session) ToOutput

func (s *Session) ToOutput() *SessionOutput

type SessionOptions

type SessionOptions struct {
	OAuthSessionID           string
	ClientID                 string
	RedirectURI              string
	SuppressIDPSessionCookie bool
	State                    string
	XState                   string
	UILocales                string
	UserAgentID              string
	// UserIDHint is for reauthentication.
	UserIDHint string
}

func (*SessionOptions) PartiallyMergeFrom

func (s *SessionOptions) PartiallyMergeFrom(o *SessionOptions) *SessionOptions

type SessionOutput

type SessionOutput struct {
	WorkflowID  string `json:"workflow_id"`
	ClientID    string `json:"client_id,omitempty"`
	RedirectURI string `json:"redirect_uri,omitempty"`
}

type SessionService

type SessionService interface {
	RevokeWithoutEvent(session.Session) error
}

type StdAttrsService

type StdAttrsService interface {
	PopulateStandardAttributes(userID string, iden *identity.Info) error
	UpdateStandardAttributesWithList(role accesscontrol.Role, userID string, attrs attrs.List) error
}

type Store

type Store interface {
	CreateSession(session *Session) error
	GetSession(workflowID string) (*Session, error)
	DeleteSession(session *Session) error

	CreateWorkflow(workflow *Workflow) error
	GetWorkflowByInstanceID(instanceID string) (*Workflow, error)
	DeleteWorkflow(workflow *Workflow) error
}

type StoreImpl

type StoreImpl struct {
	Redis   *appredis.Handle
	AppID   config.AppID
	Context context.Context
}

func (*StoreImpl) CreateSession

func (s *StoreImpl) CreateSession(session *Session) error

func (*StoreImpl) CreateWorkflow

func (s *StoreImpl) CreateWorkflow(workflow *Workflow) error

func (*StoreImpl) DeleteSession

func (s *StoreImpl) DeleteSession(session *Session) error

func (*StoreImpl) DeleteWorkflow

func (s *StoreImpl) DeleteWorkflow(workflow *Workflow) error

func (*StoreImpl) GetSession

func (s *StoreImpl) GetSession(workflowID string) (*Session, error)

func (*StoreImpl) GetWorkflowByInstanceID

func (s *StoreImpl) GetWorkflowByInstanceID(instanceID string) (*Workflow, error)

type UserService

type UserService interface {
	GetRaw(id string) (*user.User, error)
	Create(userID string) (*user.User, error)
	UpdateLoginTime(userID string, t time.Time) error
	AfterCreate(
		user *user.User,
		identities []*identity.Info,
		authenticators []*authenticator.Info,
		isAdminAPI bool,
	) error
}

type VerificationService

type VerificationService interface {
	GetIdentityVerificationStatus(i *identity.Info) ([]verification.ClaimStatus, error)
	NewVerifiedClaim(userID string, claimName string, claimValue string) *verification.Claim
	MarkClaimVerified(claim *verification.Claim) error
}

type Workflow

type Workflow struct {
	WorkflowID string
	InstanceID string
	Intent     Intent
	Nodes      []Node
}

func FindSubWorkflows

func FindSubWorkflows[T Intent](w *Workflow) []*Workflow

func MustFindSubWorkflow

func MustFindSubWorkflow[T Intent](w *Workflow) (T, *Workflow)

func NewWorkflow

func NewWorkflow(workflowID string, intent Intent) *Workflow

func (*Workflow) Accept

func (w *Workflow) Accept(ctx context.Context, deps *Dependencies, workflows Workflows, input Input) (err error)

Accept executes the workflow to the deepest using input. In addition to the errors caused by intents and nodes, ErrEOF and ErrNoChange can be returned.

func (*Workflow) ApplyAllEffects

func (w *Workflow) ApplyAllEffects(ctx context.Context, deps *Dependencies, workflows Workflows) error

func (*Workflow) ApplyRunEffects

func (w *Workflow) ApplyRunEffects(ctx context.Context, deps *Dependencies, workflows Workflows) error

func (*Workflow) Clone

func (w *Workflow) Clone() *Workflow

func (*Workflow) CollectCookies

func (w *Workflow) CollectCookies(ctx context.Context, deps *Dependencies, workflows Workflows) (cookies []*http.Cookie, err error)

func (*Workflow) FindInputReactor

func (w *Workflow) FindInputReactor(ctx context.Context, deps *Dependencies, workflows Workflows) (*Workflow, InputReactor, error)

func (*Workflow) GetAuthenticationInfoEntry

func (w *Workflow) GetAuthenticationInfoEntry(ctx context.Context, deps *Dependencies, workflows Workflows) (*authenticationinfo.Entry, bool)

func (*Workflow) IsEOF

func (w *Workflow) IsEOF(ctx context.Context, deps *Dependencies, workflows Workflows) (bool, error)

func (*Workflow) MarshalJSON

func (w *Workflow) MarshalJSON() ([]byte, error)

func (*Workflow) ToOutput

func (w *Workflow) ToOutput(ctx context.Context, deps *Dependencies, workflows Workflows) (*WorkflowOutput, error)

func (*Workflow) Traverse

func (w *Workflow) Traverse(t WorkflowTraverser) error

func (*Workflow) UnmarshalJSON

func (w *Workflow) UnmarshalJSON(d []byte) (err error)

type WorkflowAction

type WorkflowAction struct {
	Type        WorkflowActionType `json:"type"`
	RedirectURI string             `json:"redirect_uri,omitempty"`
}

type WorkflowActionType

type WorkflowActionType string
const (
	WorkflowActionTypeContinue WorkflowActionType = "continue"
	WorkflowActionTypeFinish   WorkflowActionType = "finish"
	WorkflowActionTypeRedirect WorkflowActionType = "redirect"
)

type WorkflowOutput

type WorkflowOutput struct {
	WorkflowID string       `json:"workflow_id,omitempty"`
	InstanceID string       `json:"instance_id,omitempty"`
	Intent     IntentOutput `json:"intent"`
	Nodes      []NodeOutput `json:"nodes,omitempty"`
}

type WorkflowTraverser

type WorkflowTraverser struct {
	Intent     func(intent Intent, w *Workflow) error
	NodeSimple func(nodeSimple NodeSimple, w *Workflow) error
}

type Workflows

type Workflows struct {
	Root    *Workflow
	Nearest *Workflow
}

func NewWorkflows

func NewWorkflows(root *Workflow) Workflows

func (Workflows) Replace

func (w Workflows) Replace(nearest *Workflow) Workflows

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL