Repository: internetarchive/openlibrary

Issue:
Add real-time validation for emails/screennames taken on IA to prevent random digit appending
<!-- What problem are we solving? What does the experience look like today? What are the symptoms? -->
Patron reports that their chosen username was appended with numbers. The patron was not informed that this would happen during registration and understood the chosen username was available.

### Evidence / Screenshot (if possible)

### Relevant url?
<!-- `https://openlibrary.org/...` -->

### Steps to Reproduce
<!-- What steps caused you to find the bug? -->
According to @mekarpeles , this happens when the [archive.org](http://archive.org/) ID they request is available but the open Library ID is not.

<!-- What actually happened after these steps? What did you expect to happen? -->
* Actual: No warning that the chosen username is not available and will be appended
* Expected: If chosen username is not available warn the patron and give the opportunity to choose a different name.

### Details

- **Logged in (Y/N)?**
- **Browser type/version?**
- **Operating system?**
- **Environment (prod/dev/local)?** prod
<!-- If not sure, put prod -->

### Proposal & Constraints
<!-- What is the proposed solution / implementation? Is there a precedent of this approach succeeding elsewhere? -->

### Related files
<!-- Files related to this issue; this is super useful for new contributors who might want to help! If you're not sure, leave this blank; a maintainer will add them. -->

### Stakeholders
<!-- @ tag stakeholders of this bug -->
@mekarpeles 


Discussion:
Hi @seabelis, I'd like to help solve this issue if it's still open. Please guide. Thanks! 
Perhaps @mekarpeles can provide some guidance on this?
@happycoding47 if you'd like to take a look at the code in openlibrary/account/model.py you should be able to see where this logic is being done within the `audit` function. See if you can propose a better way of doing this!

Resolving patch:
diff --git a/openlibrary/plugins/upstream/account.py b/openlibrary/plugins/upstream/account.py
--- a/openlibrary/plugins/upstream/account.py
+++ b/openlibrary/plugins/upstream/account.py
@@ -2,6 +2,7 @@
 import json
 import logging
 import re
+import requests
 from typing import Any, TYPE_CHECKING, Final
 from collections.abc import Callable
 from collections.abc import Iterable, Mapping
@@ -551,16 +552,29 @@ def GET(self):
 class account_validation(delegate.page):
     path = '/account/validate'
 
+    @staticmethod
+    def ia_username_exists(username):
+        url = "https://archive.org/metadata/@%s" % username
+        try:
+            return bool(requests.get(url).json())
+        except (OSError, ValueError):
+            return
+
     @staticmethod
     def validate_username(username):
         if not 3 <= len(username) <= 20:
             return _('Username must be between 3-20 characters')
         if not re.match('^[A-Za-z0-9-_]{3,20}$', username):
             return _('Username may only contain numbers and letters')
+
         ol_account = OpenLibraryAccount.get(username=username)
         if ol_account:
             return _("Username unavailable")
 
+        ia_account = account_validation.ia_username_exists(username)
+        if ia_account:
+            return _("Username unavailable")
+
     @staticmethod
     def validate_email(email):
         if not (email and re.match(r'.*@.*\..*', email)):
@@ -570,6 +584,10 @@ def validate_email(email):
         if ol_account:
             return _('Email already registered')
 
+        ia_account = InternetArchiveAccount.get(email=email)
+        if ia_account:
+            return _('An Internet Archive account already exists with this email')
+
     def GET(self):
         i = web.input()
         errors = {'email': None, 'username': None}


Test patch: