mosquitto-go-auth/backends/javascript.go

150 lines
3.3 KiB
Go

package backends
import (
"strconv"
"github.com/iegomez/mosquitto-go-auth/backends/js"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
type Javascript struct {
stackDepthLimit int
msMaxDuration int64
userScript string
superuserScript string
aclScript string
runner *js.Runner
}
func NewJavascript(authOpts map[string]string, logLevel log.Level) (*Javascript, error) {
log.SetLevel(logLevel)
javascript := &Javascript{
stackDepthLimit: js.DefaultStackDepthLimit,
msMaxDuration: js.DefaultMsMaxDuration,
}
jsOk := true
missingOptions := ""
if stackLimit, ok := authOpts["js_stack_depth_limit"]; ok {
limit, err := strconv.ParseInt(stackLimit, 10, 64)
if err != nil {
log.Errorf("invalid stack depth limit %s, defaulting to %d", stackLimit, js.DefaultStackDepthLimit)
} else {
javascript.stackDepthLimit = int(limit)
}
}
if maxDuration, ok := authOpts["js_ms_max_duration"]; ok {
duration, err := strconv.ParseInt(maxDuration, 10, 64)
if err != nil {
log.Errorf("invalid stack depth limit %s, defaulting to %d", maxDuration, js.DefaultMsMaxDuration)
} else {
javascript.msMaxDuration = duration
}
}
if userScriptPath, ok := authOpts["js_user_script_path"]; ok {
script, err := js.LoadScript(userScriptPath)
if err != nil {
return javascript, err
}
javascript.userScript = script
} else {
jsOk = false
missingOptions += " js_user_script_path"
}
if superuserScriptPath, ok := authOpts["js_superuser_script_path"]; ok {
script, err := js.LoadScript(superuserScriptPath)
if err != nil {
return javascript, err
}
javascript.superuserScript = script
} else {
jsOk = false
missingOptions += " js_superuser_script_path"
}
if aclScriptPath, ok := authOpts["js_acl_script_path"]; ok {
script, err := js.LoadScript(aclScriptPath)
if err != nil {
return javascript, err
}
javascript.aclScript = script
} else {
jsOk = false
missingOptions += " js_acl_script_path"
}
//Exit if any mandatory option is missing.
if !jsOk {
return nil, errors.Errorf("Javascript backend error: missing options: %s", missingOptions)
}
javascript.runner = js.NewRunner(javascript.stackDepthLimit, javascript.msMaxDuration)
return javascript, nil
}
func (o *Javascript) GetUser(username, password, clientid string) (bool, error) {
params := map[string]interface{}{
"username": username,
"password": password,
"clientid": clientid,
}
granted, err := o.runner.RunScript(o.userScript, params)
if err != nil {
log.Errorf("js error: %s", err)
}
return granted, err
}
func (o *Javascript) GetSuperuser(username string) (bool, error) {
params := map[string]interface{}{
"username": username,
}
granted, err := o.runner.RunScript(o.superuserScript, params)
if err != nil {
log.Errorf("js error: %s", err)
}
return granted, err
}
func (o *Javascript) CheckAcl(username, topic, clientid string, acc int32) (bool, error) {
params := map[string]interface{}{
"username": username,
"topic": topic,
"clientid": clientid,
"acc": acc,
}
granted, err := o.runner.RunScript(o.aclScript, params)
if err != nil {
log.Errorf("js error: %s", err)
}
return granted, err
}
//GetName returns the backend's name
func (o *Javascript) GetName() string {
return "Javascript"
}
func (o *Javascript) Halt() {
// NO-OP
}