[email] Fix email unsubscribe error handling

This commit is contained in:
Cathy Hu 2020-09-06 23:06:52 +02:00
parent 04515dfa76
commit ad4f9fb4fb
3 changed files with 27 additions and 15 deletions

View file

@ -44,8 +44,8 @@ class EmailBot(Censor):
body = ( body = (
'%s\n\n--\n' '%s\n\n--\n'
'If you want to stop receiving these mails,' 'If you want to stop receiving these mails,'
'follow this link: %s/api/hoods/%d/email/unsubscribe/%s' 'follow this link: %s/hoods/%d/email-unsubscribe?token=%s'
) % (message.text, config['root_url'], self.hood.id, token) ) % (message.text, config['frontend_url'], self.hood.id, token)
try: try:
logger.debug('Trying to send: \n%s' % body) logger.debug('Trying to send: \n%s' % body)
email.send_email( email.send_email(

View file

@ -13,6 +13,7 @@ from kibicara.config import config
from kibicara.webapi.admin import from_token, to_token from kibicara.webapi.admin import from_token, to_token
from kibicara.webapi.hoods import get_hood, get_hood_unauthorized from kibicara.webapi.hoods import get_hood, get_hood_unauthorized
from logging import getLogger from logging import getLogger
from nacl import exceptions
from ormantic.exceptions import NoMatch from ormantic.exceptions import NoMatch
from os import urandom from os import urandom
from pydantic import BaseModel, validator from pydantic import BaseModel, validator
@ -188,8 +189,8 @@ async def email_subscribe(
:return: Returns status code 200 after sending confirmation email. :return: Returns status code 200 after sending confirmation email.
""" """
token = to_token(hood=hood.id, email=subscriber.email) token = to_token(hood=hood.id, email=subscriber.email)
confirm_link = '%s/api/hoods/%d/email/subscribe/confirm/%s' % ( confirm_link = '%s/hoods/%d/email-confirm?token=%s' % (
config['root_url'], config['frontend_url'],
hood.id, hood.id,
token, token,
) )
@ -246,15 +247,20 @@ async def email_unsubscribe(token, hood=Depends(get_hood_unauthorized)):
:param token: encrypted JSON token, holds subscriber email + hood.id. :param token: encrypted JSON token, holds subscriber email + hood.id.
:param hood: Hood the Email bot belongs to. :param hood: Hood the Email bot belongs to.
""" """
logger.warning("token is: " + token) try:
payload = from_token(token) logger.warning("token is: " + token)
# If token.hood and url.hood are different, raise an error: payload = from_token(token)
if hood.id is not payload['hood']: # If token.hood and url.hood are different, raise an error:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST) if hood.id is not payload['hood']:
subscriber = await EmailSubscribers.objects.filter( raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)
hood=payload['hood'], email=payload['email'] subscriber = await EmailSubscribers.objects.filter(
).get() hood=payload['hood'], email=payload['email']
await subscriber.delete() ).get()
await subscriber.delete()
except NoMatch:
return HTTPException(status_code=status.HTTP_404_NOT_FOUND)
except exceptions.CryptoError:
return HTTPException(status_code=status.HTTP_400_BAD_REQUEST)
@router.get( @router.get(

View file

@ -22,9 +22,15 @@ def test_email_subscribe_unsubscribe(client, hood_id, receive_email):
r'(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', r'(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+',
body, body,
)[0] )[0]
response = client.post(urlparse(confirm_url).path) response = client.post(
'/api/hoods/%d/email/subscribe/confirm/%s'
% (hood_id, urlparse(confirm_url).query[len('token=') :])
)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
response = client.post(urlparse(confirm_url).path) response = client.post(
'/api/hoods/%d/email/subscribe/confirm/%s'
% (hood_id, urlparse(confirm_url).query[len('token=') :])
)
assert response.status_code == status.HTTP_409_CONFLICT assert response.status_code == status.HTTP_409_CONFLICT
token = to_token(email=mail['to'], hood=hood_id) token = to_token(email=mail['to'], hood=hood_id)
response = client.delete('/api/hoods/%d/email/unsubscribe/%s' % (hood_id, token)) response = client.delete('/api/hoods/%d/email/unsubscribe/%s' % (hood_id, token))