<think>

Okay, let's see. The problem is that the FastAPI app's login is failing because emails are normalized in one path but not another. So, in the store.py, when saving the user, they are stripping and lowercasing the email. But in the login route (routes.py), when they call login, are they passing the email in a way that gets normalized? Wait, the login function in routes.py just passes the email as is, right? Because the login function calls get_user with the email parameter. So when someone logs in, they submit their email as-is, but when they were saved, the email was lowercased and stripped. So if the login email is, say, "JohnDoe@example.COM" with uppercase and capitals, then get_user would look it up in the USERS dict, which uses lowercase and stripped. But wait, in the save_user function, the email is stored as email.strip().lower(). So when saving, the email is lowercased and stripped of whitespace. But when logging in, the user is passing the email as received, which might have uppercase letters or other characters. So if the login email is "John Doe" with a space, like "johndoe@example.com", then when saving, it's stored as "johndoe@example.com".lower(), which is the same. But if the login email is "John Doe" with a space, then when they log in, they pass that email with the space. But when they were saved, the email was stripped of whitespace and lowercased. Wait, no. The user's email when they save is whatever they input. So if the user registers with "John Doe" as email, then when they save, it's stored as "johndoe@example.com" (assuming they have trailing spaces, like "John Doe  " which is stripped). So the problem is that in the login path, the email is not being normalized. Wait, no. The login function in routes.py is calling get_user with the email parameter as passed. So if the user logs in with an email that has uppercase letters, like "JohnDoe@example.com", then get_user would look for "johndoe@example.com" in the USERS dict. Because get_user uses the key as is. Wait, no. The USERS dict is built by storing the email.strip().lower() as the key. So when you save a user with email "JohnDoe@example.COM", you get_user would look for "JohnDoe@example.COM" in the USERS. But since the key is stored as lowercased and stripped, the stored key would be "johndoe@example.com". So if the login email is "JohnDoe@example.COM", then get_user(email) would return the stored password_hash if the login email matches exactly. But that's not normalized. Wait, the problem states that emails are normalized in one path but not another. So in the save_user function, the email is normalized (lowercase and stripped). But in the login path, the email is not being normalized. So when the user logs in with an email that has uppercase letters or different casing, the login path is not normalizing it, so the stored email (which is lowercase and stripped) doesn't match the login email. So the fix would be to normalize the email in the login path as well. So in the login function in routes.py, when checking, we should process the email parameter by stripping and lowercasing it before looking up in the USERS dict. That way, both paths handle the email in the same way. So the patch would be to modify the login function in routes.py to normalize the email. For example, in the login function, take the email, strip it, lowercase it, then compare to the stored password_hash. Wait, but the stored password_hash is associated with the normalized email. So when you save, you store the normalized email as the key. So when you log in, you need to take the incoming email, normalize it (strip and lowercase), then check if that key exists in USERS. So the login function should process the email parameter. So the current login function is: def login(email, password_hash): stored = get_user(email) return stored == password_hash. But get_user(email) uses the email as the key. So if the login email is "JohnDoe@example.COM", then get_user would look for "JohnDoe@example.COM" in USERS, which would not exist because the stored keys are lowercased and stripped. So the fix is to normalize the email in the login function. So in the login function, process the email by stripping and lowercasing it before checking. So the corrected login function would be: def login(email, password_hash): email_normalized = email.strip().lower() if email_normalized in USERS: return USERS[email_normalized] else: return False. But wait, the current get_user function in store.py uses get, which returns None if not found. So stored would be None, not the password_hash. So the current login function returns stored == password_hash, which would be False (since stored is None). So the problem is that the emails are normalized in the save path but not in the login path. So the login path is using the raw email as the key, but the save path uses the normalized email. So to fix this, the login path should also normalize the email. Therefore, the patch would be to modify the login function in routes.py to normalize the email before checking. So the edited login function would be: def login(email, password_hash): email_normalized = email.strip().lower() if email_normalized in USERS: return USERS[email_normalized] else: return False. Then, the regression test would be to check that a login with an email that has uppercase letters or different cases, or trailing spaces, succeeds. For example, test case: email = "JohnDoe@example.COM", password_hash = USERS["johndoe@example.com"]. The login should return True. So the regression test would be to submit this email and password_hash and expect success. So the exact patch would be in routes.py, modify the login function to normalize the email. The file to edit is routes.py, function login. The patch would add the email normalization. The regression test would be to ensure that login("JohnDoe@example.COM", correct_hash) returns True. So the final answer is to normalize the email in the login function, and the regression test checks that case-insensitive emails log in correctly.

</think>

To resolve the issue where login fails due to inconsistent email normalization, apply the following patch:

**Patch Plan:**

1. **Normalize Email in Login Function:**
   - In `routes.py`, modify the `login` function to normalize the email parameter (strip and lowercase) before checking the password hash.

**File:** `routes.py`
**Function:** `login`
**Patch:**
```python
def login(email, password_hash):
    email_normalized = email.strip().lower()
    if email_normalized in USERS:
        return USERS[email_normalized] == password_hash
    return False
```

**Regression Test:**
- Verify that logging in with an email containing mixed case, spaces, or trailing symbols succeeds:
  ```python
  def test_login_mixed_email():
      test_email = "John Doe  "
      password_hash = save_user(test_email, "hash123")
      result = login(test_email, password_hash)
      assert result is True
  ```

**Explanation:**
- The login function now normalizes the email to match the format used when storing users (lowercase and stripped). This ensures consistency between login and storage paths. The regression test confirms that emails with irregular formatting are handled correctly.