174 lines
4.8 KiB
Go
174 lines
4.8 KiB
Go
package api
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
|
|
apiv1 "github.com/OliveTin/OliveTin/gen/olivetin/api/v1"
|
|
authpublic "github.com/OliveTin/OliveTin/internal/auth/authpublic"
|
|
config "github.com/OliveTin/OliveTin/internal/config"
|
|
"github.com/OliveTin/OliveTin/internal/entities"
|
|
)
|
|
|
|
const (
|
|
defaultEntityInstancesPageSize = 10
|
|
maxEntityInstancesPageSize = 100
|
|
)
|
|
|
|
func (api *oliveTinAPI) buildEntityDefinitionsResponse(user *authpublic.AuthenticatedUser, req *apiv1.GetEntitiesRequest, entityMap entities.EntitiesByClass) []*apiv1.EntityDefinition {
|
|
if req != nil && req.EntityType != "" {
|
|
return api.buildFilteredEntityDefinitions(user, req, entityMap)
|
|
}
|
|
|
|
return api.buildAllEntityDefinitions(user, entityMap)
|
|
}
|
|
|
|
func (api *oliveTinAPI) buildAllEntityDefinitions(user *authpublic.AuthenticatedUser, entityMap entities.EntitiesByClass) []*apiv1.EntityDefinition {
|
|
entityNames := sortedEntityTypeNames(entityMap)
|
|
entityDefinitions := make([]*apiv1.EntityDefinition, 0, len(entityNames))
|
|
|
|
for _, name := range entityNames {
|
|
if !api.userCanViewEntityType(user, name) {
|
|
continue
|
|
}
|
|
|
|
def := api.buildEntityDefinition(name, entityMap[name], false, "", 0, 0)
|
|
entityDefinitions = append(entityDefinitions, def)
|
|
}
|
|
|
|
return entityDefinitions
|
|
}
|
|
|
|
func (api *oliveTinAPI) buildFilteredEntityDefinitions(user *authpublic.AuthenticatedUser, req *apiv1.GetEntitiesRequest, entityMap entities.EntitiesByClass) []*apiv1.EntityDefinition {
|
|
if !api.userCanViewEntityType(user, req.EntityType) {
|
|
return nil
|
|
}
|
|
|
|
entityInstances, ok := entityMap[req.EntityType]
|
|
if !ok || len(entityInstances) == 0 {
|
|
return nil
|
|
}
|
|
|
|
pageSize := normalizeEntityInstancesPageSize(req.PageSize)
|
|
page := normalizeEntityInstancesPage(req.Page)
|
|
def := api.buildEntityDefinition(req.EntityType, entityInstances, true, req.Filter, page, pageSize)
|
|
|
|
return []*apiv1.EntityDefinition{def}
|
|
}
|
|
|
|
func (api *oliveTinAPI) buildEntityDefinition(entityType string, entityInstances map[string]*entities.Entity, paginate bool, filter string, page, pageSize int32) *apiv1.EntityDefinition {
|
|
entityFile := entityFileForType(api.cfg, entityType)
|
|
properties := entityPropertiesFromFile(entityFile)
|
|
instances := buildSortedEntityInstances(entityType, entityInstances, properties)
|
|
|
|
def := &apiv1.EntityDefinition{
|
|
Title: entityType,
|
|
UsedOnDashboards: findDashboardsForEntity(entityType, api.cfg.Dashboards),
|
|
Icon: entityTypeIcon(api.cfg, entityType),
|
|
Properties: entityDefinitionProperties(properties),
|
|
TotalInstances: int32(len(instances)),
|
|
}
|
|
|
|
if !paginate {
|
|
if len(properties) == 0 {
|
|
def.Instances = instances
|
|
}
|
|
return def
|
|
}
|
|
|
|
filtered := filterEntityInstances(instances, filter)
|
|
def.TotalInstances = int32(len(filtered))
|
|
def.Instances = paginateEntityInstances(filtered, page, pageSize)
|
|
return def
|
|
}
|
|
|
|
func sortedEntityTypeNames(entityMap entities.EntitiesByClass) []string {
|
|
entityNames := make([]string, 0, len(entityMap))
|
|
for name := range entityMap {
|
|
entityNames = append(entityNames, name)
|
|
}
|
|
sort.Strings(entityNames)
|
|
return entityNames
|
|
}
|
|
|
|
func normalizeEntityInstancesPage(page int32) int32 {
|
|
if page < 1 {
|
|
return 1
|
|
}
|
|
return page
|
|
}
|
|
|
|
func normalizeEntityInstancesPageSize(pageSize int32) int32 {
|
|
if pageSize < 1 {
|
|
return defaultEntityInstancesPageSize
|
|
}
|
|
if pageSize > maxEntityInstancesPageSize {
|
|
return maxEntityInstancesPageSize
|
|
}
|
|
return pageSize
|
|
}
|
|
|
|
func filterEntityInstances(instances []*apiv1.Entity, filter string) []*apiv1.Entity {
|
|
filter = strings.TrimSpace(strings.ToLower(filter))
|
|
if filter == "" {
|
|
return instances
|
|
}
|
|
|
|
filtered := make([]*apiv1.Entity, 0, len(instances))
|
|
for _, instance := range instances {
|
|
if entityInstanceMatchesFilter(instance, filter) {
|
|
filtered = append(filtered, instance)
|
|
}
|
|
}
|
|
return filtered
|
|
}
|
|
|
|
func entityInstanceMatchesFilter(instance *apiv1.Entity, filter string) bool {
|
|
if instance == nil {
|
|
return false
|
|
}
|
|
|
|
if stringContainsFold(instance.Title, filter) || stringContainsFold(instance.UniqueKey, filter) {
|
|
return true
|
|
}
|
|
|
|
return entityFieldsContainFilter(instance.Fields, filter)
|
|
}
|
|
|
|
func stringContainsFold(value, filter string) bool {
|
|
return strings.Contains(strings.ToLower(value), filter)
|
|
}
|
|
|
|
func entityFieldsContainFilter(fields map[string]string, filter string) bool {
|
|
for _, value := range fields {
|
|
if stringContainsFold(value, filter) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func paginateEntityInstances(instances []*apiv1.Entity, page, pageSize int32) []*apiv1.Entity {
|
|
count := int64(len(instances))
|
|
start := int64(page-1) * int64(pageSize)
|
|
if start >= count {
|
|
return []*apiv1.Entity{}
|
|
}
|
|
|
|
end := start + int64(pageSize)
|
|
if end > count {
|
|
end = count
|
|
}
|
|
|
|
return instances[int(start):int(end)]
|
|
}
|
|
|
|
func entityFieldsForResponse(data any, properties []config.EntityProperty) map[string]string {
|
|
if len(properties) > 0 {
|
|
return entityListFields(data, properties)
|
|
}
|
|
|
|
return serializeEntityFields(data)
|
|
}
|