Add Yaohuo verification-based self-service signup
This commit is contained in:
@@ -7,7 +7,7 @@ from pathlib import Path
|
||||
|
||||
from office365_self_service import create_app, db
|
||||
from office365_self_service.models import AuditEvent, RedemptionCode
|
||||
from office365_self_service.services import Office365Service, ServiceConfigurationError, ServiceOperationError
|
||||
from office365_self_service.services import Office365Service, ServiceConfigurationError, ServiceOperationError, YaohuoVerificationService
|
||||
from office365_self_service.settings import GRAPH_BASE_URL, GRAPH_SCOPE, Settings, TOKEN_ENDPOINT_TEMPLATE, load_settings
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ def build_settings(database_url: str, **overrides) -> Settings:
|
||||
"token_endpoint": TOKEN_ENDPOINT_TEMPLATE.format(tenant_id=tenant_id),
|
||||
"scope": GRAPH_SCOPE,
|
||||
"database_url": database_url,
|
||||
"yaohuo_cookie": "",
|
||||
"yaohuo_message_url": "https://www.yaohuo.me/bbs/messagelist_add.aspx",
|
||||
"yaohuo_verification_enabled": False,
|
||||
"yaohuo_verification_code_ttl_seconds": 600,
|
||||
"validation_errors": (),
|
||||
"warnings": (),
|
||||
}
|
||||
@@ -87,6 +91,20 @@ class FakeGraphClient:
|
||||
self.deleted_users.append(user_id)
|
||||
|
||||
|
||||
class FakeYaohuoService:
|
||||
def __init__(self):
|
||||
self.sent = []
|
||||
|
||||
def generate_code(self) -> str:
|
||||
return "123456"
|
||||
|
||||
def expires_at(self):
|
||||
return datetime(2026, 4, 15, 12, 0, 0, tzinfo=timezone.utc)
|
||||
|
||||
def send_verification_code(self, target_user_id: str, code: str) -> None:
|
||||
self.sent.append((target_user_id, code))
|
||||
|
||||
|
||||
class AppRouteTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
@@ -99,6 +117,7 @@ class AppRouteTests(unittest.TestCase):
|
||||
)
|
||||
self.app.testing = True
|
||||
self.client = self.app.test_client()
|
||||
self.app.extensions["yaohuo_verification_service"] = FakeYaohuoService()
|
||||
|
||||
with self.app.app_context():
|
||||
db.drop_all()
|
||||
@@ -257,6 +276,34 @@ class AppRouteTests(unittest.TestCase):
|
||||
self.assertEqual(response.status_code, 409)
|
||||
self.assertFalse(payload["success"])
|
||||
|
||||
def test_yaohuo_send_verify_and_provision_without_redemption_code(self):
|
||||
response = self.client.post("/api/yaohuo/send-code", json={"targetUserId": "12345"})
|
||||
payload = response.get_json()
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue(payload["success"])
|
||||
self.assertEqual(self.app.extensions["yaohuo_verification_service"].sent, [("12345", "123456")])
|
||||
|
||||
verify = self.client.post("/api/yaohuo/verify", json={"code": "123456"})
|
||||
verify_payload = verify.get_json()
|
||||
self.assertEqual(verify.status_code, 200)
|
||||
self.assertTrue(verify_payload["success"])
|
||||
|
||||
provision = self.client.post("/api/yaohuo/provision", json={"username": "alice"})
|
||||
provision_payload = provision.get_json()
|
||||
self.assertEqual(provision.status_code, 201)
|
||||
self.assertTrue(provision_payload["success"])
|
||||
self.assertEqual(provision_payload["data"]["userPrincipalName"], "alice@example.com")
|
||||
self.assertEqual(self.service.calls, ["alice"])
|
||||
|
||||
def test_yaohuo_provision_requires_verified_session(self):
|
||||
response = self.client.post("/api/yaohuo/provision", json={"username": "alice"})
|
||||
payload = response.get_json()
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertFalse(payload["success"])
|
||||
self.assertEqual(self.service.calls, [])
|
||||
|
||||
|
||||
class ServiceBehaviorTests(unittest.TestCase):
|
||||
def test_create_user_accepts_full_upn_without_default_domain(self):
|
||||
@@ -310,6 +357,17 @@ class ServiceBehaviorTests(unittest.TestCase):
|
||||
self.assertEqual(fake_client.deleted_users, ["user-1"])
|
||||
|
||||
|
||||
class YaohuoServiceTests(unittest.TestCase):
|
||||
def test_generate_code_returns_six_digits(self):
|
||||
settings = build_settings("sqlite:////tmp/unused.db", yaohuo_verification_enabled=True, yaohuo_cookie="cookie")
|
||||
service = YaohuoVerificationService(settings)
|
||||
|
||||
code = service.generate_code()
|
||||
|
||||
self.assertEqual(len(code), 6)
|
||||
self.assertTrue(code.isdigit())
|
||||
|
||||
|
||||
class ModelSerializationTests(unittest.TestCase):
|
||||
def test_redemption_code_serializes_datetimes_as_utc_z(self):
|
||||
code = RedemptionCode(
|
||||
|
||||
Reference in New Issue
Block a user