Skip to content

Commit

Permalink
Rename launch, shell and fix allow_* config options (#133)
Browse files Browse the repository at this point in the history
* api methods and config allow_launch renamed and implemented

* Change launch active to run in state and remove platform launching funcs

* Rename TokensLaunching to TokensRunning in models constants

* Rename shell cmd, remove from platform, switch to exec module globally

* Remove pointless execute allow check

* Support basic wildcard arguments in allow_execute

* Add support for quoted arguments in execute command

* Use regular expressions for allow_ configs
  • Loading branch information
wizzomafizzo authored Dec 28, 2024
1 parent 6a7a7b7 commit 63f8250
Show file tree
Hide file tree
Showing 24 changed files with 220 additions and 246 deletions.
37 changes: 25 additions & 12 deletions pkg/api/methods/launch.go → pkg/api/methods/run.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package methods

import (
"encoding/hex"
"encoding/json"
"errors"
"github.com/ZaparooProject/zaparoo-core/pkg/api/models"
"github.com/ZaparooProject/zaparoo-core/pkg/api/models/requests"
"github.com/ZaparooProject/zaparoo-core/pkg/config"
"github.com/ZaparooProject/zaparoo-core/pkg/service/tokens"
"golang.org/x/text/unicode/norm"
"net/http"
"net/url"
"strings"
"time"

"github.com/ZaparooProject/zaparoo-core/pkg/service/state"
Expand All @@ -22,19 +25,19 @@ var (
ErrNotAllowed = errors.New("not allowed")
)

func HandleLaunch(env requests.RequestEnv) (any, error) {
log.Info().Msg("received launch request")
func HandleRun(env requests.RequestEnv) (any, error) {
log.Info().Msg("received run request")

if len(env.Params) == 0 {
return nil, ErrMissingParams
}

var t tokens.Token

var params models.LaunchParams
var params models.RunParams
err := json.Unmarshal(env.Params, &params)
if err == nil {
log.Debug().Msgf("unmarshalled launch params: %+v", params)
log.Debug().Msgf("unmarshalled run params: %+v", params)

if params.Type != nil {
t.Type = *params.Type
Expand All @@ -43,7 +46,6 @@ func HandleLaunch(env requests.RequestEnv) (any, error) {
hasArg := false

if params.UID != nil {
// TODO: validate uid format (hex) and tidy
t.UID = *params.UID
hasArg = true
}
Expand All @@ -54,16 +56,21 @@ func HandleLaunch(env requests.RequestEnv) (any, error) {
}

if params.Data != nil {
// TODO: validate hex format
t.Data = *params.Data
t.Data = strings.ToLower(*params.Data)
t.Data = strings.ReplaceAll(t.Data, " ", "")

if _, err := hex.DecodeString(t.Data); err != nil {
return nil, ErrInvalidParams
}

hasArg = true
}

if !hasArg {
return nil, ErrInvalidParams
}
} else {
log.Debug().Msgf("could not unmarshal launch params, trying string: %s", env.Params)
log.Debug().Msgf("could not unmarshal run params, trying string: %s", env.Params)

var text string
err := json.Unmarshal(env.Params, &text)
Expand All @@ -88,13 +95,13 @@ func HandleLaunch(env requests.RequestEnv) (any, error) {
return nil, nil
}

// TODO: this is still insecure
func HandleLaunchBasic(
func HandleRunRest(
cfg *config.Instance,
st *state.State,
itq chan<- tokens.Token,
) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Info().Msg("received basic launch request")
log.Info().Msg("received REST run request")

text := chi.URLParam(r, "*")
text, err := url.QueryUnescape(text)
Expand All @@ -104,7 +111,13 @@ func HandleLaunchBasic(
return
}

log.Info().Msgf("launching basic token: %s", text)
if !cfg.IsRunAllowed(text) {
log.Error().Msgf("run not allowed: %s", text)
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return
}

log.Info().Msgf("running token: %s", text)

t := tokens.Token{
Text: norm.NFC.String(text),
Expand Down
12 changes: 6 additions & 6 deletions pkg/api/methods/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func HandleSettings(env requests.RequestEnv) (any, error) {
log.Info().Msg("received settings request")

resp := models.SettingsResponse{
LaunchingActive: !env.State.IsLauncherDisabled(),
RunZapScript: env.State.CanRunZapScript(),
DebugLogging: env.Config.DebugLogging(),
AudioScanFeedback: env.Config.AudioFeedback(),
ReadersAutoDetect: env.Config.Readers().AutoDetect,
Expand Down Expand Up @@ -44,12 +44,12 @@ func HandleSettingsUpdate(env requests.RequestEnv) (any, error) {
return nil, ErrInvalidParams
}

if params.LaunchingActive != nil {
log.Info().Bool("launchingActive", *params.LaunchingActive).Msg("update")
if *params.LaunchingActive {
env.State.EnableLauncher()
if params.RunZapScript != nil {
log.Info().Bool("runZapScript", *params.RunZapScript).Msg("update")
if *params.RunZapScript {
env.State.SetRunZapScript(true)
} else {
env.State.DisableLauncher()
env.State.SetRunZapScript(false)
}
}

Expand Down
4 changes: 1 addition & 3 deletions pkg/api/methods/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,8 @@ func newStatus(
}
}

launcherDisabled := st.IsLauncherDisabled()

return models.StatusResponse{
Launching: !launcherDisabled,
Launching: st.CanRunZapScript(),
Readers: readers,
Reader: models.ReaderStatusResponse{
Connected: readerConnected,
Expand Down
7 changes: 4 additions & 3 deletions pkg/api/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import "github.com/google/uuid"
const (
ReadersConnected = "readers.connected"
ReadersDisconnected = "readers.disconnected"
TokensLaunching = "tokens.launching"
TokensRunning = "tokens.running"
TokensActive = "tokens.active"
MediaStopped = "media.stopped"
MediaStarted = "media.started"
MediaIndexing = "media.indexing"
MethodLaunch = "launch"
MethodLaunch = "launch" // DEPRECATED
MethodRun = "run"
MethodStop = "stop"
MethodMediaIndex = "media.index"
MethodMediaSearch = "media.search"
Expand All @@ -27,7 +28,7 @@ const (
MethodMappingsUpdate = "mappings.update"
MethodMappingsReload = "mappings.reload"
MethodReadersWrite = "readers.write"
MethodStatus = "status"
MethodStatus = "status" // DEPRECATED
MethodVersion = "version"
)

Expand Down
4 changes: 2 additions & 2 deletions pkg/api/models/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type MediaIndexParams struct {
Systems *[]string `json:"systems"`
}

type LaunchParams struct {
type RunParams struct {
Type *string `json:"type"`
UID *string `json:"uid"`
Text *string `json:"text"`
Expand Down Expand Up @@ -45,7 +45,7 @@ type ReaderWriteParams struct {
}

type UpdateSettingsParams struct {
LaunchingActive *bool `json:"launchingActive"`
RunZapScript *bool `json:"runZapScript"`
DebugLogging *bool `json:"debugLogging"`
AudioScanFeedback *bool `json:"audioScanFeedback"`
ReadersAutoDetect *bool `json:"readersAutoDetect"`
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/models/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type IndexStatusResponse struct {
}

type SettingsResponse struct {
LaunchingActive bool `json:"launchingActive"`
RunZapScript bool `json:"runZapScript"`
DebugLogging bool `json:"debugLogging"`
AudioScanFeedback bool `json:"audioScanFeedback"`
ReadersAutoDetect bool `json:"readersAutoDetect"`
Expand Down
12 changes: 6 additions & 6 deletions pkg/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,15 @@ import (
"github.com/rs/zerolog/log"
)

// TODO: should there be a TTL for request timestamps? what about offline misters?
// TODO: can we safely allow launch basic unrestricted for local accounts?
// TODO: should api launches from localhost require allowlist?
// TODO: download log file no longer works, need an alternative

const RequestTimeout = 30 * time.Second

var methodMap = map[string]func(requests.RequestEnv) (any, error){
// launching
models.MethodLaunch: methods.HandleLaunch,
// running
models.MethodLaunch: methods.HandleRun, // DEPRECATED
models.MethodRun: methods.HandleRun,
models.MethodStop: methods.HandleStop,
// media
models.MethodMediaIndex: methods.HandleIndexMedia,
Expand Down Expand Up @@ -277,8 +276,9 @@ func Start(
log.Error().Err(err).Msg("message does not match known types")
})

// TODO: use allow list
r.Get("/l/*", methods.HandleLaunchBasic(st, itq))
r.Get("/l/*", methods.HandleRunRest(cfg, st, itq)) // DEPRECATED
r.Get("/r/*", methods.HandleRunRest(cfg, st, itq))
r.Get("/run/*", methods.HandleRunRest(cfg, st, itq))

err := http.ListenAndServe(":"+strconv.Itoa(cfg.ApiPort()), r)
if err != nil {
Expand Down
12 changes: 6 additions & 6 deletions pkg/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (f *Flags) Post(cfg *config.Instance) {
_, err := client.LocalClient(
cfg,
models.MethodSettingsUpdate,
"{\"launchingActive\":true}",
"{\"runZapScript\":true}",
)
if err != nil {
log.Error().Err(err).Msg("error re-enabling run")
Expand All @@ -143,7 +143,7 @@ func (f *Flags) Post(cfg *config.Instance) {
_, err := client.LocalClient(
cfg,
models.MethodSettingsUpdate,
"{\"launchingActive\":false}",
"{\"runZapScript\":false}",
)
if err != nil {
log.Error().Err(err).Msg("error disabling run")
Expand Down Expand Up @@ -173,18 +173,18 @@ func (f *Flags) Post(cfg *config.Instance) {
fmt.Println(resp)
os.Exit(0)
} else if *f.Run != "" || *f.Launch != "" {
data, err := json.Marshal(&models.LaunchParams{
data, err := json.Marshal(&models.RunParams{
Text: f.Run,
})
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Error encoding params: %v\n", err)
os.Exit(1)
}

_, err = client.LocalClient(cfg, models.MethodLaunch, string(data))
_, err = client.LocalClient(cfg, models.MethodRun, string(data))
if err != nil {
log.Error().Err(err).Msg("error launching")
_, _ = fmt.Fprintf(os.Stderr, "Error launching: %v\n", err)
log.Error().Err(err).Msg("error running")
_, _ = fmt.Fprintf(os.Stderr, "Error running: %v\n", err)
os.Exit(1)
} else {
os.Exit(0)
Expand Down
Loading

0 comments on commit 63f8250

Please sign in to comment.