lenso-module-auth 0.1.13

First-party auth anchor module for the Lenso backend framework.
Documentation
use auth::models::AuthUserId;
use auth::public::{create_anonymous_user_identity_in_tx, link_identity_to_anonymous_user_in_tx};
use auth::repositories::{AuthUserRepository, PostgresAuthUserRepository};
use chrono::Utc;
use platform_core::{Migration, PLATFORM_MIGRATIONS, apply_migrations};
use platform_testing::TestDatabase;

fn migrations() -> Vec<Migration> {
    PLATFORM_MIGRATIONS
        .iter()
        .chain(auth::migrations::AUTH_MIGRATIONS)
        .copied()
        .collect()
}

#[tokio::test]
async fn linking_provider_identity_marks_anonymous_user_permanent() {
    let Some(db) = TestDatabase::create().await else {
        return;
    };
    apply_migrations(&db.pool, &migrations())
        .await
        .expect("migrations apply");

    let now = Utc::now();
    let user_id = AuthUserId("usr_anonymous_link".to_owned());
    let mut tx = db.pool.begin().await.expect("begin tx");
    create_anonymous_user_identity_in_tx(
        &mut tx,
        user_id.clone(),
        "auth_identity_anonymous_link".to_owned(),
        "anonymous",
        "anon_subject_link",
        now,
    )
    .await
    .expect("anonymous identity");
    tx.commit().await.expect("commit anonymous user");

    let repo = PostgresAuthUserRepository::new(db.pool.clone());
    let anonymous_user = repo
        .find_by_id(&user_id)
        .await
        .expect("find anonymous user")
        .expect("anonymous user exists");
    assert!(anonymous_user.is_anonymous);

    let mut tx = db.pool.begin().await.expect("begin tx");
    let linked = link_identity_to_anonymous_user_in_tx(
        &mut tx,
        &user_id,
        "auth_identity_password_link".to_owned(),
        "password",
        "anon@example.com",
        now,
    )
    .await
    .expect("link password identity");
    tx.commit().await.expect("commit link");

    assert_eq!(linked.user_id, user_id);
    let permanent_user = repo
        .find_by_id(&user_id)
        .await
        .expect("find linked user")
        .expect("linked user exists");
    assert!(!permanent_user.is_anonymous);

    let providers = sqlx::query_scalar::<_, String>(
        r#"
        select provider
        from auth.identities
        where user_id = $1
        order by provider
        "#,
    )
    .bind(&user_id.0)
    .fetch_all(&db.pool)
    .await
    .expect("identity providers");
    assert_eq!(providers, vec!["anonymous", "password"]);

    db.cleanup().await;
}