Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #5462 from matrix-org/babolivier/account_validity_…
Browse files Browse the repository at this point in the history
…deactivated_accounts_2

Don't send renewal emails to deactivated users (second attempt)
  • Loading branch information
babolivier authored Jun 14, 2019
2 parents 1e7864c + 6d56a69 commit 9b14a81
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 27 deletions.
1 change: 1 addition & 0 deletions changelog.d/5394.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a bug where deactivated users could receive renewal emails if the account validity feature is on.
3 changes: 3 additions & 0 deletions synapse/handlers/account_validity.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ def _send_renewal_email(self, user_id, expiration_ts):
# Stop right here if the user doesn't have at least one email address.
# In this case, they will have to ask their server admin to renew their
# account manually.
# We don't need to do a specific check to make sure the account isn't
# deactivated, as a deactivated account isn't supposed to have any
# email address attached to it.
if not addresses:
return

Expand Down
6 changes: 6 additions & 0 deletions synapse/handlers/deactivate_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def __init__(self, hs):
# it left off (if it has work left to do).
hs.get_reactor().callWhenRunning(self._start_user_parting)

self._account_validity_enabled = hs.config.account_validity.enabled

@defer.inlineCallbacks
def deactivate_account(self, user_id, erase_data, id_server=None):
"""Deactivate a user's account
Expand Down Expand Up @@ -115,6 +117,10 @@ def deactivate_account(self, user_id, erase_data, id_server=None):
# parts users from rooms (if it isn't already running)
self._start_user_parting()

# Remove all information on the user from the account_validity table.
if self._account_validity_enabled:
yield self.store.delete_account_validity_for_user(user_id)

# Mark the user as deactivated.
yield self.store.set_user_deactivated_status(user_id, True)

Expand Down
4 changes: 2 additions & 2 deletions synapse/storage/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,12 +299,12 @@ def _set_expiration_date_when_missing(self):

def select_users_with_no_expiration_date_txn(txn):
"""Retrieves the list of registered users with no expiration date from the
database.
database, filtering out deactivated users.
"""
sql = (
"SELECT users.name FROM users"
" LEFT JOIN account_validity ON (users.name = account_validity.user_id)"
" WHERE account_validity.user_id is NULL;"
" WHERE account_validity.user_id is NULL AND users.deactivated = 0;"
)
txn.execute(sql, [])

Expand Down
14 changes: 14 additions & 0 deletions synapse/storage/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,20 @@ def set_renewal_mail_status(self, user_id, email_sent):
desc="set_renewal_mail_status",
)

@defer.inlineCallbacks
def delete_account_validity_for_user(self, user_id):
"""Deletes the entry for the given user in the account validity table, removing
their expiration date and renewal token.
Args:
user_id (str): ID of the user to remove from the account validity table.
"""
yield self._simple_delete_one(
table="account_validity",
keyvalues={"user_id": user_id},
desc="delete_account_validity_for_user",
)

@defer.inlineCallbacks
def is_server_admin(self, user):
res = yield self._simple_select_one_onecol(
Expand Down
67 changes: 42 additions & 25 deletions tests/rest/client/v2_alpha/test_register.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from synapse.api.errors import Codes
from synapse.appservice import ApplicationService
from synapse.rest.client.v1 import login
from synapse.rest.client.v2_alpha import account_validity, register, sync
from synapse.rest.client.v2_alpha import account, account_validity, register, sync

from tests import unittest

Expand Down Expand Up @@ -308,6 +308,7 @@ class AccountValidityRenewalByEmailTestCase(unittest.HomeserverTestCase):
login.register_servlets,
sync.register_servlets,
account_validity.register_servlets,
account.register_servlets,
]

def make_homeserver(self, reactor, clock):
Expand Down Expand Up @@ -358,20 +359,7 @@ def sendmail(*args, **kwargs):
def test_renewal_email(self):
self.email_attempts = []

user_id = self.register_user("kermit", "monkey")
tok = self.login("kermit", "monkey")
# We need to manually add an email address otherwise the handler will do
# nothing.
now = self.hs.clock.time_msec()
self.get_success(
self.store.user_add_threepid(
user_id=user_id,
medium="email",
address="kermit@example.com",
validated_at=now,
added_at=now,
)
)
(user_id, tok) = self.create_user()

# Move 6 days forward. This should trigger a renewal email to be sent.
self.reactor.advance(datetime.timedelta(days=6).total_seconds())
Expand All @@ -396,6 +384,44 @@ def test_renewal_email(self):
def test_manual_email_send(self):
self.email_attempts = []

(user_id, tok) = self.create_user()
request, channel = self.make_request(
b"POST",
"/_matrix/client/unstable/account_validity/send_mail",
access_token=tok,
)
self.render(request)
self.assertEquals(channel.result["code"], b"200", channel.result)

self.assertEqual(len(self.email_attempts), 1)

def test_deactivated_user(self):
self.email_attempts = []

(user_id, tok) = self.create_user()

request_data = json.dumps({
"auth": {
"type": "m.login.password",
"user": user_id,
"password": "monkey",
},
"erase": False,
})
request, channel = self.make_request(
"POST",
"account/deactivate",
request_data,
access_token=tok,
)
self.render(request)
self.assertEqual(request.code, 200)

self.reactor.advance(datetime.timedelta(days=8).total_seconds())

self.assertEqual(len(self.email_attempts), 0)

def create_user(self):
user_id = self.register_user("kermit", "monkey")
tok = self.login("kermit", "monkey")
# We need to manually add an email address otherwise the handler will do
Expand All @@ -410,16 +436,7 @@ def test_manual_email_send(self):
added_at=now,
)
)

request, channel = self.make_request(
b"POST",
"/_matrix/client/unstable/account_validity/send_mail",
access_token=tok,
)
self.render(request)
self.assertEquals(channel.result["code"], b"200", channel.result)

self.assertEqual(len(self.email_attempts), 1)
return (user_id, tok)

def test_manual_email_send_expired_account(self):
user_id = self.register_user("kermit", "monkey")
Expand Down

0 comments on commit 9b14a81

Please sign in to comment.