olivetin/internal/grpcapi/grpcApiActions.go

168 lines
4.0 KiB
Go

package grpcapi
import (
"crypto/sha256"
"fmt"
pb "github.com/OliveTin/OliveTin/gen/grpc"
acl "github.com/OliveTin/OliveTin/internal/acl"
config "github.com/OliveTin/OliveTin/internal/config"
sv "github.com/OliveTin/OliveTin/internal/stringvariables"
log "github.com/sirupsen/logrus"
"strconv"
)
type ActionWithEntity struct {
Action *config.Action
EntityPrefix string
}
var publicActionIdToActionMap map[string]ActionWithEntity
func init() {
publicActionIdToActionMap = make(map[string]ActionWithEntity)
}
func actionsCfgToPb(cfgActions []*config.Action, user *acl.AuthenticatedUser) *pb.GetDashboardComponentsResponse {
res := &pb.GetDashboardComponentsResponse{}
for _, action := range cfgActions {
if !acl.IsAllowedView(cfg, user, action) {
continue
}
if action.Entity != "" {
res.Actions = append(res.Actions, buildActionEntities(action.Entity, action)...)
} else {
btn := actionCfgToPb(action, user)
res.Actions = append(res.Actions, btn)
}
}
return res
}
func buildActionEntities(entityTitle string, tpl *config.Action) []*pb.Action {
ret := make([]*pb.Action, 0)
entityCount, _ := strconv.Atoi(sv.Get("entities." + entityTitle + ".count"))
for i := 0; i < entityCount; i++ {
ret = append(ret, buildEntityAction(tpl, entityTitle, i))
}
return ret
}
func buildEntityAction(tpl *config.Action, entityTitle string, entityIndex int) *pb.Action {
prefix := sv.GetEntityPrefix(entityTitle, entityIndex)
virtualActionId := createPublicID(tpl, prefix)
publicActionIdToActionMap[virtualActionId] = ActionWithEntity{
Action: tpl,
EntityPrefix: prefix,
}
return &pb.Action{
Id: virtualActionId,
Title: sv.ReplaceEntityVars(prefix, tpl.Title),
Icon: tpl.Icon,
PopupOnStart: tpl.PopupOnStart,
}
}
func actionCfgToPb(action *config.Action, user *acl.AuthenticatedUser) *pb.Action {
virtualActionId := createPublicID(action, "")
publicActionIdToActionMap[virtualActionId] = ActionWithEntity{
Action: action,
EntityPrefix: "noent",
}
btn := pb.Action{
Id: virtualActionId,
Title: action.Title,
Icon: action.Icon,
CanExec: acl.IsAllowedExec(cfg, user, action),
PopupOnStart: action.PopupOnStart,
}
for _, cfgArg := range action.Arguments {
pbArg := pb.ActionArgument{
Name: cfgArg.Name,
Title: cfgArg.Title,
Type: cfgArg.Type,
Description: cfgArg.Description,
DefaultValue: cfgArg.Default,
Choices: buildChoices(cfgArg),
Suggestions: cfgArg.Suggestions,
}
btn.Arguments = append(btn.Arguments, &pbArg)
}
return &btn
}
func buildChoices(arg config.ActionArgument) []*pb.ActionArgumentChoice {
if arg.Entity != "" && len(arg.Choices) == 1 {
return buildChoicesEntity(arg.Choices[0], arg.Entity)
} else {
return buildChoicesSimple(arg.Choices)
}
}
func buildChoicesEntity(firstChoice config.ActionArgumentChoice, entityTitle string) []*pb.ActionArgumentChoice {
ret := []*pb.ActionArgumentChoice{}
entityCount := sv.GetEntityCount(entityTitle)
for i := 0; i < entityCount; i++ {
prefix := sv.GetEntityPrefix(entityTitle, i)
ret = append(ret, &pb.ActionArgumentChoice{
Value: sv.ReplaceEntityVars(prefix, firstChoice.Value),
Title: sv.ReplaceEntityVars(prefix, firstChoice.Title),
})
}
return ret
}
func buildChoicesSimple(choices []config.ActionArgumentChoice) []*pb.ActionArgumentChoice {
ret := []*pb.ActionArgumentChoice{}
for _, cfgChoice := range choices {
pbChoice := pb.ActionArgumentChoice{
Value: cfgChoice.Value,
Title: cfgChoice.Title,
}
ret = append(ret, &pbChoice)
}
return ret
}
func createPublicID(action *config.Action, entityPrefix string) string {
if action.Entity == "" {
return action.ID
} else {
h := sha256.New()
h.Write([]byte(action.ID + "." + entityPrefix))
return fmt.Sprintf("%x", h.Sum(nil))
}
}
func findActionByPublicID(id string) *config.Action {
pair, found := publicActionIdToActionMap[id]
if found {
log.Infof("findPublic %v, %v", id, pair.Action.ID)
return pair.Action
}
return nil
}