fix: service credential provisioning and install reliability
Unit Tests / test (push) Successful in 7m21s
Unit Tests / test (push) Successful in 7m21s
- calendar: create_calendar_user() now writes bcrypt htpasswd entry to data/services/calendar/config/users (the path Radicale reads at /etc/radicale/users); delete_calendar_user() removes the entry - email: create_email_user() calls `docker exec cell-mail setup email add` to register the account in docker-mailserver's Dovecot/Postfix store; delete_email_user() calls the matching `setup email del` — both are non-fatal if the container isn't running - service_composer.install(): pull image separately before up so slow registry pulls don't race with container startup; retry up once on failure so a transient registry hiccup on first install doesn't require the user to manually retry Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -340,12 +340,39 @@ class EmailManager(BaseServiceManager):
|
||||
mailbox_dir = os.path.join(self.email_data_dir, 'mailboxes', f'{username}@{domain}')
|
||||
self.safe_makedirs(mailbox_dir)
|
||||
|
||||
# Provision account in docker-mailserver (non-fatal if container not running)
|
||||
self._dms_add_account(username, domain, password)
|
||||
|
||||
logger.info(f"Created email user: {username}@{domain}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to create email user {username}@{domain}: {e}")
|
||||
return False
|
||||
|
||||
def _dms_add_account(self, username: str, domain: str, password: str) -> None:
|
||||
try:
|
||||
r = subprocess.run(
|
||||
['docker', 'exec', 'cell-mail', 'setup', 'email', 'add',
|
||||
f'{username}@{domain}', password],
|
||||
capture_output=True, text=True, timeout=30, check=False,
|
||||
)
|
||||
if r.returncode != 0:
|
||||
logger.warning('dms add account %s@%s: %s', username, domain, r.stderr.strip())
|
||||
except Exception as e:
|
||||
logger.warning('dms add account %s@%s failed (non-fatal): %s', username, domain, e)
|
||||
|
||||
def _dms_del_account(self, username: str, domain: str) -> None:
|
||||
try:
|
||||
r = subprocess.run(
|
||||
['docker', 'exec', 'cell-mail', 'setup', 'email', 'del',
|
||||
f'{username}@{domain}'],
|
||||
capture_output=True, text=True, timeout=30, check=False,
|
||||
)
|
||||
if r.returncode != 0:
|
||||
logger.warning('dms del account %s@%s: %s', username, domain, r.stderr.strip())
|
||||
except Exception as e:
|
||||
logger.warning('dms del account %s@%s failed (non-fatal): %s', username, domain, e)
|
||||
|
||||
def delete_email_user(self, username: str, domain: str) -> bool:
|
||||
"""Delete an email user"""
|
||||
try:
|
||||
@@ -366,6 +393,7 @@ class EmailManager(BaseServiceManager):
|
||||
import shutil
|
||||
shutil.rmtree(mailbox_dir)
|
||||
|
||||
self._dms_del_account(username, domain)
|
||||
logger.info(f"Deleted email user: {username}@{domain}")
|
||||
return True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user