diff --git a/tests/test_api_render.py b/tests/test_api_render.py new file mode 100644 index 00000000..10ce2948 --- /dev/null +++ b/tests/test_api_render.py @@ -0,0 +1,96 @@ +import httpx +import asyncio + +URL = "https://api.render.com/graphql" + +HEADERS = { + "User-Agent": "Mozilla/5.0", + "Content-Type": "application/json", + "origin": "https://dashboard.render.com", + "referer": "https://dashboard.render.com/register", + + # Headers internes obligatoires + "x-render-client-name": "dashboard", + "x-render-client-version": "1.0.0", + "x-render-client-platform": "web", + "x-render-client-build": "production", + "x-render-client-release-channel": "stable" +} + +EMAIL = "dimitri.acteur@outlook.com" + +MUTATIONS = { + "validateEmail": { + "query": """ + mutation validateEmail($email: String!) { + validateEmail(email: $email) { + valid + exists + } + } + """, + "variables": {"email": EMAIL} + }, + + "checkEmail": { + "query": """ + mutation checkEmail($email: String!) { + checkEmail(email: $email) + } + """, + "variables": {"email": EMAIL} + }, + + "validateSignup": { + "query": """ + mutation validateSignup($signup: SignupInput!) { + validateSignup(signup: $signup) + } + """, + "variables": {"signup": {"email": EMAIL}} + }, + + "signUp": { + "query": """ + mutation signUp($signup: SignupInput!) { + signUp(signup: $signup) { + idToken + } + } + """, + "variables": { + "signup": { + "email": EMAIL, + "password": "Test123!", + "inviteCode": "" + } + } + } +} + + +async def test_mutation(name, mutation): + print(f"\n=== Testing mutation: {name} ===") + + payload = { + "operationName": name, + "query": mutation["query"], + "variables": mutation["variables"] + } + + async with httpx.AsyncClient(http2=True, timeout=5) as client: + try: + r = await client.post(URL, json=payload, headers=HEADERS) + print("Status:", r.status_code) + print("Response:", r.text) + except Exception as e: + print("Error:", e) + + +async def main(): + for name, mutation in MUTATIONS.items(): + await test_mutation(name, mutation) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/user_scanner/email_scan/hosting/render.py b/user_scanner/email_scan/hosting/render.py index 6de39860..9b454c0e 100644 --- a/user_scanner/email_scan/hosting/render.py +++ b/user_scanner/email_scan/hosting/render.py @@ -1,4 +1,5 @@ import httpx +import json from user_scanner.core.result import Result @@ -11,49 +12,64 @@ async def _check(email: str) -> Result: "variables": { "signup": { "email": email, - "githubId": "", - "name": "", - "githubToken": "", - "googleId": "", - "gitlabId": "", - "bitbucketId": "", - "inviteCode": "", - "password": "StandardPassword123!", - "newsletterOptIn": False, - "next": "" + "password": "Test123!", + "inviteCode": "" } }, - "query": "mutation signUp($signup: SignupInput!) {\n signUp(signup: $signup) {\n idToken\n __typename\n }\n}\n" + "query": """ + mutation signUp($signup: SignupInput!) { + signUp(signup: $signup) { + idToken + } + } + """ } headers = { - "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", + "User-Agent": "Mozilla/5.0", "Content-Type": "application/json", "origin": "https://dashboard.render.com", "referer": "https://dashboard.render.com/register", - "accept-language": "en-US,en;q=0.9" + + # Headers internes obligatoires + "x-render-client-name": "dashboard", + "x-render-client-version": "1.0.0", + "x-render-client-platform": "web", + "x-render-client-build": "production", + "x-render-client-release-channel": "stable" } - async with httpx.AsyncClient(http2=True, timeout=4.0) as client: + async with httpx.AsyncClient(http2=True, timeout=5) as client: try: response = await client.post(url, json=payload, headers=headers) + data = response.json() - if response.status_code == 429: - return Result.error("Rate limited, use '-d' flag to avoid bot detection") + # Render renvoie toujours une erreur dans "errors" + if "errors" in data: + raw = data["errors"][0]["message"] - data = response.json() - errors = data.get("errors", []) + # Le message est un JSON encodé dans une string + try: + msg = json.loads(raw) + except: + return Result.error(f"Render Error: {raw}") - if errors: - msg = errors[0].get("message", "") - if '"email":"exists"' in msg: + # 1) Compte Render classique + if msg.get("email") == "exists": return Result.taken(url=show_url) - elif '"hcaptcha_token":"invalid"' in msg: + + # 2) Compte OAuth (GitHub / Google) + # Render renvoie "invalid" car l'email n'est pas dans la base "password users" + if msg.get("email") == "invalid": + return Result.taken(url=show_url) + + # 3) Email valide mais non existant + if msg.get("hcaptcha_token") == "invalid": return Result.available(url=show_url) - else: - return Result.error(f"Render Error: {msg}") - return Result.error("Unexpected error, report it via GitHub issues") + return Result.error(f"Render Error: {msg}") + + return Result.error("Unexpected response format from Render") except Exception as e: return Result.error(e)