/*! \brief Internal helper function which returns a filtered objectset. 
 *
 * The following are filtered out of the objectset:
 * \li The id field. This is returned to the caller in an out parameter.
 * \li Fields that are not registered with sorcery.
 *
 * \param objectset Objectset to filter.
 * \param[out] id The ID of the sorcery object, as found in the objectset.
 * \param sorcery The sorcery instance that is requesting an objectset.
 * \param type The object type
 *
 * \return The filtered objectset
 */
static struct ast_variable *sorcery_realtime_filter_objectset(struct ast_variable *objectset, struct ast_variable **id,
		const struct ast_sorcery *sorcery, const char *type)
{
	struct ast_variable *previous = NULL, *field = objectset;
	struct ast_sorcery_object_type *object_type;

	object_type = ast_sorcery_get_object_type(sorcery, type);
	if (!object_type) {
		ast_log(LOG_WARNING, "Unknown sorcery object type %s. Expect errors\n", type);
		/* Continue since we still want to filter out the id */
	}

	while (field) {
		int remove_field = 0;
		int delete_field = 0;

		if (!strcmp(field->name, UUID_FIELD)) {
			*id = field;
			remove_field = 1;
		} else if (object_type &&
				!ast_sorcery_is_object_field_registered(object_type, field->name)) {
			ast_debug(1, "Filtering out realtime field '%s' from retrieval\n", field->name);
			remove_field = 1;
			delete_field = 1;
		}

		if (remove_field) {
			struct ast_variable *removed;

			if (previous) {
				previous->next = field->next;
			} else {
				objectset = field->next;
			}

			removed = field;
			field = field->next;
			removed->next = NULL;
			if (delete_field) {
				ast_variables_destroy(removed);
			}
		} else {
			previous = field;
			field = field->next;
		}
	}

	ao2_cleanup(object_type);

	return objectset;
}
Exemple #2
0
void ast_ari_asterisk_delete_object(struct ast_variable *headers,
	struct ast_ari_asterisk_delete_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);

	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_ari_response_error(
			response, 404, "Not Found",
			"Object with id '%s' not found",
			args->id);
		return;
	}

	if (ast_sorcery_delete(sorcery, sorcery_obj)) {
		ast_ari_response_error(
			response, 403, "Forbidden",
			"Could not delete object with id '%s'",
			args->id);
		return;
	}

	ast_ari_response_no_content(response);
}
/*! \brief Internal helper function which returns a filtered objectset.
 *
 * The following are filtered out of the objectset:
 * \li Fields that are not registered with sorcery.
 *
 * \param objectset Objectset to filter.
 * \param sorcery The sorcery instance that is requesting an objectset.
 * \param type The object type
 *
 * \return The filtered objectset
 */
static struct ast_variable *sorcery_astdb_filter_objectset(struct ast_variable *objectset, const struct ast_sorcery *sorcery,
	const char *type)
{
	struct ast_variable *previous = NULL, *field = objectset;
	struct ast_sorcery_object_type *object_type;

	object_type = ast_sorcery_get_object_type(sorcery, type);
	if (!object_type) {
		ast_log(LOG_WARNING, "Unknown sorcery object type %s. Expect errors\n", type);
		return objectset;
	}

	while (field) {
		struct ast_variable *removed;

		if (ast_sorcery_is_object_field_registered(object_type, field->name)) {
			previous = field;
			field = field->next;
			continue;
		}

		ast_debug(1, "Filtering out astdb field '%s' from retrieval\n", field->name);

		if (previous) {
			previous->next = field->next;
		} else {
			objectset = field->next;
		}

		removed = field;
		field = field->next;
		removed->next = NULL;

		ast_variables_destroy(removed);
	}

	ao2_cleanup(object_type);

	return objectset;
}
Exemple #4
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);
}