grant 0.0.1-beta.3

Manage database roles and privileges in GitOps style
Documentation
use assert_cmd::prelude::*; // Add methods on commands
use indoc::indoc;
use predicates::prelude::*; // Used for writing assertions
use std::io::Write; // Write to files
use std::path::PathBuf;
use std::process::Command; // Run programs
use tempfile::NamedTempFile; // Create temporary files

#[test]
fn missing_arguments() {
    let mut cmd = Command::cargo_bin("grant").unwrap();
    cmd.assert().failure();
}

#[test]
/// `grant apply` must have --file or -f args
fn apply_missing_arguments() {
    let mut cmd = Command::cargo_bin("grant").unwrap();
    cmd.arg("apply")
        .assert()
        .failure()
        .stderr(predicate::str::contains("--file"));
}

/// `grant apply` with a config file
#[test]
fn apply_with_config_file() {
    // create a config file
    let _text = indoc! {r#"
        connection:
          type: "postgres"
          url: "postgres://postgres:postgres@localhost:5432/postgres"

        roles:
          - name: role_database_level
            type: database
            grants:
              - CREATE
              - TEMP
            databases:
              - postgres

          - name: role_schema_level
            type: schema
            grants:
              - CREATE
            databases:
              - postgres
            schemas:
              - public
          - name: role_all_schema
            type: table
            grants:
              - SELECT
              - INSERT
              - UPDATE
            databases:
              - postgres
            schemas:
              - public
            tables:
              - ALL

        users:
          - name: duyet
            password: 1234567890
            roles:
              - role_database_level
              - role_all_schema
              - role_schema_level
          - name: duyet2
            password: 1234567890
            roles:
              - role_database_level
              - role_all_schema
              - role_schema_level
    "#};

    let mut file = NamedTempFile::new().expect("failed to create temp file");
    file.write(_text.as_bytes())
        .expect("failed to write to temp file");
    let path = PathBuf::from(file.path().to_str().unwrap());

    let mut cmd = Command::cargo_bin("grant").unwrap();
    cmd.arg("apply")
        .arg("--file")
        .arg(path)
        .assert()
        .success()
        .stderr(predicate::str::contains(
            "Connected to database: postgres://postgres:postgres@localhost:5432/postgres",
        ))
        .stderr(predicate::str::contains("duyet"))
        .stderr(predicate::str::contains("duyet2"))
        // Look like this:
        // ┌────────┬───────────────────────────────────────────────────────────┬─────────┐
        // │ User   │ Database Privilege                                        │ Action  │
        // │ ---    │ ---                                                       │ ---     │
        // │ duyet  │ `role_database_level` for database: ["postgre+ │ updated │
        // │ duyet2 │ `role_database_level` for database: ["postgre+ │ updated │
        // └────────┴───────────────────────────────────────────────────────────┴─────────┘
        .stderr(predicate::str::contains(
            "│ duyet  │ `role_database_level` for database",
        ))
        .stderr(predicate::str::contains(
            "│ duyet2 │ `role_database_level` for database",
        ))
        // Look like this:
        // ┌────────┬───────────────────────────────────────────────────────┬─────────┐
        // │ User   │ Schema Privileges                                     │ Action  │
        // │ ---    │ ---                                                   │ ---     │
        // │ duyet  │ `role_schema_level` for schema: ["public"] │ updated │
        // │ duyet2 │ `role_schema_level` for schema: ["public"] │ updated │
        // └────────┴───────────────────────────────────────────────────────┴─────────┘
        .stderr(predicate::str::contains(
            "│ duyet  │ `role_schema_level` for schema",
        ))
        .stderr(predicate::str::contains(
            "│ duyet2 │ `role_schema_level` for schema",
        ))
        // Look like this:
        // ┌────────┬─────────────────────────────────────────────────┬─────────┐
        // │ User   │ Table Privileges                                │ Action  │
        // │ ---    │ ---                                             │ ---     │
        // │ duyet  │ `role_all_schema` for table: ["ALL"] │ updated │
        // │ duyet2 │ `role_all_schema` for table: ["ALL"] │ updated │
        // └────────┴─────────────────────────────────────────────────┴─────────┘
        .stderr(predicate::str::contains(
            "│ duyet  │ `role_all_schema` for table",
        ))
        .stderr(predicate::str::contains(
            "│ duyet2 │ `role_all_schema` for table",
        ))
        .stderr(predicate::str::contains("Summary"));
}