// Extend extends target schema func (schema *Schema) Extend(fromSchema *Schema) error { if schema.Parent == "" { schema.Parent = fromSchema.Parent } if schema.Prefix == "" { schema.Prefix = fromSchema.Prefix } if schema.URL == "" { schema.URL = fromSchema.URL } if schema.NamespaceID == "" { schema.NamespaceID = fromSchema.NamespaceID } schema.JSONSchema["properties"] = util.ExtendMap( util.MaybeMap(schema.JSONSchema["properties"]), util.MaybeMap(fromSchema.JSONSchema["properties"])) schema.JSONSchema["propertiesOrder"] = util.ExtendStringList( util.MaybeStringList(fromSchema.JSONSchema["propertiesOrder"]), util.MaybeStringList(schema.JSONSchema["propertiesOrder"])) MergeAction: for _, action := range fromSchema.Actions { for _, existingAction := range schema.Actions { if action.ID == existingAction.ID { continue MergeAction } } schema.Actions = append(schema.Actions, action) } schema.Metadata = util.ExtendMap(schema.Metadata, fromSchema.Metadata) return schema.Init() }
//GetSchema returns the schema filtered and trimmed for a specific user or nil when the user shouldn't see it at all func GetSchema(s *schema.Schema, authorization schema.Authorization) (result *schema.Resource, err error) { manager := schema.GetManager() metaschema, _ := manager.Schema("schema") policy, _ := manager.PolicyValidate("read", s.GetPluralURL(), authorization) if policy == nil { return } if s.IsAbstract() { return } rawSchema := s.JSON() filteredSchema := util.ExtendMap(nil, s.JSONSchema) rawSchema["schema"] = filteredSchema schemaProperties, schemaPropertiesOrder, schemaRequired := policy.FilterSchema( util.MaybeMap(s.JSONSchema["properties"]), util.MaybeStringList(s.JSONSchema["propertiesOrder"]), util.MaybeStringList(s.JSONSchema["required"])) filteredSchema["properties"] = schemaProperties filteredSchema["propertiesOrder"] = schemaPropertiesOrder filteredSchema["required"] = schemaRequired result, err = schema.NewResource(metaschema, rawSchema) if err != nil { log.Warning("%s %s", result, err) return } return }
func filterSchemaByPermission(schema map[string]interface{}, permission string) map[string]interface{} { filteredSchema := map[string]interface{}{"type": "object"} filteredProperties := map[string]map[string]interface{}{} filteredRequirements := []string{} for id, property := range util.MaybeMap(schema["properties"]) { propertyMap := util.MaybeMap(property) allowedList := util.MaybeStringList(propertyMap["permission"]) for _, allowed := range allowedList { if allowed == permission { filteredProperties[id] = propertyMap } } } filteredSchema["properties"] = filteredProperties requirements := util.MaybeStringList(schema["required"]) if permission != "create" { // required property is used on only create event requirements = []string{} } for _, requirement := range requirements { if _, ok := filteredProperties[requirement]; ok { filteredRequirements = append(filteredRequirements, requirement) } } filteredSchema["required"] = filteredRequirements filteredSchema["additionalProperties"] = false return filteredSchema }
// Init initializes schema func (schema *Schema) Init() error { if schema.IsAbstract() { return nil } jsonSchema := schema.JSONSchema parent := schema.Parent required := util.MaybeStringList(jsonSchema["required"]) properties := util.MaybeMap(jsonSchema["properties"]) propertiesOrder := util.MaybeStringList(jsonSchema["propertiesOrder"]) if parent != "" && properties[FormatParentID(parent)] == nil { properties[FormatParentID(parent)] = getParentPropertyObj(parent, parent) propertiesOrder = append(propertiesOrder, FormatParentID(parent)) required = append(required, FormatParentID(parent)) } jsonSchema["required"] = required schema.JSONSchemaOnCreate = filterSchemaByPermission(jsonSchema, "create") schema.JSONSchemaOnUpdate = filterSchemaByPermission(jsonSchema, "update") schema.Properties = []Property{} for key := range properties { if !util.ContainsString(propertiesOrder, key) { propertiesOrder = append(propertiesOrder, key) } } jsonSchema["propertiesOrder"] = propertiesOrder for _, id := range propertiesOrder { property, ok := properties[id] if !ok { continue } propertyRequired := util.ContainsString(required, id) propertyObj, err := NewPropertyFromObj(id, property, propertyRequired) if err != nil { return fmt.Errorf("Invalid schema: Properties is missing %v", err) } schema.Properties = append(schema.Properties, *propertyObj) } return nil }
func fixEnumDefaultValue(node map[string]interface{}) { if defaultValue, ok := node["default"]; ok { if enums, ok := node["enum"]; ok { if defaultValueStr, ok := defaultValue.(string); ok { enumsArr := util.MaybeStringList(enums) if !util.ContainsString(enumsArr, defaultValueStr) { delete(node, "default") } } } } }
//NewSchemaFromObj is a constructor for a schema by obj func NewSchemaFromObj(rawTypeData interface{}) (*Schema, error) { typeData := rawTypeData.(map[string]interface{}) metaschema, ok := GetManager().Schema("schema") if ok { err := metaschema.Validate(metaschema.JSONSchema, typeData) if err != nil { return nil, err } } id := util.MaybeString(typeData["id"]) if id == "" { return nil, &typeAssertionError{"id"} } plural := util.MaybeString(typeData["plural"]) if plural == "" { return nil, &typeAssertionError{"plural"} } title := util.MaybeString(typeData["title"]) if title == "" { return nil, &typeAssertionError{"title"} } description := util.MaybeString(typeData["description"]) if description == "" { return nil, &typeAssertionError{"description"} } singular := util.MaybeString(typeData["singular"]) if singular == "" { return nil, &typeAssertionError{"singular"} } schema := NewSchema(id, plural, title, description, singular) schema.Prefix = util.MaybeString(typeData["prefix"]) schema.URL = util.MaybeString(typeData["url"]) schema.Type = util.MaybeString(typeData["type"]) schema.Parent = util.MaybeString(typeData["parent"]) schema.OnParentDeleteCascade, _ = typeData["on_parent_delete_cascade"].(bool) schema.NamespaceID = util.MaybeString(typeData["namespace"]) schema.IsolationLevel = util.MaybeMap(typeData["isolation_level"]) jsonSchema, ok := typeData["schema"].(map[string]interface{}) if !ok { return nil, &typeAssertionError{"schema"} } schema.JSONSchema = jsonSchema schema.Metadata = util.MaybeMap(typeData["metadata"]) schema.Extends = util.MaybeStringList(typeData["extends"]) actions := util.MaybeMap(typeData["actions"]) schema.Actions = []Action{} for actionID, actionBody := range actions { action, err := NewActionFromObject(actionID, actionBody) if err != nil { return nil, err } schema.Actions = append(schema.Actions, action) } if err := schema.Init(); err != nil { return nil, err } return schema, nil }