Generalize email domain handling in documentation and tests (#27)

* Generalize email domain handling in documentation and tests

- Add .worktrees/ to .gitignore for git worktree support
- Update _sanitize_email_for_username docstring to be domain-agnostic
- Change CLAUDE.md example from trailofbits.com to example.com
- Add tests for google.com, gmail.com, corporate, and plus addressing

The code already supported any email domain; this updates docs and
tests to reflect that capability.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Address PR review comments

- Remove redundant trailofbits.com regex, simplify to split("@")[0]
- Rename test to clarify backwards compatibility intent

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
This commit is contained in:
Riccardo Schirone
2026-02-09 19:26:59 +01:00
committed by GitHub
parent 714de47762
commit eae5bc1cf4
4 changed files with 31 additions and 11 deletions
+3
View File
@@ -11,3 +11,6 @@ dropkit/_version.txt
# Virtual environments
.venv
# Git worktrees
.worktrees/
+1 -1
View File
@@ -55,7 +55,7 @@ dropkit/
### Username
- **Derived from DigitalOcean account email**, not configured
- Fetched via `/v2/account`, sanitized for Linux compatibility
- `john.doe@trailofbits.com``john_doe`
- `john.doe@example.com``john_doe`
### SSH Hostname
- All SSH entries use `dropkit.<droplet-name>` format
+5 -8
View File
@@ -117,9 +117,10 @@ class DigitalOceanAPI:
@staticmethod
def _sanitize_email_for_username(email: str) -> str:
"""
Sanitize email address to create a valid username.
Sanitize email address to create a valid Linux username.
Removes @trailofbits.com suffix and replaces special characters.
Extracts the local part (before @) and replaces special characters
with underscores. Ensures the result is a valid Linux username.
Args:
email: Email address from DigitalOcean account
@@ -127,12 +128,8 @@ class DigitalOceanAPI:
Returns:
Sanitized username suitable for Linux user creation
"""
# Remove @trailofbits.com suffix (case insensitive)
username = re.sub(r"@trailofbits\.com$", "", email, flags=re.IGNORECASE)
# If no @trailofbits.com, just take the part before @
if "@" in username:
username = username.split("@")[0]
# Extract local part (before @)
username = email.split("@")[0]
# Replace dots, hyphens, and other special characters with underscores
username = re.sub(r"[^a-z0-9_]", "_", username.lower())
+22 -2
View File
@@ -8,8 +8,8 @@ from dropkit.api import DigitalOceanAPI
class TestDigitalOceanAPI:
"""Tests for DigitalOceanAPI class."""
def test_sanitize_email_for_username_trailofbits(self):
"""Test sanitizing trailofbits.com email."""
def test_sanitize_email_for_username_trailofbits_backwards_compat(self):
"""Test backwards compatibility: trailofbits.com emails still work."""
username = DigitalOceanAPI._sanitize_email_for_username("john.doe@trailofbits.com")
assert username == "john_doe"
@@ -33,6 +33,26 @@ class TestDigitalOceanAPI:
username = DigitalOceanAPI._sanitize_email_for_username("@trailofbits.com")
assert username == "user"
def test_sanitize_email_for_username_google(self):
"""Test sanitizing google.com email."""
username = DigitalOceanAPI._sanitize_email_for_username("jane.smith@google.com")
assert username == "jane_smith"
def test_sanitize_email_for_username_gmail(self):
"""Test sanitizing gmail.com email."""
username = DigitalOceanAPI._sanitize_email_for_username("user123@gmail.com")
assert username == "user123"
def test_sanitize_email_for_username_corporate(self):
"""Test sanitizing corporate email with subdomain."""
username = DigitalOceanAPI._sanitize_email_for_username("dev.ops@corp.company.com")
assert username == "dev_ops"
def test_sanitize_email_for_username_plus_addressing(self):
"""Test sanitizing email with plus addressing (any domain)."""
username = DigitalOceanAPI._sanitize_email_for_username("user+tag@outlook.com")
assert username == "user_tag"
class TestValidatePositiveInt:
"""Tests for _validate_positive_int method."""