示例#1
0
文件: sql.go 项目: vozhyk-/gohan
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
}
示例#2
0
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
}
示例#3
0
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
}
示例#4
0
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
}
示例#5
0
//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
}
示例#6
0
文件: sql.go 项目: vozhyk-/gohan
//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
}
示例#7
0
// 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
}
示例#8
0
//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
}