Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/thunderbird_accounts/mail/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,25 @@ def test_user_without_active_subscription(self, mock_backend_cls):
self.assertFalse(payload['success'])
self.assertEqual(payload['error'], _('An error has occurred while setting up the Appointment CalDAV.'))

@override_settings(APPOINTMENT_CALDAV_SECRET='test-secret-123')
@patch('thunderbird_accounts.mail.views.AccountsOIDCBackend')
@patch('thunderbird_accounts.mail.views.MailClient')
def test_mail_account_not_ready(self, mock_mail_client_cls, mock_backend_cls):
Email.objects.filter(type=Email.EmailType.PRIMARY, account=self.account).delete()
mock_backend = Mock()
mock_backend.get_user_from_access_token.return_value = self.user
mock_backend_cls.return_value = mock_backend

response = self.client.post(
self.url,
data=json.dumps({'appointment-secret': 'test-secret-123', 'oidc-access-token': self.access_token}),
content_type='application/json',
)

self.assertEqual(response.status_code, 409)
self.assertEqual(json.loads(response.content.decode())['code'], 'mail_account_not_ready')
mock_mail_client_cls.assert_not_called()

@override_settings(APPOINTMENT_CALDAV_SECRET='test-secret-123')
@patch('thunderbird_accounts.mail.views.secrets.token_urlsafe')
@patch('thunderbird_accounts.mail.views.AccountsOIDCBackend')
Expand Down
20 changes: 16 additions & 4 deletions src/thunderbird_accounts/mail/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,25 +627,37 @@ def appointment_caldav_setup(request: HttpRequest):
error_response.status_code = 400
return error_response

primary_email = user.stalwart_primary_email
if not primary_email:
logging.info(f'Primary Stalwart email not found during Appointment CalDAV setup for user {user.uuid}')
return JsonResponse(
{
'success': False,
'error': _('Thundermail account setup is still in progress. Please try again shortly.'),
'code': 'mail_account_not_ready',
},
status=409,
)

# Use a special label for the App Password to be used in Appointment's CalDAV auto-setup
label = f'{settings.APPOINTMENT_APP_PASSWORD_PREFIX}{user.stalwart_primary_email}'
label = f'{settings.APPOINTMENT_APP_PASSWORD_PREFIX}{primary_email}'

try:
stalwart_client = MailClient()
email_user = stalwart_client.get_account(user.stalwart_primary_email)
email_user = stalwart_client.get_account(primary_email)

# Remove any existing app password for this label so we can
# replace it with a fresh one.
expected_prefix = f'$app${label}$'
for secret in email_user.get('secrets', []):
if secret.startswith(expected_prefix):
stalwart_client.delete_app_password(user.stalwart_primary_email, secret)
stalwart_client.delete_app_password(primary_email, secret)

# Generate a random base64 password, hash it for Stalwart
# storage, and return the base64 password to the caller for CalDAV auth.
base64_password = secrets.token_urlsafe(64)
app_password_hash = utils.save_app_password(label, base64_password)
stalwart_client.save_app_password(user.stalwart_primary_email, app_password_hash)
stalwart_client.save_app_password(primary_email, app_password_hash)

return JsonResponse({'success': True, 'app_password': base64_password})

Expand Down
Loading