示例#1
0
static void sorcery_astdb_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len)
{
	const char *family_prefix = data;
	size_t family_len = strlen(family_prefix) + strlen(type) + 1; /* +1 for slash delimiter */
	char family[family_len + 1];
	char tree[prefix_len + 1];
	RAII_VAR(struct ast_db_entry *, entries, NULL, ast_db_freetree);
	struct ast_db_entry *entry;

	snprintf(tree, sizeof(tree), "%.*s", (int) prefix_len, prefix);
	snprintf(family, sizeof(family), "%s/%s", family_prefix, type);

	if (!(entries = ast_db_gettree_by_prefix(family, tree))) {
		return;
	}

	for (entry = entries; entry; entry = entry->next) {
		/* The key in the entry includes the family, so we need to strip it out */
		const char *key = entry->key + family_len + 2;
		RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
		struct ast_json_error error;
		RAII_VAR(void *, object, NULL, ao2_cleanup);
		RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);

		if (!(json = ast_json_load_string(entry->data, &error))
		   || (ast_json_to_ast_variables(json, &objset) != AST_JSON_TO_AST_VARS_CODE_SUCCESS)
		   || !(objset = sorcery_astdb_filter_objectset(objset, sorcery, type))
		   || !(object = ast_sorcery_alloc(sorcery, type, key))
		   || ast_sorcery_objectset_apply(sorcery, object, objset)) {
			return;
		}

		ao2_link(objects, object);
	}
}
示例#2
0
static void *sorcery_astdb_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
{
	const char *prefix = data;
	char family[strlen(prefix) + strlen(type) + 2];
	RAII_VAR(char *, value, NULL, ast_free_ptr);
	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
	struct ast_json_error error;
	RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
	void *object = NULL;

	snprintf(family, sizeof(family), "%s/%s", prefix, type);

	if (ast_db_get_allocated(family, id, &value)
		|| !(json = ast_json_load_string(value, &error))
		|| (ast_json_to_ast_variables(json, &objset) != AST_JSON_TO_AST_VARS_CODE_SUCCESS)
		|| !(objset = sorcery_astdb_filter_objectset(objset, sorcery, type))
		|| !(object = ast_sorcery_alloc(sorcery, type, id))
		|| ast_sorcery_objectset_apply(sorcery, object, objset)) {
		ast_debug(3, "Failed to retrieve object '%s' from astdb\n", id);
		ao2_cleanup(object);
		return NULL;
	}

	return object;
}
示例#3
0
static void sorcery_astdb_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex)
{
	const char *prefix = data;
	char family[strlen(prefix) + strlen(type) + 2];
	char tree[strlen(regex) + 1];
	RAII_VAR(struct ast_db_entry *, entries, NULL, ast_db_freetree);
	regex_t expression;
	struct ast_db_entry *entry;

	snprintf(family, sizeof(family), "%s/%s", prefix, type);

	if (regex[0] == '^') {
		/*
		 * For performance reasons, try to create an astDB prefix
		 * pattern from the regex to reduce the number of entries
		 * retrieved from astDB for regex to then match.
		 */
		if (make_astdb_prefix_pattern(tree, regex)) {
			return;
		}
	} else {
		tree[0] = '\0';
	}

	if (!(entries = ast_db_gettree(family, tree))
		|| regcomp(&expression, regex, REG_EXTENDED | REG_NOSUB)) {
		return;
	}

	for (entry = entries; entry; entry = entry->next) {
		/* The key in the entry includes the family, so we need to strip it out for regex purposes */
		const char *key = entry->key + strlen(family) + 2;
		RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
		struct ast_json_error error;
		RAII_VAR(void *, object, NULL, ao2_cleanup);
		RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);

		if (regexec(&expression, key, 0, NULL, 0)) {
			continue;
		} else if (!(json = ast_json_load_string(entry->data, &error))
			|| (ast_json_to_ast_variables(json, &objset) != AST_JSON_TO_AST_VARS_CODE_SUCCESS)
			|| !(objset = sorcery_astdb_filter_objectset(objset, sorcery, type))
			|| !(object = ast_sorcery_alloc(sorcery, type, key))
			|| ast_sorcery_objectset_apply(sorcery, object, objset)) {
			regfree(&expression);
			return;
		}

		ao2_link(objects, object);
	}

	regfree(&expression);
}
示例#4
0
/*! \brief Internal helper function which retrieves an object, or multiple objects, using fields for criteria */
static void *sorcery_astdb_retrieve_fields_common(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields, struct ao2_container *objects)
{
	const char *prefix = data;
	char family[strlen(prefix) + strlen(type) + 2];
	RAII_VAR(struct ast_db_entry *, entries, NULL, ast_db_freetree);
	struct ast_db_entry *entry;

	snprintf(family, sizeof(family), "%s/%s", prefix, type);

	if (!(entries = ast_db_gettree(family, NULL))) {
		return NULL;
	}

	for (entry = entries; entry; entry = entry->next) {
		const char *key = entry->key + strlen(family) + 2;
		RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
		struct ast_json_error error;
		RAII_VAR(struct ast_variable *, existing, NULL, ast_variables_destroy);
		void *object = NULL;

		if (!(json = ast_json_load_string(entry->data, &error))) {
			return NULL;
		}

		if (ast_json_to_ast_variables(json, &existing) != AST_JSON_TO_AST_VARS_CODE_SUCCESS) {
			return NULL;
		}

		existing = sorcery_astdb_filter_objectset(existing, sorcery, type);

		if (fields && !ast_variable_lists_match(existing, fields, 0)) {
			continue;
		}

		if (!(object = ast_sorcery_alloc(sorcery, type, key)) ||
			ast_sorcery_objectset_apply(sorcery, object, existing)) {
			ao2_cleanup(object);
			return NULL;
		}

		if (!objects) {
			return object;
		}

		ao2_link(objects, object);
		ao2_cleanup(object);
	}

	return NULL;
}
示例#5
0
/*! \brief Internal helper function which retrieves an object, or multiple objects, using fields for criteria */
static void *sorcery_astdb_retrieve_fields_common(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields, struct ao2_container *objects)
{
	const char *prefix = data;
	char family[strlen(prefix) + strlen(type) + 2];
	RAII_VAR(struct ast_db_entry *, entries, NULL, ast_db_freetree);
	RAII_VAR(struct ast_json *, criteria, NULL, ast_json_unref);
	struct ast_db_entry *entry;

	snprintf(family, sizeof(family), "%s/%s", prefix, type);

	if (!(entries = ast_db_gettree(family, NULL)) || (fields && !(criteria = sorcery_objectset_to_json(fields)))) {
		return NULL;
	}

	for (entry = entries; entry; entry = entry->next) {
		const char *key = entry->key + strlen(family) + 2;
		RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
		struct ast_json_error error;
		RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
		void *object = NULL;

		if (!(json = ast_json_load_string(entry->data, &error))) {
			return NULL;
		} else if (criteria && !sorcery_json_equal(json, criteria)) {
			continue;
		} else if (!(objset = sorcery_json_to_objectset(json)) ||
			!(object = ast_sorcery_alloc(sorcery, type, key)) ||
			ast_sorcery_objectset_apply(sorcery, object, objset)) {
			ao2_cleanup(object);
			return NULL;
		}

		if (!objects) {
			return object;
		}

		ao2_link(objects, object);
		ao2_cleanup(object);
	}

	return NULL;
}
static void *sorcery_realtime_retrieve_fields(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields)
{
	const char *family = data;
	RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy);
	RAII_VAR(struct ast_variable *, id, NULL, ast_variables_destroy);
	void *object = NULL;

	if (!(objectset = ast_load_realtime_fields(family, fields))) {
		return NULL;
	}

	objectset = sorcery_realtime_filter_objectset(objectset, &id, sorcery, type);

	if (!id
		|| !(object = ast_sorcery_alloc(sorcery, type, id->value))
		|| ast_sorcery_objectset_apply(sorcery, object, objectset)) {
		return NULL;
	}

	return object;
}
示例#7
0
static void *sorcery_astdb_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
{
	const char *prefix = data;
	char family[strlen(prefix) + strlen(type) + 2];
	RAII_VAR(char *, value, NULL, ast_free_ptr);
	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
	struct ast_json_error error;
	RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
	void *object = NULL;

	snprintf(family, sizeof(family), "%s/%s", prefix, type);

	if (ast_db_get_allocated(family, id, &value) || !(json = ast_json_load_string(value, &error)) ||
		!(objset = sorcery_json_to_objectset(json)) || !(object = ast_sorcery_alloc(sorcery, type, id)) ||
		ast_sorcery_objectset_apply(sorcery, object, objset)) {
		ao2_cleanup(object);
		return NULL;
	}

	return object;
}
static void sorcery_realtime_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields)
{
	const char *family = data;
	RAII_VAR(struct ast_config *, rows, NULL, ast_config_destroy);
	RAII_VAR(struct ast_variable *, all, NULL, ast_variables_destroy);
	struct ast_category *row = NULL;

	if (!fields) {
		char field[strlen(UUID_FIELD) + 6], value[2];

		/* If no fields have been specified we want all rows, so trick realtime into doing it */
		snprintf(field, sizeof(field), "%s LIKE", UUID_FIELD);
		snprintf(value, sizeof(value), "%%");

		if (!(all = ast_variable_new(field, value, ""))) {
			return;
		}

		fields = all;
	}

	if (!(rows = ast_load_realtime_multientry_fields(family, fields))) {
		return;
	}

	while ((row = ast_category_browse_filtered(rows, NULL, row, NULL))) {
		struct ast_variable *objectset = ast_category_detach_variables(row);
		RAII_VAR(struct ast_variable *, id, NULL, ast_variables_destroy);
		RAII_VAR(void *, object, NULL, ao2_cleanup);

		objectset = sorcery_realtime_filter_objectset(objectset, &id, sorcery, type);

		if (id && (object = ast_sorcery_alloc(sorcery, type, id->value)) && !ast_sorcery_objectset_apply(sorcery, object, objectset)) {
			ao2_link(objects, object);
		}

		ast_variables_destroy(objectset);
	}
}
示例#9
0
void ast_ari_asterisk_update_object(struct ast_variable *headers, struct ast_ari_asterisk_update_object_args *args, struct ast_ari_response *response)
{
	RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
	RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
	RAII_VAR(void *, sorcery_obj, NULL, ao2_cleanup);
	struct ast_json *fields;
	struct ast_variable *update_set = NULL;
	int created = 0;

	sorcery = ast_sorcery_retrieve_by_module_name(args->config_class);
	if (!sorcery) {
		ast_ari_response_error(
			response, 404, "Not Found",
			"configClass '%s' not found",
			args->config_class);
		return;
	}

	object_type = ast_sorcery_get_object_type(sorcery, args->object_type);
	if (!object_type) {
		ast_ari_response_error(
			response, 404, "Not Found",
			"objectType '%s' not found",
			args->object_type);
		return;
	}

	sorcery_obj = ast_sorcery_retrieve_by_id(sorcery, args->object_type, args->id);
	if (!sorcery_obj) {
		ast_debug(5, "Sorcery object '%s' does not exist; creating it\n", args->id);
		sorcery_obj = ast_sorcery_alloc(sorcery, args->object_type, args->id);
		if (!sorcery_obj) {
			ast_ari_response_alloc_failed(response);
			return;
		}

		created = 1;
	} else {
		void *copy;

		copy = ast_sorcery_copy(sorcery, sorcery_obj);
		if (!copy) {
			ast_ari_response_alloc_failed(response);
			return;
		}

		ao2_ref(sorcery_obj, -1);
		sorcery_obj = copy;
	}

	fields = ast_json_object_get(args->fields, "fields");
	if (!fields && !created) {
		/* Whoops. We need data. */
		ast_ari_response_error(
			response, 400, "Bad request",
			"Fields must be provided to update object '%s'",
			args->id);
		return;
	} else if (fields) {
		size_t i;

		for (i = 0; i < ast_json_array_size(fields); i++) {
			struct ast_variable *new_var;
			struct ast_json *json_value = ast_json_array_get(fields, i);

			if (!json_value) {
				continue;
			}

			new_var = ast_variable_new(
				ast_json_string_get(ast_json_object_get(json_value, "attribute")),
				ast_json_string_get(ast_json_object_get(json_value, "value")),
				"");
			if (!new_var) {
				ast_variables_destroy(update_set);
				ast_ari_response_alloc_failed(response);
				return;
			}
			ast_variable_list_append(&update_set, new_var);
		}
	}

	/* APPLY! Note that a NULL update_set is fine (and necessary), as it
	 * will force validation on a newly created object.
	 */
	if (ast_sorcery_objectset_apply(sorcery, sorcery_obj, update_set)) {
		ast_variables_destroy(update_set);
		ast_ari_response_error(
			response, 400, "Bad request",
			"%s of object '%s' failed field value validation",
			created ? "Creation" : "Update",
			args->id);
		return;
	}

	ast_variables_destroy(update_set);

	if (created) {
		if (ast_sorcery_create(sorcery, sorcery_obj)) {
			ast_ari_response_error(
				response, 403, "Forbidden",
				"Cannot create sorcery objects of type '%s'",
				args->object_type);
			return;
		}
	} else {
		if (ast_sorcery_update(sorcery, sorcery_obj)) {
			ast_ari_response_error(
				response, 403, "Forbidden",
				"Cannot update sorcery objects of type '%s'",
				args->object_type);
			return;
		}
	}

	return_sorcery_object(sorcery, sorcery_obj, response);
}