func addFilterToQuery(s *schema.Schema, q sq.SelectBuilder, filter map[string]interface{}, join bool) (sq.SelectBuilder, error) { if filter == nil { return q, nil } for key, value := range filter { property, err := s.GetPropertyByID(key) if err != nil { return q, err } var column string if join { column = makeColumn(s.GetDbTableName(), *property) } else { column = quote(key) } queryValues, ok := value.([]string) if ok && property.Type == "boolean" { v := make([]bool, len(queryValues)) for i, j := range queryValues { v[i], _ = strconv.ParseBool(j) } q = q.Where(sq.Eq{column: v}) } else { q = q.Where(sq.Eq{column: value}) } } return q, nil }
func addFilterToQuery(s *schema.Schema, q sq.SelectBuilder, filter map[string]interface{}, join bool) sq.SelectBuilder { if filter == nil { return q } for key, value := range filter { property, err := s.GetPropertyByID(key) var column string if join { column = makeColumn(s, *property) } else { column = quote(key) } if err != nil { log.Notice(err.Error()) continue } if property.Type == "boolean" { v := make([]bool, len(value.([]string))) for i, j := range value.([]string) { v[i], _ = strconv.ParseBool(j) } q = q.Where(sq.Eq{column: v}) } else { q = q.Where(sq.Eq{column: value}) } } return q }
func getArgsAsMap(args []string, s *schema.Schema) (map[string]interface{}, error) { if len(args)%2 != 0 { return nil, fmt.Errorf("Parameters should be in [--param-name value]... format") } result := map[string]interface{}{} for i := 0; i < len(args); i += 2 { key := strings.TrimPrefix(args[i], "--") valueType := "string" if property, err := s.GetPropertyByID(key); err == nil { valueType = property.Type } rawValue := args[i+1] var value interface{} var err error if rawValue == "<null>" { value = nil } else { switch valueType { case "integer", "number": value, err = strconv.ParseInt(rawValue, 10, 64) case "boolean": value, err = strconv.ParseBool(rawValue) case "array", "object": err = json.Unmarshal([]byte(rawValue), &value) default: value = rawValue } if err != nil { return nil, fmt.Errorf("Error parsing parameter '%v': %v", key, err) } } result[key] = value } return result, nil }
func (gohanClientCLI *GohanClientCLI) handleRelationArguments(s *schema.Schema, args map[string]interface{}) (map[string]interface{}, error) { parsedArgs := map[string]interface{}{} for arg, value := range args { if arg == s.Parent { parentID, err := gohanClientCLI.getResourceIDForSchemaID(s.Parent, value.(string)) if err != nil { return nil, err } parsedArgs[s.ParentSchemaPropertyID()] = parentID continue } property, _ := s.GetPropertyByID(arg) if property == nil { property, _ = s.GetPropertyByID(arg + "_id") if property != nil && property.Relation != "" { relatedID, err := gohanClientCLI.getResourceIDForSchemaID(property.Relation, value.(string)) if err != nil { return nil, err } parsedArgs[property.ID] = relatedID continue } } parsedArgs[arg] = value } return parsedArgs, nil }
//FilterFromQueryParameter makes list filter from query func FilterFromQueryParameter(resourceSchema *schema.Schema, queryParameters map[string][]string) map[string]interface{} { filter := map[string]interface{}{} for key, value := range queryParameters { if _, err := resourceSchema.GetPropertyByID(key); err != nil { log.Info("Resource %s does not have %s property, ignoring filter.") continue } filter[key] = value } return filter }
//List resources in the db func (tx *Transaction) List(s *schema.Schema, filter transaction.Filter, pg *pagination.Paginator) (list []*schema.Resource, total uint64, err error) { cols := MakeColumns(s, s.GetDbTableName(), true) q := sq.Select(cols...).From(quote(s.GetDbTableName())) q, err = addFilterToQuery(s, q, filter, true) if err != nil { return nil, 0, err } if pg != nil { property, err := s.GetPropertyByID(pg.Key) if err == nil { q = q.OrderBy(makeColumn(s.GetDbTableName(), *property) + " " + pg.Order) if pg.Limit > 0 { q = q.Limit(pg.Limit) } if pg.Offset > 0 { q = q.Offset(pg.Offset) } } } q = makeJoin(s, s.GetDbTableName(), q) sql, args, err := q.ToSql() if err != nil { return } logQuery(sql, args...) rows, err := tx.transaction.Queryx(sql, args...) if err != nil { return } defer rows.Close() list, err = tx.decodeRows(s, rows, list) if err != nil { return nil, 0, err } total, err = tx.count(s, filter) return }
// CreateResource creates the resource specified by the schema and dataMap func CreateResource( context middleware.Context, dataStore db.DB, identityService middleware.IdentityService, resourceSchema *schema.Schema, dataMap map[string]interface{}, ) error { manager := schema.GetManager() // Load environment environmentManager := extension.GetManager() environment, ok := environmentManager.GetEnvironment(resourceSchema.ID) if !ok { return fmt.Errorf("No environment for schema") } auth := context["auth"].(schema.Authorization) //LoadPolicy policy, err := loadPolicy(context, "create", resourceSchema.GetPluralURL(), auth) if err != nil { return err } _, err = resourceSchema.GetPropertyByID("tenant_id") if _, ok := dataMap["tenant_id"]; err == nil && !ok { dataMap["tenant_id"] = context["tenant_id"] } if tenantID, ok := dataMap["tenant_id"]; ok && tenantID != nil { dataMap["tenant_name"], err = identityService.GetTenantName(tenantID.(string)) if err != nil { return ResourceError{err, err.Error(), Unauthorized} } } //Apply policy for api input err = policy.Check(schema.ActionCreate, auth, dataMap) if err != nil { return ResourceError{err, err.Error(), Unauthorized} } delete(dataMap, "tenant_name") // apply property filter err = policy.ApplyPropertyConditionFilter(schema.ActionCreate, dataMap, nil) if err != nil { return ResourceError{err, err.Error(), Unauthorized} } context["resource"] = dataMap if id, ok := dataMap["id"]; !ok || id == "" { dataMap["id"] = uuid.NewV4().String() } context["id"] = dataMap["id"] if err := extension.HandleEvent(context, environment, "pre_create"); err != nil { return err } if resourceData, ok := context["resource"].(map[string]interface{}); ok { dataMap = resourceData } //Validation err = resourceSchema.ValidateOnCreate(dataMap) if err != nil { return ResourceError{err, fmt.Sprintf("Validation error: %s", err), WrongData} } resource, err := manager.LoadResource(resourceSchema.ID, dataMap) if err != nil { return err } //Fillup default err = resource.PopulateDefaults() if err != nil { return err } context["resource"] = resource.Data() if err := InTransaction( context, dataStore, transaction.GetIsolationLevel(resourceSchema, schema.ActionCreate), func() error { return CreateResourceInTransaction(context, resource) }, ); err != nil { return err } if err := extension.HandleEvent(context, environment, "post_create"); err != nil { return err } if err := ApplyPolicyForResource(context, resourceSchema); err != nil { return ResourceError{err, "", Unauthorized} } return nil }
//List resources in the db func (tx *Transaction) List(s *schema.Schema, filter map[string]interface{}, pg *pagination.Paginator) (list []*schema.Resource, total uint64, err error) { db := tx.db db.load() table := db.getTable(s) for _, rawData := range table { data := rawData.(map[string]interface{}) var resource *schema.Resource resource, err = schema.NewResource(s, data) if err != nil { log.Warning("%s %s", resource, err) return } valid := true if filter != nil { for key, value := range filter { if data[key] == nil { continue } property, err := s.GetPropertyByID(key) if err != nil { continue } switch value.(type) { case string: if property.Type == "boolean" { dataBool, err1 := strconv.ParseBool(data[key].(string)) valueBool, err2 := strconv.ParseBool(value.(string)) if err1 != nil || err2 != nil || dataBool != valueBool { valid = false } } else if data[key] != value { valid = false } case []string: if property.Type == "boolean" { v, _ := strconv.ParseBool(data[key].(string)) if !boolInSlice(v, value.([]string)) { valid = false } } if !stringInSlice(fmt.Sprintf("%v", data[key]), value.([]string)) { valid = false } default: if data[key] != value { valid = false } } } } if valid { list = append(list, resource) } if pg != nil { sort.Sort(byPaginator{list, pg}) if pg.Limit > 0 { list = list[:pg.Limit] } } } total = uint64(len(list)) return }