diff options
Diffstat (limited to 'service/pixelated/resources')
-rw-r--r-- | service/pixelated/resources/account_recovery_resource.py | 87 | ||||
-rw-r--r-- | service/pixelated/resources/backup_account_resource.py | 25 | ||||
-rw-r--r-- | service/pixelated/resources/login_resource.py | 14 | ||||
-rw-r--r-- | service/pixelated/resources/root_resource.py | 4 |
4 files changed, 114 insertions, 16 deletions
diff --git a/service/pixelated/resources/account_recovery_resource.py b/service/pixelated/resources/account_recovery_resource.py new file mode 100644 index 00000000..209a7693 --- /dev/null +++ b/service/pixelated/resources/account_recovery_resource.py @@ -0,0 +1,87 @@ +# +# 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/>. + +import os +import json + +from twisted.python.filepath import FilePath +from twisted.web.http import OK, INTERNAL_SERVER_ERROR +from twisted.web.template import Element, XMLFile, renderElement +from twisted.web.server import NOT_DONE_YET +from twisted.internet import defer +from twisted.logger import Logger + +from pixelated.resources import BaseResource +from pixelated.resources import get_public_static_folder + +log = Logger() + + +class InvalidPasswordError(Exception): + pass + + +class AccountRecoveryPage(Element): + loader = XMLFile(FilePath(os.path.join(get_public_static_folder(), 'account_recovery.html'))) + + def __init__(self): + super(AccountRecoveryPage, self).__init__() + + +class AccountRecoveryResource(BaseResource): + BASE_URL = 'account-recovery' + isLeaf = True + + def __init__(self, services_factory): + BaseResource.__init__(self, services_factory) + + def render_GET(self, request): + request.setResponseCode(OK) + return self._render_template(request) + + def _render_template(self, request): + site = AccountRecoveryPage() + return renderElement(request, site) + + def render_POST(self, request): + def success_response(response): + request.setResponseCode(OK) + request.finish() + + def error_response(failure): + log.warn(failure) + request.setResponseCode(INTERNAL_SERVER_ERROR) + request.finish() + + d = self._handle_post(request) + d.addCallbacks(success_response, error_response) + return NOT_DONE_YET + + def _get_post_form(self, request): + return json.loads(request.content.getvalue()) + + def _validate_password(self, password, confirm_password): + return password == confirm_password and len(password) >= 8 and len(password) <= 9999 + + def _handle_post(self, request): + form = self._get_post_form(request) + password = form.get('password') + confirm_password = form.get('confirmPassword') + + if not self._validate_password(password, confirm_password): + return defer.fail(InvalidPasswordError('The user entered an invalid password or confirmation')) + + return defer.succeed('Done!') diff --git a/service/pixelated/resources/backup_account_resource.py b/service/pixelated/resources/backup_account_resource.py index b752b4c7..94129122 100644 --- a/service/pixelated/resources/backup_account_resource.py +++ b/service/pixelated/resources/backup_account_resource.py @@ -15,16 +15,18 @@ # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. import os -from xml.sax import SAXParseException +import json -from pixelated.resources import BaseResource from twisted.python.filepath import FilePath -from pixelated.resources import get_protected_static_folder -from pixelated.account_recovery import AccountRecovery from twisted.web.http import OK, NO_CONTENT, INTERNAL_SERVER_ERROR from twisted.web.server import NOT_DONE_YET 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): loader = XMLFile(FilePath(os.path.join(get_protected_static_folder(), 'backup_account.html'))) @@ -36,9 +38,10 @@ class BackupAccountPage(Element): class BackupAccountResource(BaseResource): isLeaf = True - def __init__(self, services_factory, authenticator): + def __init__(self, services_factory, authenticator, leap_provider): BaseResource.__init__(self, services_factory) self._authenticator = authenticator + self._leap_provider = leap_provider def render_GET(self, request): request.setResponseCode(OK) @@ -51,7 +54,11 @@ class BackupAccountResource(BaseResource): def render_POST(self, request): account_recovery = AccountRecovery( self._authenticator.bonafide_session, - self.soledad(request)) + self.soledad(request), + self._service(request, '_leap_session').smtp_config, + self._get_backup_email(request), + self._leap_provider.server_name, + language=self._get_language(request)) def update_response(response): request.setResponseCode(NO_CONTENT) @@ -64,3 +71,9 @@ class BackupAccountResource(BaseResource): d = account_recovery.update_recovery_code() d.addCallbacks(update_response, error_response) return NOT_DONE_YET + + 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 3e1200d7..5b0b70d0 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -20,7 +20,10 @@ from xml.sax import SAXParseException from pixelated.authentication import Authenticator 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 @@ -35,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'))) @@ -101,6 +95,8 @@ class LoginResource(BaseResource): return self if path == 'status': return LoginStatusResource(self._services_factory) + if path == AccountRecoveryResource.BASE_URL: + return AccountRecoveryResource(self._services_factory) if not self.is_logged_in(request): return UnAuthorizedResource() return NoResource() diff --git a/service/pixelated/resources/root_resource.py b/service/pixelated/resources/root_resource.py index 10d57c6f..896bc24b 100644 --- a/service/pixelated/resources/root_resource.py +++ b/service/pixelated/resources/root_resource.py @@ -23,6 +23,7 @@ from pixelated.resources import BaseResource, UnAuthorizedResource, UnavailableR from pixelated.resources import get_public_static_folder, get_protected_static_folder from pixelated.resources.attachments_resource import AttachmentsResource from pixelated.resources.sandbox_resource import SandboxResource +from pixelated.resources.account_recovery_resource import AccountRecoveryResource from pixelated.resources.backup_account_resource import BackupAccountResource from pixelated.resources.contacts_resource import ContactsResource from pixelated.resources.features_resource import FeaturesResource @@ -91,7 +92,8 @@ class RootResource(BaseResource): def initialize(self, provider=None, disclaimer_banner=None, authenticator=None): self._child_resources.add('assets', File(self._protected_static_folder)) - self._child_resources.add('backup-account', BackupAccountResource(self._services_factory, authenticator)) + self._child_resources.add(AccountRecoveryResource.BASE_URL, AccountRecoveryResource(self._services_factory)) + self._child_resources.add('backup-account', BackupAccountResource(self._services_factory, authenticator, provider)) self._child_resources.add('sandbox', SandboxResource(self._protected_static_folder)) self._child_resources.add('keys', KeysResource(self._services_factory)) self._child_resources.add(AttachmentsResource.BASE_URL, AttachmentsResource(self._services_factory)) |