Files

99 lines
2.9 KiB
Go

package api
import (
"fmt"
"strings"
"connectrpc.com/connect"
apiv1 "github.com/OliveTin/OliveTin/gen/olivetin/api/v1"
authpublic "github.com/OliveTin/OliveTin/internal/auth/authpublic"
"github.com/OliveTin/OliveTin/internal/config"
"github.com/OliveTin/OliveTin/internal/entities"
"github.com/OliveTin/OliveTin/internal/executor"
"github.com/OliveTin/OliveTin/internal/tpl"
log "github.com/sirupsen/logrus"
)
func validateJustificationRequired(action *config.Action, justification string, user *authpublic.AuthenticatedUser) error {
if !actionRequiresJustificationConfig(action) || justificationProvided(justification, user) {
return nil
}
return fmt.Errorf("justification is required for this action")
}
func actionRequiresJustificationConfig(action *config.Action) bool {
return action != nil && action.RequiresJustification()
}
func justificationProvided(justification string, user *authpublic.AuthenticatedUser) bool {
return strings.TrimSpace(justification) != "" || executor.IsSystemExecution(user)
}
func connectInvalidJustification(err error) error {
return connect.NewError(connect.CodeInvalidArgument, err)
}
func startActionArgumentsFromProto(args []*apiv1.StartActionArgument) map[string]string {
result := make(map[string]string, len(args))
for _, arg := range args {
result[arg.Name] = arg.Value
}
return result
}
func resolveStartJustification(action *config.Action, binding *executor.ActionBinding, clientJustification string, args map[string]string) string {
if strings.TrimSpace(clientJustification) != "" {
return clientJustification
}
return resolveJustificationFromTemplate(action, binding, clientJustification, args)
}
func resolveJustificationFromTemplate(action *config.Action, binding *executor.ActionBinding, fallback string, args map[string]string) string {
templateText := action.JustificationTemplateText()
if templateText == "" {
return fallback
}
resolved, err := tpl.ParseTemplateWithActionContext(templateText, bindingEntity(binding), args)
if err != nil {
log.WithFields(justificationTemplateErrorFields(templateText, binding, err)).Warn("Failed to resolve justification template")
return fallback
}
return resolved
}
func justificationTemplateErrorFields(templateText string, binding *executor.ActionBinding, err error) log.Fields {
fields := log.Fields{
"template": templateText,
"error": err,
}
entity := bindingEntity(binding)
if entity == nil {
return fields
}
fields["entityKey"] = entity.UniqueKey
if binding.Action != nil && binding.Action.Entity != "" {
fields["entityType"] = binding.Action.Entity
}
return fields
}
func bindingEntity(binding *executor.ActionBinding) *entities.Entity {
if binding == nil {
return nil
}
return binding.Entity
}
func restartRequiresJustificationError() error {
return connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("justification is required for this action; use StartAction with a justification instead"))
}