backend signup
This commit is contained in:
@@ -3,8 +3,9 @@ mod common;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use axum::body::Body;
|
||||
use axum::http::{header::SET_COOKIE, StatusCode};
|
||||
use backend::models::NewUserMembership;
|
||||
use backend::schema::{tenants, user_memberships};
|
||||
use backend::jobs::JOB_PROVISION_TENANT;
|
||||
use backend::models::{Job, NewUserMembership, TenantStatus};
|
||||
use backend::schema::{jobs, tenants, user_memberships, users};
|
||||
use common::{acquire_db_lock, body_to_vec, TestApp};
|
||||
use diesel::prelude::*;
|
||||
use serde::Deserialize;
|
||||
@@ -81,6 +82,77 @@ async fn login_rejects_unknown_user() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn signup_creates_user_tenant_and_membership() -> Result<()> {
|
||||
let _lock = acquire_db_lock().await;
|
||||
let app = TestApp::new().await?;
|
||||
|
||||
let payload = json!({
|
||||
"username": "signup-user",
|
||||
"password": "super-secret",
|
||||
});
|
||||
|
||||
let response = app.post_json("/api/auth/signup", &payload, None).await?;
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = body_to_vec(response.into_body()).await?;
|
||||
let login: LoginResponse = serde_json::from_slice(&body)?;
|
||||
|
||||
// session works immediately
|
||||
let me = app.get("/api/auth/me", Some(&login.access_token)).await?;
|
||||
assert_eq!(me.status(), StatusCode::OK);
|
||||
|
||||
app.with_conn(|conn| {
|
||||
let user: backend::models::User = users::table
|
||||
.filter(users::username.eq("signup-user"))
|
||||
.first(conn)?;
|
||||
|
||||
let tenant: backend::models::Tenant = tenants::table
|
||||
.filter(tenants::slug.eq("signup-user"))
|
||||
.first(conn)?;
|
||||
|
||||
assert_eq!(tenant.status, TenantStatus::Creating);
|
||||
assert_eq!(tenant.created_by, Some(user.id));
|
||||
|
||||
let membership_exists: bool = diesel::select(diesel::dsl::exists(
|
||||
user_memberships::table
|
||||
.filter(user_memberships::user_id.eq(user.id))
|
||||
.filter(user_memberships::tenant_id.eq(tenant.id)),
|
||||
))
|
||||
.get_result(conn)?;
|
||||
assert!(
|
||||
!membership_exists,
|
||||
"membership should be enqueued, not created synchronously"
|
||||
);
|
||||
|
||||
let job: Job = jobs::table
|
||||
.filter(jobs::tenant_id.eq(tenant.id))
|
||||
.filter(jobs::job_type.eq(JOB_PROVISION_TENANT))
|
||||
.first(conn)
|
||||
.context("provision job missing")?;
|
||||
|
||||
let members = job
|
||||
.payload
|
||||
.get("members")
|
||||
.and_then(|value| value.as_array())
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
|
||||
assert!(members.iter().any(|value| {
|
||||
value
|
||||
.as_str()
|
||||
.and_then(|id| Uuid::parse_str(id).ok())
|
||||
.map(|parsed| parsed == user.id)
|
||||
.unwrap_or(false)
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
|
||||
app.cleanup().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn login_rejects_invalid_password() -> Result<()> {
|
||||
let _lock = acquire_db_lock().await;
|
||||
@@ -198,6 +270,7 @@ async fn login_returns_tenant_selection_when_multiple_memberships() -> Result<()
|
||||
.values((
|
||||
tenants::id.eq(secondary_id),
|
||||
tenants::slug.eq(&slug_for_insert),
|
||||
tenants::status.eq(TenantStatus::Active),
|
||||
))
|
||||
.execute(conn)?;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use axum::Router;
|
||||
use backend::auth::jwt::JwtService;
|
||||
use backend::config::AppConfig;
|
||||
use backend::db::{self, PgPool};
|
||||
use backend::models::{Job, NewUser, NewUserMembership, Tenant};
|
||||
use backend::models::{Job, NewUser, NewUserMembership, Tenant, TenantStatus};
|
||||
use backend::routes;
|
||||
use backend::state::AppState;
|
||||
use backend::storage::ObjectStorage;
|
||||
@@ -278,6 +278,7 @@ impl TestApp {
|
||||
tenants_dsl::slug.eq(&slug_value),
|
||||
tenants_dsl::storage_root.eq(Some(root)),
|
||||
tenants_dsl::quickwit_index.eq(quickwit_value),
|
||||
tenants_dsl::status.eq(TenantStatus::Active),
|
||||
))
|
||||
.execute(conn)
|
||||
.context("failed to insert default tenant")?;
|
||||
|
||||
@@ -2,7 +2,7 @@ mod common;
|
||||
|
||||
use anyhow::Result;
|
||||
use axum::http::StatusCode;
|
||||
use backend::models::{NewUser, NewUserMembership, Tag};
|
||||
use backend::models::{NewUser, NewUserMembership, Tag, TenantStatus};
|
||||
use backend::schema::{
|
||||
tags::dsl as tags_dsl, tenants::dsl as tenants_dsl, user_memberships::dsl as memberships_dsl,
|
||||
users::dsl as users_dsl,
|
||||
@@ -213,6 +213,7 @@ async fn tags_are_isolated_between_tenants() -> Result<()> {
|
||||
tenants_dsl::id.eq(tenant_b_id),
|
||||
tenants_dsl::slug.eq("tenant-b"),
|
||||
tenants_dsl::storage_root.eq(Some(storage_root)),
|
||||
tenants_dsl::status.eq(TenantStatus::Active),
|
||||
))
|
||||
.execute(conn)?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user