ironoxide 0.26.0

A pure-Rust SDK for accessing IronCore's privacy platform
Documentation
mod common;

use common::{create_id_all_classes, gen_jwt, initialize_sdk};
use galvanic_assert::{matchers::*, *};
use ironoxide::prelude::*;
use std::{convert::TryInto, default::Default};
use uuid::Uuid;
#[tokio::test]
async fn user_verify_non_existing_user() -> Result<(), IronOxideErr> {
    let option_result = IronOxide::user_verify(&gen_jwt(None).0, None).await?;
    assert_eq!(true, option_result.is_none());
    Ok(())
}

#[tokio::test]
async fn user_verify_existing_user() -> Result<(), IronOxideErr> {
    let account_id: UserId = create_id_all_classes("").try_into()?;
    IronOxide::user_create(
        &gen_jwt(Some(account_id.id())).0,
        "foo",
        &Default::default(),
        None,
    )
    .await?;

    let result = IronOxide::user_verify(&gen_jwt(Some(account_id.id())).0, None).await?;
    assert_eq!(true, result.is_some());
    let verify_resp = result.unwrap();

    assert_eq!(&account_id, verify_resp.account_id());
    Ok(())
}

#[tokio::test]
async fn user_verify_after_create_with_needs_rotation() -> Result<(), IronOxideErr> {
    let account_id: UserId = Uuid::new_v4().to_string().try_into()?;
    IronOxide::user_create(
        &gen_jwt(Some(account_id.id())).0,
        "foo",
        &UserCreateOpts::new(true),
        None,
    )
    .await?;

    let result = IronOxide::user_verify(&gen_jwt(Some(account_id.id())).0, None).await?;
    assert!(result.is_some());
    let verify_resp = result.unwrap();
    assert!(verify_resp.needs_rotation());
    Ok(())
}
#[tokio::test]
async fn user_create_good_with_devices() -> Result<(), IronOxideErr> {
    let account_id: UserId = Uuid::new_v4().to_string().try_into()?;
    IronOxide::user_create(
        &gen_jwt(Some(account_id.id())).0,
        "foo",
        &Default::default(),
        None,
    )
    .await?;
    let device: DeviceContext = IronOxide::generate_new_device(
        &gen_jwt(Some(account_id.id())).0,
        "foo",
        &DeviceCreateOpts::new(Some("myDevice".try_into()?)),
        None,
    )
    .await?
    .into();
    let sdk = ironoxide::initialize(&device, &Default::default()).await?;
    let device_list = sdk.user_list_devices().await?;

    assert_eq!(1, device_list.result().len());
    assert_eq!(
        &"myDevice".to_string(),
        device_list.result()[0].name().unwrap().name()
    );
    Ok(())
}

#[tokio::test]
async fn user_private_key_rotation() -> Result<(), IronOxideErr> {
    let io = initialize_sdk().await?;

    let result1 = io.user_rotate_private_key(common::USER_PASSWORD).await?;
    assert_eq!(result1.needs_rotation(), false);

    let result2 = io.user_rotate_private_key(common::USER_PASSWORD).await?;
    assert_ne!(
        &result1.user_master_private_key(),
        &result2.user_master_private_key()
    );

    Ok(())
}

#[tokio::test]
async fn sdk_init_with_private_key_rotation() -> Result<(), IronOxideErr> {
    use ironoxide::InitAndRotationCheck;

    let (user_id, init_result) = common::init_sdk_get_init_result(true).await;
    let _: IronOxide = match init_result {
        InitAndRotationCheck::NoRotationNeeded(_ironoxide) => panic!("user should need rotation"),
        InitAndRotationCheck::RotationNeeded(io, rotation_check) => {
            assert_eq!(rotation_check.user_rotation_needed(), Some(&user_id));
            let rotation_result = io.user_rotate_private_key(common::USER_PASSWORD).await?;
            assert_eq!(rotation_result.needs_rotation(), false);
            io
        }
    };
    Ok(())
}

#[tokio::test]
async fn user_add_device_after_rotation() -> Result<(), IronOxideErr> {
    //create a user
    let (user, sdk) = common::init_sdk_get_user().await;
    let bytes = vec![42u8, 43u8];

    let encrypt_result = sdk
        .document_encrypt(
            &bytes,
            &DocumentEncryptOpts::with_explicit_grants(None, None, true, vec![]),
        )
        .await?;
    let encrypted_data = encrypt_result.encrypted_data();

    //rotate the private key
    let _rotation_result = sdk.user_rotate_private_key(common::USER_PASSWORD).await?;

    //add a new device
    let new_device = IronOxide::generate_new_device(
        &common::gen_jwt(Some(user.id())).0,
        common::USER_PASSWORD,
        &Default::default(),
        None,
    )
    .await?;

    assert_eq!(new_device.created(), new_device.last_updated());
    assert_eq!(new_device.name(), None);

    //reinitialize the sdk with the new device and decrypt some data
    let new_sdk = ironoxide::initialize(&new_device.into(), &Default::default()).await?;
    let decrypt_result = new_sdk.document_decrypt(&encrypted_data).await?;
    let decrypted_data = decrypt_result.decrypted_data();

    assert_eq!(bytes, decrypted_data.to_vec());

    Ok(())
}

#[tokio::test]
async fn user_create_with_needs_rotation() -> Result<(), IronOxideErr> {
    let account_id: UserId = Uuid::new_v4().to_string().try_into()?;
    let result = IronOxide::user_create(
        &gen_jwt(Some(account_id.id())).0,
        common::USER_PASSWORD,
        &UserCreateOpts::new(true),
        None,
    )
    .await;
    assert!(result?.needs_rotation());
    Ok(())
}
#[tokio::test]
async fn generate_device_with_timeout() -> Result<(), IronOxideErr> {
    let result = IronOxide::generate_new_device(
        &common::gen_jwt(None).0,
        "pass",
        &Default::default(),
        Some(std::time::Duration::from_millis(1)),
    )
    .await;

    assert!(result.is_err());
    let err_result = result.unwrap_err();
    dbg!(&err_result);
    assert_that!(&err_result, is_variant!(IronOxideErr::OperationTimedOut));
    assert_that!(
        &err_result,
        has_structure!(IronOxideErr::OperationTimedOut {
            operation: eq(SdkOperation::GenerateNewDevice),
            duration: eq(std::time::Duration::from_millis(1))
        })
    );
    Ok(())
}