2021-09-27 13:43:49 +02:00
|
|
|
package actions
|
|
|
|
|
|
|
|
import (
|
2022-10-06 14:23:59 +02:00
|
|
|
"context"
|
2021-09-27 13:43:49 +02:00
|
|
|
"errors"
|
2022-10-06 14:23:59 +02:00
|
|
|
"fmt"
|
2021-09-27 13:43:49 +02:00
|
|
|
|
|
|
|
"github.com/dop251/goja_nodejs/require"
|
2022-10-06 14:23:59 +02:00
|
|
|
z_errs "github.com/zitadel/zitadel/internal/errors"
|
|
|
|
"github.com/zitadel/zitadel/internal/query"
|
2021-09-27 13:43:49 +02:00
|
|
|
)
|
|
|
|
|
2022-10-06 14:23:59 +02:00
|
|
|
type Config struct {
|
|
|
|
HTTP HTTPConfig
|
|
|
|
}
|
2021-09-27 13:43:49 +02:00
|
|
|
|
2022-10-06 14:23:59 +02:00
|
|
|
var (
|
|
|
|
ErrHalt = errors.New("interrupt")
|
|
|
|
)
|
2021-09-27 13:43:49 +02:00
|
|
|
|
2022-10-06 14:23:59 +02:00
|
|
|
type jsAction func(fields, fields) error
|
|
|
|
|
|
|
|
func Run(ctx context.Context, ctxParam contextFields, apiParam apiFields, script, name string, opts ...Option) error {
|
|
|
|
config, err := prepareRun(ctx, ctxParam, apiParam, script, opts)
|
2021-09-27 13:43:49 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-10-06 14:23:59 +02:00
|
|
|
|
2021-09-27 13:43:49 +02:00
|
|
|
var fn jsAction
|
2022-10-06 14:23:59 +02:00
|
|
|
jsFn := config.vm.Get(name)
|
2021-09-27 13:43:49 +02:00
|
|
|
if jsFn == nil {
|
|
|
|
return errors.New("function not found")
|
|
|
|
}
|
2022-10-06 14:23:59 +02:00
|
|
|
err = config.vm.ExportTo(jsFn, &fn)
|
2021-09-27 13:43:49 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-10-06 14:23:59 +02:00
|
|
|
|
|
|
|
t := config.Start()
|
2021-09-27 13:43:49 +02:00
|
|
|
defer func() {
|
|
|
|
t.Stop()
|
|
|
|
}()
|
2022-10-06 14:23:59 +02:00
|
|
|
|
|
|
|
return executeFn(config, fn)
|
2021-09-27 13:43:49 +02:00
|
|
|
}
|
|
|
|
|
2022-10-06 14:23:59 +02:00
|
|
|
func prepareRun(ctx context.Context, ctxParam contextFields, apiParam apiFields, script string, opts []Option) (config *runConfig, err error) {
|
|
|
|
config = newRunConfig(ctx, opts...)
|
|
|
|
if config.timeout == 0 {
|
|
|
|
return nil, z_errs.ThrowInternal(nil, "ACTIO-uCpCx", "Errrors.Internal")
|
|
|
|
}
|
|
|
|
t := config.Prepare()
|
|
|
|
defer func() {
|
|
|
|
t.Stop()
|
|
|
|
}()
|
|
|
|
|
|
|
|
if ctxParam != nil {
|
|
|
|
ctxParam(config.ctxParam)
|
|
|
|
}
|
|
|
|
if apiParam != nil {
|
|
|
|
apiParam(config.apiParam)
|
|
|
|
}
|
2021-09-27 13:43:49 +02:00
|
|
|
|
|
|
|
registry := new(require.Registry)
|
2022-10-06 14:23:59 +02:00
|
|
|
registry.Enable(config.vm)
|
2021-09-27 13:43:49 +02:00
|
|
|
|
2022-10-06 14:23:59 +02:00
|
|
|
for name, loader := range config.modules {
|
|
|
|
registry.RegisterNativeModule(name, loader)
|
|
|
|
}
|
2021-09-27 13:43:49 +02:00
|
|
|
|
2022-10-06 14:23:59 +02:00
|
|
|
// overload error if function panics
|
2021-09-27 13:43:49 +02:00
|
|
|
defer func() {
|
2022-10-06 14:23:59 +02:00
|
|
|
r := recover()
|
|
|
|
if r != nil {
|
|
|
|
err = r.(error)
|
|
|
|
return
|
|
|
|
}
|
2021-09-27 13:43:49 +02:00
|
|
|
}()
|
2022-10-06 14:23:59 +02:00
|
|
|
_, err = config.vm.RunString(script)
|
|
|
|
return config, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func executeFn(config *runConfig, fn jsAction) (err error) {
|
|
|
|
defer func() {
|
|
|
|
r := recover()
|
|
|
|
if r != nil && !config.allowedToFail {
|
|
|
|
var ok bool
|
|
|
|
if err, ok = r.(error); ok {
|
2021-09-27 13:43:49 +02:00
|
|
|
return
|
|
|
|
}
|
2022-10-06 14:23:59 +02:00
|
|
|
|
|
|
|
e, ok := r.(string)
|
|
|
|
if ok {
|
|
|
|
err = errors.New(e)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = fmt.Errorf("unknown error occured: %v", r)
|
2021-09-27 13:43:49 +02:00
|
|
|
}
|
|
|
|
}()
|
2022-10-06 14:23:59 +02:00
|
|
|
err = fn(config.ctxParam.fields, config.apiParam.fields)
|
|
|
|
if err != nil && !config.allowedToFail {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2021-09-27 13:43:49 +02:00
|
|
|
}
|
|
|
|
|
2022-10-06 14:23:59 +02:00
|
|
|
func ActionToOptions(a *query.Action) []Option {
|
|
|
|
opts := make([]Option, 0, 1)
|
|
|
|
if a.AllowedToFail {
|
|
|
|
opts = append(opts, WithAllowedToFail())
|
|
|
|
}
|
|
|
|
return opts
|
2021-09-27 13:43:49 +02:00
|
|
|
}
|