Files
mq/services/user_config.go
2025-09-18 18:26:35 +05:45

580 lines
20 KiB
Go

package services
import (
"github.com/oarkflow/json"
v2 "github.com/oarkflow/jsonschema"
"github.com/oarkflow/filters"
"github.com/oarkflow/metadata"
)
type Storage struct {
Name string `json:"name" yaml:"name"`
Key string `json:"key" yaml:"key"`
Driver string `json:"driver" yaml:"driver"`
Database string `json:"database" yaml:"database"`
Host string `json:"host" yaml:"host"`
Username string `json:"username" yaml:"username"`
Password string `json:"password" yaml:"password"`
Port int `json:"port" yaml:"port"`
IndexCache int `json:"index_cache" yaml:"index_cache"`
BlockCache int `json:"block_cache" yaml:"block_cache"`
InMemory bool `json:"in_memory" yaml:"in_memory"`
}
type Cache struct {
Name string `json:"name" yaml:"name"`
Key string `json:"key" yaml:"key"`
Driver string `json:"driver" yaml:"driver"`
Database string `json:"database" yaml:"database"`
Host string `json:"host" yaml:"host"`
Username string `json:"username" yaml:"username"`
Password string `json:"password" yaml:"password"`
Prefix string `json:"prefix" yaml:"prefix"`
Port int `json:"port" yaml:"port"`
}
type Credentials struct {
Databases []metadata.Config `json:"databases" yaml:"databases"`
Storages []Storage `json:"storages" yaml:"storages"`
Caches []Cache `json:"caches" yaml:"caches"`
}
type Core struct {
Consts map[string]any `json:"consts" yaml:"consts"`
Enums map[string]map[string]any `json:"enums" yaml:"enums"`
Credentials Credentials `json:"credentials" yaml:"credentials"`
}
type Operation struct {
Role string `json:"role" yaml:"role"`
Actions []string `json:"actions" yaml:"actions"`
}
type Query struct {
File string `json:"file" yaml:"file"`
String string `json:"string" yaml:"string"`
}
type Model struct {
Name string `json:"name" yaml:"name"`
OldName string `json:"old_name" yaml:"old_name"`
Key string `json:"key" yaml:"key"`
Title string `json:"title" yaml:"title"`
Database string `json:"database" yaml:"database"`
ModelType string `json:"model_type" yaml:"model_type"`
StoreFields []string `json:"store_fields" yaml:"store_fields"`
IndexFields []string `json:"index_fields" yaml:"index_fields"`
Query Query `json:"query" yaml:"query"`
Constraints metadata.Constraint `json:"constraints" yaml:"constraints"`
Fields []metadata.Field `json:"fields" yaml:"fields"`
Operations []Operation `json:"operations" yaml:"operations"`
Fulltext bool `json:"fulltext" yaml:"fulltext"`
Files map[string]bool `json:"files" yaml:"files"`
SortField string `json:"sort_field" yaml:"sort_field"`
SortOrder string `json:"sort_order" yaml:"sort_order"`
RestApi bool `json:"rest_api" yaml:"rest_api"`
SoftDelete bool `json:"soft_delete" yaml:"soft_delete"`
Update bool `json:"update" yaml:"update"`
}
type Property struct {
Properties map[string]Property `json:"properties,omitempty" yaml:"properties,omitempty"`
Items *RequestSchema `json:"items,omitempty" yaml:"items,omitempty"`
Type any `json:"type,omitempty" yaml:"type,omitempty"`
Default any `json:"default" yaml:"default"`
In string `json:"in,omitempty" yaml:"in,omitempty"`
AdditionalProperties bool `json:"additionalProperties,omitempty" yaml:"additionalProperties,omitempty"`
}
func (p *Property) UnmarshalJSON(data []byte) error {
type T Property
var pr T
err := json.Unmarshal(data, &pr)
if err != nil {
return err
}
p.Properties = pr.Properties
p.Items = pr.Items
p.In = pr.In
p.AdditionalProperties = pr.AdditionalProperties
switch pr.Type.(type) {
case string:
p.Type = pr.Type.(string)
case []any:
var v []string
for _, i := range pr.Type.([]any) {
v = append(v, i.(string))
}
p.Type = v
}
return nil
}
type Provider struct {
Mapping map[string]any `json:"mapping,omitempty" yaml:"mapping,omitempty"`
UpdateMapping map[string]any `json:"update_mapping,omitempty" yaml:"update_mapping,omitempty"`
InsertMapping map[string]any `json:"insert_mapping,omitempty" yaml:"insert_mapping,omitempty"`
Defaults map[string]any `json:"defaults,omitempty" yaml:"defaults,omitempty"`
ProviderType string `json:"provider_type,omitempty" yaml:"provider_type,omitempty"`
Database string `json:"database,omitempty" yaml:"database,omitempty"`
Source string `json:"source,omitempty" yaml:"source,omitempty"`
}
type Data struct {
Mapping map[string]string `json:"mapping,omitempty" yaml:"mapping,omitempty"`
AdditionalData map[string]any `json:"additional_data,omitempty" yaml:"additional_data,omitempty"`
GeneratedFields []string `json:"generated_fields,omitempty" yaml:"generated_fields,omitempty"`
Conditions map[string]Filter `json:"conditions,omitempty" yaml:"conditions,omitempty"`
Providers []Provider `json:"providers,omitempty" yaml:"providers,omitempty"`
}
type Node struct {
Name string `json:"name,omitempty" yaml:"name,omitempty"`
ID string `json:"id" yaml:"id"`
NodeKey string `json:"node_key" yaml:"node_key"`
Node string `json:"node" yaml:"node"`
Data Data `json:"data" yaml:"data"`
Debug bool `json:"debug" yaml:"debug"`
FirstNode bool `json:"first_node" yaml:"first_node"`
}
type Loop struct {
Label string `json:"label" yaml:"label"`
Source string `json:"source" yaml:"source"`
Target []string `json:"target" yaml:"target"`
}
type Edge struct {
Label string `json:"label" yaml:"label"`
Source string `json:"source" yaml:"source"`
Target []string `json:"target" yaml:"target"`
}
type Branch struct {
ConditionalNodes map[string]string `json:"conditional_nodes" yaml:"conditional_nodes"`
Key string `json:"key" yaml:"key"`
}
type Handler struct {
Name string `json:"name" yaml:"name"`
Key string `json:"key" yaml:"key"`
DisableLog bool `json:"disable_log" yaml:"disable_log"`
Debug bool `json:"debug" yaml:"debug"`
Nodes []Node `json:"nodes,omitempty" yaml:"nodes,omitempty"`
Edges []Edge `json:"edges,omitempty" yaml:"edges,omitempty"`
Branches []Branch `json:"branches,omitempty" yaml:"branches,omitempty"`
Loops []Loop `json:"loops,omitempty" yaml:"loops,omitempty"`
}
type RequestSchema struct {
Properties map[string]Property `json:"properties,omitempty" yaml:"properties,omitempty"`
Items *RequestSchema `json:"items,omitempty" yaml:"items,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
MaxLength int `json:"maxLength,omitempty" yaml:"maxLength,omitempty"`
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
PrimaryKeys []string `json:"primaryKeys,omitempty" yaml:"primaryKeys,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
AdditionalProperties bool `json:"additionalProperties,omitempty" yaml:"additionalProperties,omitempty"`
}
type RestrictedFields struct {
Fields []string `json:"fields" yaml:"fields"`
Roles []string `json:"roles" yaml:"roles"`
}
type Route struct {
Name string `json:"name" yaml:"name"`
Description string `json:"description" yaml:"description"`
Uri string `json:"route_uri" yaml:"route_uri"`
HandlerKey string `json:"handler_key" yaml:"handler_key"`
Method string `json:"route_method" yaml:"route_method"`
Schema []byte `json:"schema" yaml:"schema"`
SchemaFile string `json:"schema_file" yaml:"schema_file"`
Rules map[string]string `json:"rules" yaml:"rules"`
CustomRules []string `json:"custom_rules" yaml:"custom_rules"`
Model string `json:"model" yaml:"model"`
Handler Handler `json:"handler" yaml:"handler"`
Middlewares []Middleware `json:"middlewares" yaml:"middlewares"`
Operation string `json:"operation" yaml:"operation"`
RestrictedFields RestrictedFields `json:"restricted_fields" yaml:"restricted_fields"`
schema *v2.Schema
}
func (r *Route) GetSchema() *v2.Schema {
if r.schema != nil {
return r.schema
}
return nil
}
func (r *Route) SetSchema(schema *v2.Schema) {
r.schema = schema
}
type Schedule struct {
Enable bool `json:"enable" yaml:"enable"`
Interval string `json:"interval" yaml:"interval"`
}
type BackgroundHandler struct {
Queue string `json:"queue" yaml:"queue"`
HandlerKey string `json:"handler_key" yaml:"handler_key"`
Payload json.RawMessage `json:"payload" yaml:"payload"`
Handler Handler `json:"handler" yaml:"handler"`
Schedule *Schedule `json:"schedule" yaml:"schedule"`
}
type Api struct {
Prefix string `json:"prefix" yaml:"prefix"`
Middlewares []Middleware `json:"middlewares" yaml:"middlewares"`
Routes []*Route `json:"routes" yaml:"routes"`
}
type AllowedStatus struct {
Source string `json:"source" yaml:"source"`
Target []string `yaml:"target"`
}
type Transition struct {
Source string `json:"source" yaml:"source"`
Target string `json:"target" yaml:"target"`
Filters map[string]any `json:"filters" yaml:"filters"`
Validators []map[string]any `json:"validators" yaml:"validators"`
Triggers []map[string]any `json:"triggers" yaml:"triggers"`
Actions []map[string]any `json:"actions" yaml:"actions"`
}
type FlowPipeline struct {
ID string `json:"id" yaml:"id"`
Statuses []string `json:"statuses" yaml:"statuses"`
}
type Flow struct {
ID string `json:"id" yaml:"id"`
Service string `json:"service" yaml:"service"`
Entity string `json:"entity" yaml:"entity"`
Model string `json:"model" yaml:"model"`
StatusField string `json:"status_field" yaml:"status_field"`
AggregateBy []string `json:"aggregate_by" yaml:"aggregate_by"`
Statuses []string `json:"statuses" yaml:"statuses"`
AllowedStatuses []AllowedStatus `json:"allowed_statuses" yaml:"allowed_statuses"`
Transitions []Transition `json:"transitions" yaml:"transitions"`
Pipelines []FlowPipeline `json:"pipelines" yaml:"pipelines"`
}
func (f *Flow) GetPipeline(key string) *FlowPipeline {
for _, pipeline := range f.Pipelines {
if pipeline.ID == key {
return &pipeline
}
}
return nil
}
type Middleware struct {
Name string `json:"name" yaml:"name"`
Options json.RawMessage `json:"options" yaml:"options"`
}
type Static struct {
Dir string `json:"dir" yaml:"dir"`
Prefix string `json:"prefix" yaml:"prefix"`
Options struct {
ByteRange bool `json:"byte_range" yaml:"byte_range"`
Compress bool `json:"compress" yaml:"compress"`
Browse bool `json:"browse" yaml:"browse"`
IndexFile string `json:"index_file" yaml:"index_file"`
} `json:"options" yaml:"options"`
}
type RenderConfig struct {
ID string `json:"id" yaml:"id"`
Prefix string `json:"prefix" yaml:"prefix"`
Root string `json:"root" yaml:"root"`
Index string `json:"index" yaml:"index"`
UseIndex bool `json:"use_index" yaml:"use_index"`
Compress bool `json:"compress" yaml:"compress"`
Extension string `json:"extension" yaml:"extension"`
}
type Web struct {
Prefix string `json:"prefix" yaml:"prefix"`
Static *Static `json:"static" yaml:"static"`
Render []*RenderConfig `json:"render" yaml:"render"`
Middlewares []Middleware `json:"middlewares" yaml:"middlewares"`
Apis []Api `json:"apis" yaml:"apis"`
}
type Schema struct {
File string `json:"file" yaml:"file"`
Instance *v2.Schema
}
type Policy struct {
Web Web `json:"web" yaml:"web"`
Models []Model `json:"models" yaml:"models"`
BackgroundHandlers []*BackgroundHandler `json:"background_handlers" yaml:"background_handlers"`
Commands []*GenericCommand `json:"commands"`
Schemas []Schema `json:"schemas" yaml:"schemas"`
Conditions []*filters.Filter `json:"conditions" yaml:"conditions"`
ApplicationRules []*filters.ApplicationRule `json:"application_rules" yaml:"application_rules"`
Handlers []Handler `json:"handlers" yaml:"handlers"`
Flows []Flow `json:"flows" yaml:"flows"`
// Enhanced configuration support
EnhancedHandlers []EnhancedHandler `json:"enhanced_handlers" yaml:"enhanced_handlers"`
EnhancedWorkflows []WorkflowDefinition `json:"enhanced_workflows" yaml:"enhanced_workflows"`
ValidationRules []ValidationServiceConfig `json:"validation_rules" yaml:"validation_rules"`
}
// Enhanced workflow configuration structures
type WorkflowConfig struct {
Engine string `json:"engine" yaml:"engine"`
Version string `json:"version" yaml:"version"`
Timeout string `json:"timeout" yaml:"timeout"`
RetryPolicy *RetryPolicy `json:"retry_policy,omitempty" yaml:"retry_policy,omitempty"`
Metadata map[string]string `json:"metadata,omitempty" yaml:"metadata,omitempty"`
}
type RetryPolicy struct {
MaxAttempts int `json:"max_attempts" yaml:"max_attempts"`
BackoffType string `json:"backoff_type" yaml:"backoff_type"`
InitialDelay string `json:"initial_delay" yaml:"initial_delay"`
}
type WorkflowDefinition struct {
ID string `json:"id" yaml:"id"`
Name string `json:"name" yaml:"name"`
Description string `json:"description" yaml:"description"`
Version string `json:"version" yaml:"version"`
Steps []WorkflowStep `json:"steps" yaml:"steps"`
Metadata map[string]string `json:"metadata,omitempty" yaml:"metadata,omitempty"`
}
type WorkflowStep struct {
ID string `json:"id" yaml:"id"`
Name string `json:"name" yaml:"name"`
Type string `json:"type" yaml:"type"`
Handler string `json:"handler" yaml:"handler"`
Input map[string]any `json:"input,omitempty" yaml:"input,omitempty"`
Condition string `json:"condition,omitempty" yaml:"condition,omitempty"`
Metadata map[string]string `json:"metadata,omitempty" yaml:"metadata,omitempty"`
}
type ValidationRule struct {
Field string `json:"field" yaml:"field"`
Type string `json:"type" yaml:"type"`
Required bool `json:"required" yaml:"required"`
Message string `json:"message" yaml:"message"`
Options map[string]any `json:"options,omitempty" yaml:"options,omitempty"`
}
type ValidationProcessor struct {
Name string `json:"name" yaml:"name"`
Type string `json:"type" yaml:"type"`
Config map[string]any `json:"config,omitempty" yaml:"config,omitempty"`
}
type UserConfig struct {
Core Core `json:"core" yaml:"core"`
Policy Policy `json:"policies" yaml:"policies"`
}
func (c *UserConfig) GetModel(source string) *Model {
for _, model := range c.Policy.Models {
if model.Name == source {
return &model
}
}
return nil
}
func (c *UserConfig) GetSchemaInstance(source string) *Schema {
for _, schema := range c.Policy.Schemas {
if schema.File == source {
return &schema
}
}
return nil
}
func (c *UserConfig) GetRenderConfig(source string) *RenderConfig {
for _, model := range c.Policy.Web.Render {
if model.ID == source {
return model
}
}
return nil
}
func (c *UserConfig) GetEntities() (entities []string) {
for _, model := range c.Policy.Models {
entities = append(entities, model.Name)
}
return
}
func (c *UserConfig) GetDatabase(db string) *metadata.Config {
for _, database := range c.Core.Credentials.Databases {
if database.Key == db {
return &database
}
}
return nil
}
func (c *UserConfig) GetHandler(handlerName string) *Handler {
for _, handler := range c.Policy.Handlers {
if handler.Key == handlerName {
return &handler
}
}
return nil
}
func (c *UserConfig) GetRoute(name string) *Route {
for _, routes := range c.Policy.Web.Apis {
for _, route := range routes.Routes {
if route.Name == name {
return route
}
}
}
return nil
}
func (c *UserConfig) GetHandlerList() (handlers []string) {
for _, handler := range c.Policy.Handlers {
handlers = append(handlers, handler.Key)
}
return
}
func (c *UserConfig) GetSourceDatabase(source string, db ...string) *metadata.Config {
if len(db) > 0 && db[0] != "" {
for _, database := range c.Core.Credentials.Databases {
if database.Key == db[0] {
return &database
}
}
}
model := c.GetModel(source)
if model == nil {
return nil
}
for _, database := range c.Core.Credentials.Databases {
if database.Key == model.Database {
return &database
}
}
return nil
}
func (c *UserConfig) GetCondition(key string) *filters.Filter {
for _, condition := range c.Policy.Conditions {
if condition.Key == key {
return condition
}
}
return nil
}
func (c *UserConfig) GetApplicationRule(key string) *filters.ApplicationRule {
for _, applicationRule := range c.Policy.ApplicationRules {
if applicationRule.Key == key {
return applicationRule
}
}
return nil
}
func (c *UserConfig) GetFlow(key string) *Flow {
for _, flow := range c.Policy.Flows {
if flow.ID == key {
return &flow
}
}
return nil
}
// Enhanced methods for workflow engine integration
// GetEnhancedHandler retrieves an enhanced handler by key
func (c *UserConfig) GetEnhancedHandler(handlerName string) *EnhancedHandler {
for _, handler := range c.Policy.EnhancedHandlers {
if handler.Key == handlerName {
return &handler
}
}
return nil
}
// GetEnhancedHandlerList returns list of all enhanced handler keys
func (c *UserConfig) GetEnhancedHandlerList() (handlers []string) {
for _, handler := range c.Policy.EnhancedHandlers {
handlers = append(handlers, handler.Key)
}
return
}
// GetWorkflowDefinition retrieves a workflow definition by ID
func (c *UserConfig) GetWorkflowDefinition(workflowID string) *WorkflowDefinition {
for _, workflow := range c.Policy.EnhancedWorkflows {
if workflow.ID == workflowID {
return &workflow
}
}
return nil
}
// GetValidationConfig retrieves validation configuration by name
func (c *UserConfig) GetValidationConfig(name string) *ValidationServiceConfig {
for _, config := range c.Policy.ValidationRules {
// Since ValidationServiceConfig doesn't have a name field in enhanced_contracts,
// we'll use the index or a different approach
if len(c.Policy.ValidationRules) > 0 {
return &config
}
}
return nil
}
// IsEnhancedHandler checks if a handler is configured as enhanced
func (c *UserConfig) IsEnhancedHandler(handlerName string) bool {
handler := c.GetEnhancedHandler(handlerName)
return handler != nil && handler.WorkflowEnabled
}
// GetAllHandlers returns both traditional and enhanced handlers
func (c *UserConfig) GetAllHandlers() map[string]any {
handlers := make(map[string]any)
// Add traditional handlers
for _, handler := range c.Policy.Handlers {
handlers[handler.Key] = handler
}
// Add enhanced handlers
for _, handler := range c.Policy.EnhancedHandlers {
handlers[handler.Key] = handler
}
return handlers
}
// GetHandlerByKey returns either traditional or enhanced handler by key
func (c *UserConfig) GetHandlerByKey(key string) any {
// Check traditional handlers first
if handler := c.GetHandler(key); handler != nil {
return *handler
}
// Check enhanced handlers
if handler := c.GetEnhancedHandler(key); handler != nil {
return *handler
}
return nil
}