diff --git a/routers/admin.py b/routers/admin.py index f5357887..2a31425b 100644 --- a/routers/admin.py +++ b/routers/admin.py @@ -76,6 +76,21 @@ def get_revoked_users(client: Annotated[Auth0Client, Depends(get_auth0_client)], return resp +@router.get("/users/unverified", response_model=list[Auth0UserData]) +def get_unverified_users( + client: Annotated[Auth0Client, Depends(get_auth0_client)], + pagination: Annotated[PaginationParams, Depends(get_pagination_params)], +): + """ + Return users whose email is not verified, using Auth0 search for efficiency. + """ + return client.get_users( + page=pagination.page, + per_page=pagination.per_page, + q="email_verified:false", + ) + + @router.get("/users/{user_id}", response_model=Auth0UserData) def get_user(user_id: Annotated[str, UserIdParam], diff --git a/tests/test_admin.py b/tests/test_admin.py index 488a3387..71eefdbf 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -298,3 +298,20 @@ def test_resend_verification_email(test_client, as_admin_user, mock_auth0_client resp = test_client.post(f"/admin/users/{user.user_id}/verification-email/resend") assert resp.status_code == 200 assert resp.json() == {"message": "Verification email resent."} + + +def test_get_unverified_users(test_client, as_admin_user, mock_auth0_client): + u1 = Auth0UserDataFactory.build(email_verified=False) + u2 = Auth0UserDataFactory.build(email_verified=False) + mock_auth0_client.get_users.return_value = [u1, u2] + + resp = test_client.get("/admin/users/unverified?page=2&per_page=10") + assert resp.status_code == 200 + + mock_auth0_client.get_users.assert_called_once_with( + page=2, per_page=10, q="email_verified:false" + ) + + data = resp.json() + assert len(data) == 2 + assert all(u["email_verified"] is False for u in data)