summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnike Arni <aarni@thoughtworks.com>2017-04-18 19:03:19 -0300
committerAnike Arni <aarni@thoughtworks.com>2017-04-19 14:11:43 -0300
commita86e59b026ee875630cfda1f55fe5371947031c2 (patch)
treebf0f638dc394cf00b62d9d6f78ad36ccab3e2923
parent3d394a960f43a87e38c2b8ffcbfc521ec5c759ff (diff)
[#927] Adds email template translation for portuguese
-rw-r--r--service/pixelated/account_recovery.py10
-rw-r--r--service/pixelated/assets/recovery.mail.pt-BR20
-rw-r--r--service/pixelated/resources/backup_account_resource.py7
-rw-r--r--service/pixelated/resources/login_resource.py11
-rw-r--r--service/pixelated/support/language.py24
-rw-r--r--service/test/unit/resources/test_backup_account_resource.py7
-rw-r--r--service/test/unit/resources/test_login_resource.py21
-rw-r--r--service/test/unit/support/test_language.py40
-rw-r--r--service/test/unit/test_account_recovery.py35
9 files changed, 138 insertions, 37 deletions
diff --git a/service/pixelated/account_recovery.py b/service/pixelated/account_recovery.py
index 723d4048..4e8a1583 100644
--- a/service/pixelated/account_recovery.py
+++ b/service/pixelated/account_recovery.py
@@ -15,6 +15,7 @@
# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
import pkg_resources
+import binascii
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.logger import Logger
@@ -28,12 +29,13 @@ log = Logger()
class AccountRecovery(object):
- def __init__(self, session, soledad, smtp_config, backup_email, domain):
+ def __init__(self, session, soledad, smtp_config, backup_email, domain, language='en-US'):
self._bonafide_session = session
self._soledad = soledad
self._smtp_config = smtp_config
self._backup_email = backup_email
self._domain = domain
+ self._language = language
@inlineCallbacks
def update_recovery_code(self):
@@ -72,15 +74,15 @@ class AccountRecovery(object):
log.error('Failed trying to send the email with the recovery code')
raise e
- def _get_recovery_mail(self, code, language='en-US'):
+ def _get_recovery_mail(self, code):
recovery_mail = pkg_resources.resource_filename(
'pixelated.assets',
- 'recovery.mail.%s' % (language))
+ 'recovery.mail.%s' % (self._language))
account_recovery_url = '{}/{}'.format(self._domain, AccountRecoveryResource.BASE_URL)
with open(recovery_mail) as mail_template_file:
return mail_template_file.read().format(
domain=self._domain,
- recovery_code=code,
+ recovery_code=binascii.hexlify(code),
account_recovery_url=account_recovery_url)
diff --git a/service/pixelated/assets/recovery.mail.pt-BR b/service/pixelated/assets/recovery.mail.pt-BR
new file mode 100644
index 00000000..77271b39
--- /dev/null
+++ b/service/pixelated/assets/recovery.mail.pt-BR
@@ -0,0 +1,20 @@
+Olá,
+
+Você está recebendo este email porque você se registrou em um provedor do Pixelated, no {domain}.
+Se algum dia esquecer sua senha, você pode acessar esse link {account_recovery_url} e usar o código abaixo:
+
+{recovery_code}
+
+Esse código é a única forma de recuperar o acesso a sua conta se perder a senha.
+Guarde-o com carinho!!!
+
+Por quê isso é importante?
+
+Pixelated é um cliente de email que respeita sua privacidade e usa criptografia PGP para isso.
+Sua senha também te da acesso as suas chaves, então se você esquecê-la você perderá acesso a sua conta e a habilidade de descriptografar suas mensagens.
+Nós entedemos que esquecer a senha é algo comum, por isso desenvolvemos uma forma mais segura de recuperar sua conta e, consequentemente, um pouco mais chata ;)
+
+Esse código é uma metade do código necesário para recuperar a conta. A outra metade está com o administrador da conta. Se você esquecer a senha, use esse código e o do administrador para recuperar acesso a conta. É como se fosse um cadeado com duas chaves :)
+Você só terá sucesso se tiver ambos os códigos, então, nunca machuca pedir novamente: GUARDE ESSE CÓDIGO!
+
+PS: Se você não criou uma conta no site {domain}, por favor ignore esse email.
diff --git a/service/pixelated/resources/backup_account_resource.py b/service/pixelated/resources/backup_account_resource.py
index ec3e9dee..94129122 100644
--- a/service/pixelated/resources/backup_account_resource.py
+++ b/service/pixelated/resources/backup_account_resource.py
@@ -25,6 +25,7 @@ from twisted.web.template import Element, XMLFile, renderElement
from pixelated.resources import BaseResource
from pixelated.resources import get_protected_static_folder
from pixelated.account_recovery import AccountRecovery
+from pixelated.support.language import parse_accept_language
class BackupAccountPage(Element):
@@ -56,7 +57,8 @@ class BackupAccountResource(BaseResource):
self.soledad(request),
self._service(request, '_leap_session').smtp_config,
self._get_backup_email(request),
- self._leap_provider.server_name)
+ self._leap_provider.server_name,
+ language=self._get_language(request))
def update_response(response):
request.setResponseCode(NO_CONTENT)
@@ -72,3 +74,6 @@ class BackupAccountResource(BaseResource):
def _get_backup_email(self, request):
return json.loads(request.content.getvalue()).get('backupEmail')
+
+ def _get_language(self, request):
+ return parse_accept_language(request.getAllHeaders())
diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py
index 45942ea6..5b0b70d0 100644
--- a/service/pixelated/resources/login_resource.py
+++ b/service/pixelated/resources/login_resource.py
@@ -22,6 +22,8 @@ from pixelated.config.leap import BootstrapUserServices
from pixelated.resources import BaseResource, UnAuthorizedResource, IPixelatedSession
from pixelated.resources.account_recovery_resource import AccountRecoveryResource
from pixelated.resources import get_public_static_folder, respond_json
+from pixelated.support.language import parse_accept_language
+
from twisted.cred.error import UnauthorizedLogin
from twisted.internet import defer
from twisted.logger import Logger
@@ -36,15 +38,6 @@ from twisted.web.template import Element, XMLFile, renderElement, renderer
log = Logger()
-def parse_accept_language(all_headers):
- accepted_languages = ['pt-BR', 'en-US']
- languages = all_headers.get('accept-language', '').split(';')[0]
- for language in accepted_languages:
- if language in languages:
- return language
- return 'pt-BR'
-
-
class DisclaimerElement(Element):
loader = XMLFile(FilePath(os.path.join(get_public_static_folder(), '_login_disclaimer_banner.html')))
diff --git a/service/pixelated/support/language.py b/service/pixelated/support/language.py
new file mode 100644
index 00000000..4999bc04
--- /dev/null
+++ b/service/pixelated/support/language.py
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2017 ThoughtWorks, Inc.
+#
+# Pixelated is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pixelated is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
+
+
+def parse_accept_language(all_headers):
+ accepted_languages = ['pt-BR', 'en-US']
+ languages = all_headers.get('accept-language', '').split(';')[0]
+ for language in accepted_languages:
+ if language in languages:
+ return language
+ return 'pt-BR'
diff --git a/service/test/unit/resources/test_backup_account_resource.py b/service/test/unit/resources/test_backup_account_resource.py
index 220e3909..e16fa0e1 100644
--- a/service/test/unit/resources/test_backup_account_resource.py
+++ b/service/test/unit/resources/test_backup_account_resource.py
@@ -44,8 +44,10 @@ class TestBackupAccountResource(unittest.TestCase):
d.addCallback(assert_200_when_user_logged_in)
return d
+ @patch('pixelated.resources.backup_account_resource.parse_accept_language')
@patch('pixelated.resources.backup_account_resource.AccountRecovery')
- def test_post_updates_recovery_code(self, mock_account_recovery_init):
+ def test_post_updates_recovery_code(self, mock_account_recovery_init, mock_language):
+ mock_language.return_value = 'pt-BR'
mock_account_recovery = MagicMock()
mock_account_recovery_init.return_value = mock_account_recovery
mock_account_recovery.update_recovery_code.return_value = defer.succeed("Success")
@@ -61,7 +63,8 @@ class TestBackupAccountResource(unittest.TestCase):
self.resource.soledad(request),
self.resource._service(request, '_leap_session').smtp_config,
self.resource._get_backup_email(request),
- self.leap_provider.server_name)
+ self.leap_provider.server_name,
+ language='pt-BR')
mock_account_recovery.update_recovery_code.assert_called()
d.addCallback(assert_update_recovery_code_called)
diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py
index eaaba1d4..e33b5618 100644
--- a/service/test/unit/resources/test_login_resource.py
+++ b/service/test/unit/resources/test_login_resource.py
@@ -24,30 +24,9 @@ from twisted.trial import unittest
from twisted.web.test.requesthelper import DummyRequest
from pixelated.resources.login_resource import LoginResource, LoginStatusResource
-from pixelated.resources.login_resource import parse_accept_language
from test.unit.resources import DummySite
-class TestParseAcceptLanguage(unittest.TestCase):
- def test_parse_pt_br_simple(self):
- all_headers = {
- 'accept-language': 'pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3'}
- parsed_language = parse_accept_language(all_headers)
- self.assertEqual('pt-BR', parsed_language)
-
- def test_parse_en_us_simple(self):
- all_headers = {
- 'accept-language': 'en-US,en;q=0.8,en-US;q=0.5,en;q=0.3'}
- parsed_language = parse_accept_language(all_headers)
- self.assertEqual('en-US', parsed_language)
-
- def test_parse_pt_br_as_default(self):
- all_headers = {
- 'accept-language': 'de-DE,de;q=0.8,en-US;q=0.5,en;q=0.3'}
- parsed_language = parse_accept_language(all_headers)
- self.assertEqual('pt-BR', parsed_language)
-
-
class TestLoginResource(unittest.TestCase):
def setUp(self):
self.services_factory = mock()
diff --git a/service/test/unit/support/test_language.py b/service/test/unit/support/test_language.py
new file mode 100644
index 00000000..23983b53
--- /dev/null
+++ b/service/test/unit/support/test_language.py
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2017 ThoughtWorks, Inc.
+#
+# Pixelated is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pixelated is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
+
+
+from twisted.trial import unittest
+
+from pixelated.support.language import parse_accept_language
+
+
+class TestParseAcceptLanguage(unittest.TestCase):
+ def test_parse_pt_br_simple(self):
+ all_headers = {
+ 'accept-language': 'pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3'}
+ parsed_language = parse_accept_language(all_headers)
+ self.assertEqual('pt-BR', parsed_language)
+
+ def test_parse_en_us_simple(self):
+ all_headers = {
+ 'accept-language': 'en-US,en;q=0.8,en-US;q=0.5,en;q=0.3'}
+ parsed_language = parse_accept_language(all_headers)
+ self.assertEqual('en-US', parsed_language)
+
+ def test_parse_pt_br_as_default(self):
+ all_headers = {
+ 'accept-language': 'de-DE,de;q=0.8,en-US;q=0.5,en;q=0.3'}
+ parsed_language = parse_accept_language(all_headers)
+ self.assertEqual('pt-BR', parsed_language)
diff --git a/service/test/unit/test_account_recovery.py b/service/test/unit/test_account_recovery.py
index b0edc466..eb7927d0 100644
--- a/service/test/unit/test_account_recovery.py
+++ b/service/test/unit/test_account_recovery.py
@@ -50,6 +50,41 @@ class AccountRecoveryTest(unittest.TestCase):
yield self.account_recovery.update_recovery_code()
self.mock_bonafide_session.update_recovery_code.assert_called_once_with(self.generated_code)
+ @defer.inlineCallbacks
+ def test_creates_recovery_code(self):
+ when(self.account_recovery)._send_mail(ANY).thenReturn(defer.succeed(None))
+ yield self.account_recovery.update_recovery_code()
+ self.mock_soledad.create_recovery_code.assert_called_once()
+
+ @patch('pixelated.account_recovery.smtp.sendmail')
+ @patch('pixelated.account_recovery.pkg_resources.resource_filename')
+ @defer.inlineCallbacks
+ def test_default_email_template(self, mock_resource, mock_sendmail):
+ mock_sendmail.return_value = defer.succeed(None)
+
+ with patch('pixelated.account_recovery.open', mock_open(read_data=''), create=True):
+ yield self.account_recovery.update_recovery_code()
+ mock_resource.assert_called_once_with('pixelated.assets',
+ 'recovery.mail.en-US')
+
+ @patch('pixelated.account_recovery.smtp.sendmail')
+ @patch('pixelated.account_recovery.pkg_resources.resource_filename')
+ @defer.inlineCallbacks
+ def test_portuguese_email_template(self, mock_resource, mock_sendmail):
+ self.account_recovery = AccountRecovery(
+ self.mock_bonafide_session,
+ self.mock_soledad,
+ self.mock_smtp_config,
+ self.backup_email,
+ self.domain,
+ language='pt-BR')
+ mock_sendmail.return_value = defer.succeed(None)
+
+ with patch('pixelated.account_recovery.open', mock_open(read_data=''), create=True):
+ yield self.account_recovery.update_recovery_code()
+ mock_resource.assert_called_once_with('pixelated.assets',
+ 'recovery.mail.pt-BR')
+
@patch('pixelated.account_recovery.smtp.sendmail')
@patch('pixelated.account_recovery.pkg_resources.resource_filename')
@defer.inlineCallbacks