sql-audit 0.1.0

A companion library to `sql-audit-cli` implementing all of the same functionality, plus useful runtime operations.
Documentation
use sql_audit::{
    generate_audit, query_audit, set_local_app_user, set_local_request_id, AuditRecord,
};

#[async_std::test]
async fn test_e2e() {
    color_eyre::install().unwrap();
    let database_uri = "postgres://postgres:rootpw@localhost/testing";
    let pool = sqlx::PgPool::connect(database_uri).await.unwrap();
    sqlx::query("CREATE TABLE should_be_audited(pk serial primary key, data text)")
        .execute(&pool)
        .await
        .unwrap();
    sqlx::query("CREATE TABLE excluded(pk serial primary key, data text)")
        .execute(&pool)
        .await
        .unwrap();

    generate_audit(&pool, vec!["excluded".to_string()])
        .await
        .unwrap();

    let app_user = "some user";
    let request_id = "my request";
    let should_be_audited = "should_be_audited".to_string();

    sqlx::query("START TRANSACTION;")
        .execute(&pool)
        .await
        .unwrap();
    sqlx::query(&format!(
        "INSERT INTO {} (data) VALUES ('hi')",
        should_be_audited
    ))
    .execute(&pool)
    .await
    .unwrap();
    set_local_app_user(app_user, &pool).await.unwrap();
    set_local_request_id(request_id, &pool).await.unwrap();
    sqlx::query(&format!("UPDATE {} SET data='bye'", should_be_audited))
        .execute(&pool)
        .await
        .unwrap();
    sqlx::query(&format!("DELETE FROM {}", should_be_audited))
        .execute(&pool)
        .await
        .unwrap();
    sqlx::query("INSERT INTO excluded (data) VALUES ('hi')")
        .execute(&pool)
        .await
        .unwrap();
    sqlx::query("UPDATE excluded SET data='bye'")
        .execute(&pool)
        .await
        .unwrap();
    sqlx::query("DELETE FROM excluded")
        .execute(&pool)
        .await
        .unwrap();
    sqlx::query("END TRANSACTION").execute(&pool).await.unwrap();

    let audit_results = query_audit(&pool, &should_be_audited).await.unwrap();
    let expected = vec![
        AuditRecord {
            id: 1,
            table_name: should_be_audited.clone(),
            pk: 1,
            operation: "INSERT".to_string(),
            db_user: "postgres".to_string(),
            app_user: None,
            request_id: None,
            old_val: None,
            new_val: Some(serde_json::json!({
                "pk": 1,
                "data": "hi"
            })),
        },
        AuditRecord {
            id: 2,
            table_name: should_be_audited.clone(),
            pk: 1,
            operation: "UPDATE".to_string(),
            db_user: "postgres".to_string(),
            app_user: Some(app_user.to_string()),
            request_id: Some(request_id.to_string()),
            old_val: Some(serde_json::json!({
                "pk": 1,
                "data": "hi",
            })),
            new_val: Some(serde_json::json!({
                "pk": 1,
                "data": "bye",
            })),
        },
        AuditRecord {
            id: 3,
            table_name: should_be_audited.clone(),
            pk: 1,
            operation: "DELETE".to_string(),
            db_user: "postgres".to_string(),
            app_user: Some(app_user.to_string()),
            request_id: Some(request_id.to_string()),
            old_val: Some(serde_json::json!( {
                "pk": 1,
                "data": "bye",
            })),
            new_val: None,
        },
    ];
    for (index, record) in expected.into_iter().enumerate() {
        assert_eq!(audit_results[index], record);
    }

    let not_audited_results = query_audit(&pool, "excluded").await.unwrap();
    assert_eq!(not_audited_results.len(), 0);
}