/*! \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; }
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; }
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); }