diff options
Diffstat (limited to 'service/pixelated/resources')
-rw-r--r-- | service/pixelated/resources/__init__.py | 11 | ||||
-rw-r--r-- | service/pixelated/resources/backup_account_resource.py (renamed from service/pixelated/resources/account_recovery_resource.py) | 12 | ||||
-rw-r--r-- | service/pixelated/resources/login_resource.py | 62 | ||||
-rw-r--r-- | service/pixelated/resources/root_resource.py | 23 | ||||
-rw-r--r-- | service/pixelated/resources/session.py | 16 |
5 files changed, 78 insertions, 46 deletions
diff --git a/service/pixelated/resources/__init__.py b/service/pixelated/resources/__init__.py index 6bac2f59..f5512644 100644 --- a/service/pixelated/resources/__init__.py +++ b/service/pixelated/resources/__init__.py @@ -57,12 +57,15 @@ def handle_error_deferred(e, request): request.finish() -def get_startup_folder(): - path = os.path.dirname(os.path.abspath(__file__)) - return os.path.join(path, '..', 'assets') +def get_protected_static_folder(): + return os.path.join(_get_static_folder(), 'protected') -def get_static_folder(): +def get_public_static_folder(): + return os.path.join(_get_static_folder(), 'public') + + +def _get_static_folder(): static_folder = os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "..", "..", "..", "web-ui", "dist")) if not os.path.exists(static_folder): static_folder = os.path.join('/', 'usr', 'share', 'pixelated-user-agent') diff --git a/service/pixelated/resources/account_recovery_resource.py b/service/pixelated/resources/backup_account_resource.py index a69cac9a..f1eeee53 100644 --- a/service/pixelated/resources/account_recovery_resource.py +++ b/service/pixelated/resources/backup_account_resource.py @@ -19,19 +19,19 @@ from xml.sax import SAXParseException from pixelated.resources import BaseResource from twisted.python.filepath import FilePath -from pixelated.resources import get_static_folder +from pixelated.resources import get_protected_static_folder from twisted.web.http import OK from twisted.web.template import Element, XMLFile, renderElement -class AccountRecoveryPage(Element): - loader = XMLFile(FilePath(os.path.join(get_static_folder(), 'account_recovery.html'))) +class BackupAccountPage(Element): + loader = XMLFile(FilePath(os.path.join(get_protected_static_folder(), 'backup_account.html'))) def __init__(self): - super(AccountRecoveryPage, self).__init__() + super(BackupAccountPage, self).__init__() -class AccountRecoveryResource(BaseResource): +class BackupAccountResource(BaseResource): isLeaf = True def __init__(self, services_factory): @@ -42,5 +42,5 @@ class AccountRecoveryResource(BaseResource): return self._render_template(request) def _render_template(self, request): - site = AccountRecoveryPage() + site = BackupAccountPage() return renderElement(request, site) diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index 4d78174f..5adfadf9 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -20,7 +20,7 @@ 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 import handle_error_deferred, get_startup_folder +from pixelated.resources import get_public_static_folder, respond_json from twisted.cred.error import UnauthorizedLogin from twisted.internet import defer from twisted.logger import Logger @@ -45,7 +45,7 @@ def parse_accept_language(all_headers): class DisclaimerElement(Element): - loader = XMLFile(FilePath(os.path.join(get_startup_folder(), '_login_disclaimer_banner.html'))) + loader = XMLFile(FilePath(os.path.join(get_public_static_folder(), '_login_disclaimer_banner.html'))) def __init__(self, banner): super(DisclaimerElement, self).__init__() @@ -68,20 +68,13 @@ class DisclaimerElement(Element): class LoginWebSite(Element): - loader = XMLFile(FilePath(os.path.join(get_startup_folder(), 'login.html'))) + loader = XMLFile(FilePath(os.path.join(get_public_static_folder(), 'login.html'))) - def __init__(self, error_msg=None, disclaimer_banner_file=None): + def __init__(self, disclaimer_banner_file=None): super(LoginWebSite, self).__init__() - self._error_msg = error_msg self.disclaimer_banner_file = disclaimer_banner_file @renderer - def error_msg(self, request, tag): - if self._error_msg is not None: - return tag(self._error_msg) - return tag('') - - @renderer def disclaimer(self, request, tag): return DisclaimerElement(self.disclaimer_banner_file).render(request) @@ -91,14 +84,14 @@ class LoginResource(BaseResource): def __init__(self, services_factory, provider=None, disclaimer_banner=None, authenticator=None): BaseResource.__init__(self, services_factory) - self._startup_folder = get_startup_folder() self._disclaimer_banner = disclaimer_banner self._provider = provider self._authenticator = authenticator or Authenticator(provider) self._bootstrap_user_services = BootstrapUserServices(services_factory, provider) - self.putChild('startup-assets', File(self._startup_folder)) - with open(os.path.join(self._startup_folder, 'Interstitial.html')) as f: + static_folder = get_public_static_folder() + self.putChild('public', File(static_folder)) + with open(os.path.join(static_folder, 'interstitial.html')) as f: self.interstitial = f.read() def getChild(self, path, request): @@ -106,6 +99,8 @@ class LoginResource(BaseResource): return self if path == 'login': return self + if path == 'status': + return LoginStatusResource(self._services_factory) if not self.is_logged_in(request): return UnAuthorizedResource() return NoResource() @@ -114,8 +109,8 @@ class LoginResource(BaseResource): request.setResponseCode(OK) return self._render_template(request) - def _render_template(self, request, error_msg=None): - site = LoginWebSite(error_msg=error_msg, disclaimer_banner_file=self._disclaimer_banner) + def _render_template(self, request): + site = LoginWebSite(disclaimer_banner_file=self._disclaimer_banner) return renderElement(request, site) def render_POST(self, request): @@ -135,12 +130,12 @@ class LoginResource(BaseResource): log.error('Authentication error for %s' % request.args['username'][0]) log.error('%s' % error) request.setResponseCode(UNAUTHORIZED) - return self._render_template(request, 'Invalid username or password') + content = util.redirectTo("/login?auth-error", request) + request.write(content) + request.finish() d = self._handle_login(request) d.addCallbacks(render_response, render_error) - d.addErrback(handle_error_deferred, request) - return NOT_DONE_YET @defer.inlineCallbacks @@ -151,15 +146,32 @@ class LoginResource(BaseResource): defer.returnValue(user_auth) def _complete_bootstrap(self, user_auth, request): - def log_error(error): + def login_error(error, session): log.error('Login error during %s services setup: %s \n %s' % (user_auth.username, error.getErrorMessage(), error.getTraceback())) + session.login_error() - def set_session_cookies(_): - session = IPixelatedSession(request.getSession()) - session.user_uuid = user_auth.uuid + def login_successful(_, session): + session.login_successful(user_auth.uuid) language = parse_accept_language(request.getAllHeaders()) password = request.args['password'][0] + session = IPixelatedSession(request.getSession()) + session.login_started() + d = self._bootstrap_user_services.setup(user_auth, password, language) - d.addCallback(set_session_cookies) - d.addErrback(log_error) + d.addCallback(login_successful, session) + d.addErrback(login_error, session) + + +class LoginStatusResource(BaseResource): + isLeaf = True + + def __init__(self, services_factory): + BaseResource.__init__(self, services_factory) + + def render_GET(self, request): + session = IPixelatedSession(request.getSession()) + status = 'completed' if self._services_factory.mode.is_single_user else str(session.check_login_status()) + + response = {'status': status} + return respond_json(response, request) diff --git a/service/pixelated/resources/root_resource.py b/service/pixelated/resources/root_resource.py index a97bd049..320a1204 100644 --- a/service/pixelated/resources/root_resource.py +++ b/service/pixelated/resources/root_resource.py @@ -20,14 +20,14 @@ from string import Template from pixelated.resources.users import UsersResource from pixelated.resources import BaseResource, UnAuthorizedResource, UnavailableResource -from pixelated.resources import get_startup_folder, get_static_folder +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 from pixelated.resources.feedback_resource import FeedbackResource -from pixelated.resources.login_resource import LoginResource +from pixelated.resources.login_resource import LoginResource, LoginStatusResource from pixelated.resources.logout_resource import LogoutResource from pixelated.resources.user_settings_resource import UserSettingsResource from pixelated.resources.mail_resource import MailResource @@ -51,17 +51,18 @@ MODE_RUNNING = 2 class RootResource(BaseResource): def __init__(self, services_factory): BaseResource.__init__(self, services_factory) - self._startup_assets_folder = get_startup_folder() - self._static_folder = get_static_folder() - self._html_template = open(os.path.join(self._static_folder, 'index.html')).read() + self._public_static_folder = get_public_static_folder() + self._protected_static_folder = get_protected_static_folder() + self._html_template = open(os.path.join(self._protected_static_folder, 'index.html')).read() self._services_factory = services_factory self._child_resources = ChildResourcesMap() - with open(os.path.join(self._startup_assets_folder, 'Interstitial.html')) as f: + with open(os.path.join(self._public_static_folder, 'interstitial.html')) as f: self.interstitial = f.read() self._startup_mode() def _startup_mode(self): - self.putChild('startup-assets', File(self._startup_assets_folder)) + self.putChild('public', File(self._public_static_folder)) + self.putChild('status', LoginStatusResource(self._services_factory)) self._mode = MODE_STARTUP def getChild(self, path, request): @@ -89,9 +90,9 @@ class RootResource(BaseResource): return csrf_input and csrf_input == xsrf_token def initialize(self, provider=None, disclaimer_banner=None, authenticator=None): - self._child_resources.add('recovery', AccountRecoveryResource(self._services_factory)) - self._child_resources.add('sandbox', SandboxResource(self._static_folder)) - self._child_resources.add('assets', File(self._static_folder)) + self._child_resources.add('assets', File(self._protected_static_folder)) + self._child_resources.add('backup-account', BackupAccountResource(self._services_factory)) + 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)) self._child_resources.add('contacts', ContactsResource(self._services_factory)) diff --git a/service/pixelated/resources/session.py b/service/pixelated/resources/session.py index 9ade8d29..5dfa52e6 100644 --- a/service/pixelated/resources/session.py +++ b/service/pixelated/resources/session.py @@ -21,6 +21,7 @@ from twisted.web.server import Session class IPixelatedSession(Interface): user_uuid = Attribute('The uuid of the currently logged in user') + login_status = Attribute('The status during user login') class PixelatedSession(object): @@ -28,12 +29,27 @@ class PixelatedSession(object): def __init__(self, session): self.user_uuid = None + self.login_status = None def is_logged_in(self): return self.user_uuid is not None def expire(self): self.user_uuid = None + self.login_status = None + + def login_started(self): + self.login_status = 'started' + + def login_successful(self, user_uuid): + self.user_uuid = user_uuid + self.login_status = 'completed' + + def login_error(self): + self.login_status = 'error' + + def check_login_status(self): + return self.login_status registerAdapter(PixelatedSession, Session, IPixelatedSession) |