2010-04-21 10:50:16 +02:00
|
|
|
# w.c.s. - web application for online forms
|
|
|
|
# Copyright (C) 2005-2010 Entr'ouvert
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program 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 General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
2012-01-26 17:32:10 +01:00
|
|
|
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2010-04-21 10:50:16 +02:00
|
|
|
|
2013-04-03 23:56:03 +02:00
|
|
|
import json
|
2005-07-16 15:03:25 +02:00
|
|
|
import os
|
2013-04-03 23:56:03 +02:00
|
|
|
import re
|
2016-06-14 21:52:47 +02:00
|
|
|
from importlib import import_module
|
2005-07-16 15:03:25 +02:00
|
|
|
|
2019-04-15 15:53:17 +02:00
|
|
|
from quixote import get_publisher, get_request, get_response, get_session, get_session_manager, redirect
|
2005-07-15 20:05:40 +02:00
|
|
|
from quixote.directory import Directory
|
2005-07-16 15:03:25 +02:00
|
|
|
from quixote.util import StaticDirectory
|
2005-07-15 20:05:40 +02:00
|
|
|
|
2019-09-29 20:53:23 +02:00
|
|
|
from . import portfolio
|
|
|
|
from .api import ApiDirectory
|
|
|
|
from .categories import Category
|
|
|
|
from .formdef import FormDef
|
|
|
|
from .forms import root
|
|
|
|
from .forms.actions import ActionsDirectory
|
|
|
|
from .forms.preview import PreviewDirectory
|
2022-01-31 19:39:01 +01:00
|
|
|
from .qommon import _, errors, get_cfg, ident, misc, saml2, template
|
2019-09-29 20:53:23 +02:00
|
|
|
from .qommon.afterjobs import AfterJobStatusDirectory
|
2022-12-29 09:30:32 +01:00
|
|
|
from .qommon.myspace import MyspaceDirectory
|
2022-07-11 10:22:59 +02:00
|
|
|
from .qommon.upload_storage import UploadStorageError, get_storage_object
|
2006-08-11 11:23:56 +02:00
|
|
|
|
2020-01-18 20:33:44 +01:00
|
|
|
|
2006-03-04 23:21:46 +01:00
|
|
|
class CompatibilityDirectory(Directory):
|
|
|
|
_q_exports = ['']
|
2005-07-15 20:05:40 +02:00
|
|
|
|
|
|
|
def _q_index(self):
|
2006-03-04 23:21:46 +01:00
|
|
|
return redirect('..')
|
|
|
|
|
2013-04-08 10:50:59 +02:00
|
|
|
|
2006-09-07 20:49:20 +02:00
|
|
|
class IdentDirectory(Directory):
|
|
|
|
def _q_lookup(self, component):
|
2006-10-15 21:02:38 +02:00
|
|
|
get_response().breadcrumb.append(('ident/', None))
|
2007-07-03 11:27:20 +02:00
|
|
|
try:
|
2019-09-29 20:53:23 +02:00
|
|
|
return ident.get_method_directory(component)
|
2007-07-03 11:27:20 +02:00
|
|
|
except KeyError:
|
|
|
|
raise errors.TraversalError()
|
2006-09-07 20:49:20 +02:00
|
|
|
|
2006-08-11 12:42:04 +02:00
|
|
|
|
2006-08-11 11:23:56 +02:00
|
|
|
class LoginDirectory(Directory):
|
|
|
|
_q_exports = ['']
|
2006-03-04 23:21:46 +01:00
|
|
|
|
2013-11-03 14:22:43 +01:00
|
|
|
def _q_index(self):
|
2006-10-27 12:49:43 +02:00
|
|
|
ident_methods = get_cfg('identification', {}).get('methods', [])
|
2006-08-11 11:23:56 +02:00
|
|
|
|
2014-10-23 15:01:41 +02:00
|
|
|
if get_request().form.get('ReturnUrl'):
|
2016-01-13 22:09:08 +01:00
|
|
|
get_request().form['next'] = get_request().form.pop('ReturnUrl')
|
2014-10-06 13:02:26 +02:00
|
|
|
|
2006-08-14 23:11:24 +02:00
|
|
|
if len(ident_methods) == 0:
|
2006-10-27 12:49:43 +02:00
|
|
|
idps = get_cfg('idp', {})
|
2006-08-15 17:07:38 +02:00
|
|
|
if len(idps) == 0:
|
|
|
|
return template.error_page(_('Authentication subsystem is not yet configured.'))
|
2015-01-04 12:16:16 +01:00
|
|
|
ident_methods = ['idp'] # fallback to old behaviour; saml.
|
2006-08-15 17:07:38 +02:00
|
|
|
|
2014-10-06 13:02:26 +02:00
|
|
|
if 'IsPassive' in get_request().form and 'idp' in ident_methods:
|
|
|
|
# if isPassive is given in query parameters, we restrict ourselves
|
|
|
|
# to saml login.
|
|
|
|
ident_methods = ['idp']
|
|
|
|
|
2022-12-04 15:51:25 +01:00
|
|
|
# always prefer idp (saml), fallback to first configured method
|
|
|
|
method = 'idp' if 'idp' in ident_methods else ident_methods[0]
|
|
|
|
return ident.login(method)
|
2006-08-11 11:23:56 +02:00
|
|
|
|
2009-04-27 13:33:12 +02:00
|
|
|
def _q_lookup(self, component):
|
|
|
|
try:
|
2019-09-29 20:53:23 +02:00
|
|
|
dir = ident.get_method_directory(component)
|
2009-04-27 13:33:12 +02:00
|
|
|
# set the register page as the index page, so the url can be
|
|
|
|
# /login/password/ instead of /login/password/login
|
|
|
|
dir._q_exports.append('')
|
|
|
|
dir._q_index = dir.login
|
|
|
|
return dir
|
|
|
|
except KeyError:
|
|
|
|
return errors.TraversalError()
|
|
|
|
|
|
|
|
|
2006-09-07 20:49:20 +02:00
|
|
|
class RegisterDirectory(Directory):
|
|
|
|
_q_exports = ['']
|
|
|
|
|
2013-11-03 14:22:43 +01:00
|
|
|
def _q_index(self):
|
2006-10-27 12:49:43 +02:00
|
|
|
ident_methods = get_cfg('identification', {}).get('methods', [])
|
2006-09-07 20:49:20 +02:00
|
|
|
|
|
|
|
if len(ident_methods) == 0:
|
2006-10-27 12:49:43 +02:00
|
|
|
idps = get_cfg('idp', {})
|
2006-09-07 20:49:20 +02:00
|
|
|
if len(idps) == 0:
|
|
|
|
return template.error_page(_('Authentication subsystem is not yet configured.'))
|
2015-01-04 12:16:16 +01:00
|
|
|
ident_methods = ['idp'] # fallback to old behaviour; saml.
|
2006-09-07 20:49:20 +02:00
|
|
|
|
2022-12-04 15:51:25 +01:00
|
|
|
# always prefer idp (saml), fallback to first configured method
|
|
|
|
method = 'idp' if 'idp' in ident_methods else ident_methods[0]
|
|
|
|
return ident.register(method)
|
2009-04-27 13:33:12 +02:00
|
|
|
|
2006-08-11 11:23:56 +02:00
|
|
|
def _q_lookup(self, component):
|
2007-07-03 11:27:20 +02:00
|
|
|
try:
|
2019-09-29 20:53:23 +02:00
|
|
|
dir = ident.get_method_directory(component)
|
2020-03-25 09:01:55 +01:00
|
|
|
if 'register' not in dir._q_exports:
|
|
|
|
return errors.TraversalError()
|
2009-04-27 13:20:28 +02:00
|
|
|
# set the register page as the index page, so the url can be
|
|
|
|
# /register/password/ instead of /register/password/register
|
|
|
|
dir._q_exports.append('')
|
|
|
|
dir._q_index = dir.register
|
|
|
|
return dir
|
2007-07-03 11:27:20 +02:00
|
|
|
except KeyError:
|
|
|
|
return errors.TraversalError()
|
2006-08-11 11:23:56 +02:00
|
|
|
|
|
|
|
|
2016-06-29 08:48:01 +02:00
|
|
|
class StaticsDirectory(Directory):
|
|
|
|
static_directories = {
|
2018-11-14 13:10:26 +01:00
|
|
|
'': ['web', 'qommon', 'django:gadjo', 'django:ckeditor'],
|
2017-01-18 17:53:37 +01:00
|
|
|
'xstatic': [
|
|
|
|
'xstatic:jquery',
|
|
|
|
'xstatic:jquery_ui',
|
2019-01-21 16:52:50 +01:00
|
|
|
'xstatic:font_awesome',
|
2021-12-14 10:43:44 +01:00
|
|
|
'xstatic:godo',
|
2019-01-21 16:52:50 +01:00
|
|
|
'xstatic:opensans',
|
2020-01-25 20:37:24 +01:00
|
|
|
'xstatic:leaflet',
|
|
|
|
'xstatic:leaflet_gesturehandling',
|
2022-04-03 12:29:39 +02:00
|
|
|
'xstatic:select2',
|
2020-01-25 20:37:24 +01:00
|
|
|
],
|
2016-06-29 08:48:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def resolve_static_directories(cls, prefix):
|
|
|
|
directories = cls.static_directories[prefix]
|
|
|
|
for directory in directories:
|
|
|
|
if directory[0] == '/':
|
|
|
|
yield directory
|
2021-03-22 11:14:42 +01:00
|
|
|
elif ':' not in directory:
|
2016-06-29 08:48:01 +02:00
|
|
|
yield os.path.join(get_publisher().data_dir, directory)
|
|
|
|
else:
|
|
|
|
directory_type, value = directory.split(':')
|
|
|
|
try:
|
|
|
|
if directory_type == 'xstatic':
|
|
|
|
module = import_module('xstatic.pkg.%s' % value)
|
|
|
|
yield module.BASE_DIR
|
|
|
|
elif directory_type == 'django':
|
|
|
|
module = import_module(value)
|
|
|
|
yield os.path.join(os.path.dirname(module.__file__), 'static')
|
|
|
|
except ImportError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def _q_traverse(self, path):
|
2021-09-16 23:52:32 +02:00
|
|
|
# noqa pylint: disable=consider-iterating-dictionary
|
2016-06-29 08:48:01 +02:00
|
|
|
if path[0] in self.static_directories.keys():
|
|
|
|
prefix, rest = path[0], path[1:]
|
|
|
|
else:
|
|
|
|
prefix, rest = '', path
|
|
|
|
|
|
|
|
if not rest:
|
|
|
|
raise errors.AccessForbiddenError()
|
|
|
|
|
|
|
|
for directory in self.resolve_static_directories(prefix):
|
|
|
|
try:
|
|
|
|
return StaticDirectory(directory, follow_symlinks=True)._q_traverse(rest)
|
|
|
|
except errors.TraversalError:
|
|
|
|
continue
|
|
|
|
raise errors.TraversalError()
|
|
|
|
|
|
|
|
|
2024-01-27 12:11:29 +01:00
|
|
|
class TinyRedirectDirectory(Directory):
|
|
|
|
def _q_lookup(self, component):
|
|
|
|
formdata_match = re.match('^([1-9][0-9]*)-([1-9][0-9]*)$', component)
|
|
|
|
formdef_match = re.match('^([1-9][0-9]*)$', component)
|
|
|
|
if formdata_match:
|
|
|
|
formdef_id, formdata_id = formdata_match.groups()
|
|
|
|
elif formdef_match:
|
|
|
|
formdef_id, formdata_id = formdef_match.groups()[0], None
|
|
|
|
else:
|
|
|
|
raise errors.TraversalError()
|
|
|
|
try:
|
|
|
|
formdef = FormDef.get(formdef_id)
|
|
|
|
except KeyError:
|
|
|
|
raise errors.TraversalError()
|
|
|
|
if formdata_id:
|
|
|
|
return redirect(formdef.get_url() + f'{formdata_id}/')
|
|
|
|
else:
|
|
|
|
return redirect(formdef.get_url())
|
|
|
|
|
|
|
|
|
2006-08-11 11:23:56 +02:00
|
|
|
class RootDirectory(Directory):
|
2015-07-10 22:30:55 +02:00
|
|
|
_q_exports = [
|
|
|
|
'admin',
|
|
|
|
'backoffice',
|
|
|
|
'forms',
|
|
|
|
'login',
|
|
|
|
'logout',
|
|
|
|
'saml',
|
2013-06-04 17:05:28 +02:00
|
|
|
'ident',
|
|
|
|
'register',
|
|
|
|
'afterjobs',
|
|
|
|
'myspace',
|
|
|
|
'user',
|
|
|
|
'roles',
|
2019-09-18 11:06:58 +02:00
|
|
|
('tmp-upload', 'tmp_upload'),
|
|
|
|
'api',
|
2020-01-25 22:44:09 +01:00
|
|
|
'tryauth',
|
|
|
|
'auth',
|
|
|
|
'preview',
|
2018-08-08 13:34:43 +02:00
|
|
|
'fargo',
|
|
|
|
'static',
|
|
|
|
'actions',
|
2024-01-27 12:11:29 +01:00
|
|
|
('r', 'tiny_redirect'),
|
2018-08-08 13:34:43 +02:00
|
|
|
]
|
2008-09-09 17:22:00 +02:00
|
|
|
|
2014-11-04 10:39:35 +01:00
|
|
|
api = ApiDirectory()
|
2014-07-21 10:47:36 +02:00
|
|
|
myspace = MyspaceDirectory()
|
2017-03-31 11:05:11 +02:00
|
|
|
fargo = portfolio.FargoDirectory()
|
2016-06-29 08:48:01 +02:00
|
|
|
static = StaticsDirectory()
|
2018-08-08 13:34:43 +02:00
|
|
|
actions = ActionsDirectory()
|
2024-01-27 12:11:29 +01:00
|
|
|
tiny_redirect = TinyRedirectDirectory()
|
2016-06-14 21:52:47 +02:00
|
|
|
|
2022-10-23 18:04:36 +02:00
|
|
|
forced_language = False
|
|
|
|
|
2015-04-02 18:54:14 +02:00
|
|
|
def tryauth(self):
|
2019-09-29 20:53:23 +02:00
|
|
|
return root.tryauth(get_publisher().get_root_url())
|
2015-04-02 18:54:14 +02:00
|
|
|
|
|
|
|
def auth(self):
|
2019-09-29 20:53:23 +02:00
|
|
|
return root.auth(get_publisher().get_root_url())
|
2015-04-02 18:54:14 +02:00
|
|
|
|
2005-07-15 20:05:40 +02:00
|
|
|
def logout(self):
|
|
|
|
session = get_session()
|
|
|
|
if not session:
|
2007-06-19 18:02:29 +02:00
|
|
|
return redirect(get_publisher().get_root_url())
|
2006-10-27 12:49:43 +02:00
|
|
|
ident_methods = get_cfg('identification', {}).get('methods', [])
|
2018-10-05 14:14:35 +02:00
|
|
|
|
2018-12-14 01:44:45 +01:00
|
|
|
if (
|
|
|
|
'fc' in ident_methods
|
|
|
|
and session.extra_user_variables
|
|
|
|
and 'fc_id_token' in session.extra_user_variables
|
|
|
|
):
|
|
|
|
return get_publisher().ident_methods['fc']().logout()
|
2018-10-05 14:14:35 +02:00
|
|
|
|
2021-03-22 11:14:42 +01:00
|
|
|
if 'idp' not in ident_methods:
|
2009-01-15 10:50:37 +01:00
|
|
|
get_session_manager().expire_session()
|
2007-06-19 18:02:29 +02:00
|
|
|
return redirect(get_publisher().get_root_url())
|
2006-08-14 09:36:17 +02:00
|
|
|
|
2007-01-10 10:46:49 +01:00
|
|
|
if not get_session().lasso_identity_provider_id:
|
2009-01-15 10:50:37 +01:00
|
|
|
get_session_manager().expire_session()
|
2007-06-19 18:02:29 +02:00
|
|
|
return redirect(get_publisher().get_root_url())
|
2007-01-10 10:46:49 +01:00
|
|
|
|
2005-07-15 20:05:40 +02:00
|
|
|
# add settings to disable single logout?
|
|
|
|
# (and to set it as none/get/soap?)
|
2015-01-04 12:16:16 +01:00
|
|
|
return self.saml.slo_sp()
|
2005-07-15 20:05:40 +02:00
|
|
|
|
2013-05-08 11:46:21 +02:00
|
|
|
def user(self):
|
2015-09-19 10:11:38 +02:00
|
|
|
# endpoint for backward compatibility, new code should call /api/user/
|
2013-05-08 11:46:21 +02:00
|
|
|
if get_request().is_json():
|
2015-09-19 10:11:38 +02:00
|
|
|
return self.api.user._q_index()
|
2013-05-08 11:46:21 +02:00
|
|
|
return redirect('myspace/')
|
|
|
|
|
2013-06-04 17:05:28 +02:00
|
|
|
def roles(self):
|
2015-05-14 20:57:13 +02:00
|
|
|
# endpoint for backward compatibility, new code should call /api/roles
|
2013-06-04 17:05:28 +02:00
|
|
|
if not get_request().is_json():
|
|
|
|
return redirect('/')
|
2015-05-14 20:57:13 +02:00
|
|
|
return self.api.roles()
|
2013-06-04 17:05:28 +02:00
|
|
|
|
2013-04-03 23:56:03 +02:00
|
|
|
def tmp_upload(self):
|
|
|
|
results = []
|
2020-02-05 12:28:36 +01:00
|
|
|
storage = get_request().form.get('storage')
|
2021-03-19 22:49:33 +01:00
|
|
|
for v in get_request().form.values():
|
2013-04-03 23:56:03 +02:00
|
|
|
if hasattr(v, 'fp'):
|
2020-02-26 11:46:31 +01:00
|
|
|
try:
|
|
|
|
tempfile = get_session().add_tempfile(v, storage=storage)
|
|
|
|
results.append(
|
2021-02-04 10:37:40 +01:00
|
|
|
{
|
2020-02-26 11:46:31 +01:00
|
|
|
'name': tempfile.get('base_filename'),
|
|
|
|
'type': tempfile.get('content_type'),
|
|
|
|
'size': tempfile.get('size'),
|
|
|
|
'token': tempfile.get('token'),
|
2021-02-04 10:37:40 +01:00
|
|
|
}
|
2020-02-26 11:46:31 +01:00
|
|
|
)
|
2022-07-11 10:22:59 +02:00
|
|
|
if not get_storage_object(storage).has_redirect_url(None):
|
|
|
|
results[-1]['url'] = 'tempfile?t=%s' % tempfile.get('token')
|
2020-02-26 11:46:31 +01:00
|
|
|
except UploadStorageError as e:
|
2021-07-08 11:46:00 +02:00
|
|
|
get_publisher().record_error(_('Upload storage error'), exception=e)
|
2020-02-26 11:46:31 +01:00
|
|
|
results.append({'error': _('failed to store file (system error)')})
|
2018-04-06 14:04:35 +02:00
|
|
|
|
2013-04-03 23:56:03 +02:00
|
|
|
get_response().set_content_type('application/json')
|
2020-01-25 21:44:48 +01:00
|
|
|
useragent = get_request().get_header('User-agent') or ''
|
2014-12-20 19:50:40 +01:00
|
|
|
if re.findall(r'MSIE \d\.', useragent):
|
2013-04-03 23:56:03 +02:00
|
|
|
# hack around MSIE version < 10 as they do not have support for
|
|
|
|
# XmlHttpRequest 2 (hence the forced usage of an iframe to send
|
|
|
|
# a file in the background (cf jquery.iframe-transport.js); and
|
|
|
|
# they would propose the returned json content for download if
|
|
|
|
# it was served with the appropriate content type :/
|
|
|
|
get_response().set_content_type('text/plain')
|
2021-05-15 15:34:16 +02:00
|
|
|
return json.dumps(results, cls=misc.JSONEncoder)
|
2005-07-15 20:05:40 +02:00
|
|
|
|
2016-06-17 12:26:47 +02:00
|
|
|
def feed_substitution_parts(self):
|
|
|
|
get_publisher().substitutions.feed(get_session())
|
|
|
|
get_publisher().substitutions.feed(get_request().user)
|
|
|
|
|
2006-03-04 23:37:56 +01:00
|
|
|
def _q_traverse(self, path):
|
2023-08-06 10:40:27 +02:00
|
|
|
if get_publisher().site_options_exception:
|
|
|
|
raise Exception('invalid site options') from get_publisher().site_options_exception
|
2023-07-21 13:42:07 +02:00
|
|
|
if path and path[0] == 'manage':
|
|
|
|
return redirect('/backoffice' + get_request().get_path_query().removeprefix('/manage'))
|
|
|
|
|
2022-10-23 18:04:36 +02:00
|
|
|
self.forced_language = False
|
2016-06-17 12:26:47 +02:00
|
|
|
self.feed_substitution_parts()
|
|
|
|
|
2023-01-27 13:11:25 +01:00
|
|
|
output = self.try_passive_sso(path)
|
misc: improve passive sso on state change (#67090)
- automatic_sso is renamed try_passive_sso to be clearer on the goal of
the method,
- test for possible passive sso is now done before rendering the current
page,
- on a succesfull SSO if <idp_session_cookie_name> cookie is present,
its value is saved in the Quixote session,
- behaviour of try_passive_sso is changed:
- if user is logged in or <idp_session_cookie_name> cookie value
differs from the value in '*-passive-auth-tried' cookie, the
'*-passive-auth-tried' cookie is expired,
- if user is logged and <idp_session_cookie_name> cookie cookie value
differs from the one saved in the Quixote session, user is logged
out, if not treatment stop here.
- if the <idp_session_cookie_name> cookie cookie is not valued or if
its value is equal to '*-passive-auth-tried' cookie, treatment stops
here,
- if the <idp_session_cookie_name> cookie is valued and its value
differs from the '*-passive-auth-tried' cookie cookie value, then
'*-passive-auth-tried' cookie is set to the value of
<idp_session_cookie_name> cookie and a passive SSO is tried.
2022-07-06 19:06:03 +02:00
|
|
|
if output:
|
|
|
|
return output
|
|
|
|
|
2006-07-15 11:23:35 +02:00
|
|
|
response = get_response()
|
2023-04-29 11:12:34 +02:00
|
|
|
if not response.filter:
|
|
|
|
response.filter = {'default_org': _('Forms')}
|
2006-07-15 11:23:35 +02:00
|
|
|
if not hasattr(response, 'breadcrumb'):
|
|
|
|
response.breadcrumb = [('', _('Home'))]
|
|
|
|
|
2007-01-15 17:03:07 +01:00
|
|
|
if not self.admin:
|
|
|
|
self.admin = get_publisher().admin_directory_class()
|
|
|
|
|
|
|
|
if not self.backoffice:
|
|
|
|
self.backoffice = get_publisher().backoffice_directory_class()
|
|
|
|
|
2006-03-04 23:37:56 +01:00
|
|
|
try:
|
|
|
|
return Directory._q_traverse(self, path)
|
|
|
|
except errors.TraversalError:
|
|
|
|
pass
|
|
|
|
|
misc: improve passive sso on state change (#67090)
- automatic_sso is renamed try_passive_sso to be clearer on the goal of
the method,
- test for possible passive sso is now done before rendering the current
page,
- on a succesfull SSO if <idp_session_cookie_name> cookie is present,
its value is saved in the Quixote session,
- behaviour of try_passive_sso is changed:
- if user is logged in or <idp_session_cookie_name> cookie value
differs from the value in '*-passive-auth-tried' cookie, the
'*-passive-auth-tried' cookie is expired,
- if user is logged and <idp_session_cookie_name> cookie cookie value
differs from the one saved in the Quixote session, user is logged
out, if not treatment stop here.
- if the <idp_session_cookie_name> cookie cookie is not valued or if
its value is equal to '*-passive-auth-tried' cookie, treatment stops
here,
- if the <idp_session_cookie_name> cookie is valued and its value
differs from the '*-passive-auth-tried' cookie cookie value, then
'*-passive-auth-tried' cookie is set to the value of
<idp_session_cookie_name> cookie and a passive SSO is tried.
2022-07-06 19:06:03 +02:00
|
|
|
return root.RootDirectory()._q_traverse(path)
|
|
|
|
|
2023-01-27 13:11:25 +01:00
|
|
|
def try_passive_sso(self, path):
|
2023-10-06 08:39:57 +02:00
|
|
|
if path and path[0] == 'api':
|
|
|
|
# skip passive SSO for API calls
|
|
|
|
return
|
misc: improve passive sso on state change (#67090)
- automatic_sso is renamed try_passive_sso to be clearer on the goal of
the method,
- test for possible passive sso is now done before rendering the current
page,
- on a succesfull SSO if <idp_session_cookie_name> cookie is present,
its value is saved in the Quixote session,
- behaviour of try_passive_sso is changed:
- if user is logged in or <idp_session_cookie_name> cookie value
differs from the value in '*-passive-auth-tried' cookie, the
'*-passive-auth-tried' cookie is expired,
- if user is logged and <idp_session_cookie_name> cookie cookie value
differs from the one saved in the Quixote session, user is logged
out, if not treatment stop here.
- if the <idp_session_cookie_name> cookie cookie is not valued or if
its value is equal to '*-passive-auth-tried' cookie, treatment stops
here,
- if the <idp_session_cookie_name> cookie is valued and its value
differs from the '*-passive-auth-tried' cookie cookie value, then
'*-passive-auth-tried' cookie is set to the value of
<idp_session_cookie_name> cookie and a passive SSO is tried.
2022-07-06 19:06:03 +02:00
|
|
|
publisher = get_publisher()
|
|
|
|
idp_session_cookie_name = publisher.get_site_option('idp_session_cookie_name')
|
|
|
|
|
|
|
|
if not idp_session_cookie_name:
|
|
|
|
return
|
|
|
|
ident_methods = get_cfg('identification', {}).get('methods', [])
|
|
|
|
idps = get_cfg('idp', {})
|
|
|
|
if len(idps) != 1:
|
|
|
|
return
|
|
|
|
if ident_methods and 'idp' not in ident_methods:
|
|
|
|
return
|
2019-04-15 15:53:17 +02:00
|
|
|
|
|
|
|
request = get_request()
|
misc: improve passive sso on state change (#67090)
- automatic_sso is renamed try_passive_sso to be clearer on the goal of
the method,
- test for possible passive sso is now done before rendering the current
page,
- on a succesfull SSO if <idp_session_cookie_name> cookie is present,
its value is saved in the Quixote session,
- behaviour of try_passive_sso is changed:
- if user is logged in or <idp_session_cookie_name> cookie value
differs from the value in '*-passive-auth-tried' cookie, the
'*-passive-auth-tried' cookie is expired,
- if user is logged and <idp_session_cookie_name> cookie cookie value
differs from the one saved in the Quixote session, user is logged
out, if not treatment stop here.
- if the <idp_session_cookie_name> cookie cookie is not valued or if
its value is equal to '*-passive-auth-tried' cookie, treatment stops
here,
- if the <idp_session_cookie_name> cookie is valued and its value
differs from the '*-passive-auth-tried' cookie cookie value, then
'*-passive-auth-tried' cookie is set to the value of
<idp_session_cookie_name> cookie and a passive SSO is tried.
2022-07-06 19:06:03 +02:00
|
|
|
cookies = request.cookies
|
|
|
|
|
|
|
|
if request.user:
|
|
|
|
if request.session.opened_session_value and request.session.opened_session_value != cookies.get(
|
|
|
|
idp_session_cookie_name
|
|
|
|
):
|
|
|
|
# logout current user if saved value for idp_session_cookie_name differs from the current one
|
|
|
|
get_session_manager().expire_session()
|
|
|
|
get_request()._user = ()
|
2023-10-05 20:31:19 +02:00
|
|
|
get_publisher().session_manager.start_request()
|
|
|
|
get_publisher().session_manager.maintain_session(get_session())
|
misc: improve passive sso on state change (#67090)
- automatic_sso is renamed try_passive_sso to be clearer on the goal of
the method,
- test for possible passive sso is now done before rendering the current
page,
- on a succesfull SSO if <idp_session_cookie_name> cookie is present,
its value is saved in the Quixote session,
- behaviour of try_passive_sso is changed:
- if user is logged in or <idp_session_cookie_name> cookie value
differs from the value in '*-passive-auth-tried' cookie, the
'*-passive-auth-tried' cookie is expired,
- if user is logged and <idp_session_cookie_name> cookie cookie value
differs from the one saved in the Quixote session, user is logged
out, if not treatment stop here.
- if the <idp_session_cookie_name> cookie cookie is not valued or if
its value is equal to '*-passive-auth-tried' cookie, treatment stops
here,
- if the <idp_session_cookie_name> cookie is valued and its value
differs from the '*-passive-auth-tried' cookie cookie value, then
'*-passive-auth-tried' cookie is set to the value of
<idp_session_cookie_name> cookie and a passive SSO is tried.
2022-07-06 19:06:03 +02:00
|
|
|
else:
|
|
|
|
# already logged, stop here.
|
|
|
|
return
|
2023-10-06 08:39:57 +02:00
|
|
|
elif path and path[0] in ('backoffice', 'login', 'manage'):
|
|
|
|
# do not start passive SSO for backoffice or login URLs
|
2023-01-27 13:11:25 +01:00
|
|
|
return
|
2023-10-05 20:31:19 +02:00
|
|
|
|
|
|
|
session = get_session()
|
|
|
|
|
|
|
|
if (
|
|
|
|
idp_session_cookie_name not in cookies
|
|
|
|
or cookies.get(idp_session_cookie_name) == session.opened_session_value
|
misc: improve passive sso on state change (#67090)
- automatic_sso is renamed try_passive_sso to be clearer on the goal of
the method,
- test for possible passive sso is now done before rendering the current
page,
- on a succesfull SSO if <idp_session_cookie_name> cookie is present,
its value is saved in the Quixote session,
- behaviour of try_passive_sso is changed:
- if user is logged in or <idp_session_cookie_name> cookie value
differs from the value in '*-passive-auth-tried' cookie, the
'*-passive-auth-tried' cookie is expired,
- if user is logged and <idp_session_cookie_name> cookie cookie value
differs from the one saved in the Quixote session, user is logged
out, if not treatment stop here.
- if the <idp_session_cookie_name> cookie cookie is not valued or if
its value is equal to '*-passive-auth-tried' cookie, treatment stops
here,
- if the <idp_session_cookie_name> cookie is valued and its value
differs from the '*-passive-auth-tried' cookie cookie value, then
'*-passive-auth-tried' cookie is set to the value of
<idp_session_cookie_name> cookie and a passive SSO is tried.
2022-07-06 19:06:03 +02:00
|
|
|
):
|
2023-10-05 20:31:19 +02:00
|
|
|
# let the flow continue and the expected page be served.
|
misc: improve passive sso on state change (#67090)
- automatic_sso is renamed try_passive_sso to be clearer on the goal of
the method,
- test for possible passive sso is now done before rendering the current
page,
- on a succesfull SSO if <idp_session_cookie_name> cookie is present,
its value is saved in the Quixote session,
- behaviour of try_passive_sso is changed:
- if user is logged in or <idp_session_cookie_name> cookie value
differs from the value in '*-passive-auth-tried' cookie, the
'*-passive-auth-tried' cookie is expired,
- if user is logged and <idp_session_cookie_name> cookie cookie value
differs from the one saved in the Quixote session, user is logged
out, if not treatment stop here.
- if the <idp_session_cookie_name> cookie cookie is not valued or if
its value is equal to '*-passive-auth-tried' cookie, treatment stops
here,
- if the <idp_session_cookie_name> cookie is valued and its value
differs from the '*-passive-auth-tried' cookie cookie value, then
'*-passive-auth-tried' cookie is set to the value of
<idp_session_cookie_name> cookie and a passive SSO is tried.
2022-07-06 19:06:03 +02:00
|
|
|
return
|
2023-10-05 20:31:19 +02:00
|
|
|
|
|
|
|
session.opened_session_value = cookies.get(idp_session_cookie_name)
|
misc: improve passive sso on state change (#67090)
- automatic_sso is renamed try_passive_sso to be clearer on the goal of
the method,
- test for possible passive sso is now done before rendering the current
page,
- on a succesfull SSO if <idp_session_cookie_name> cookie is present,
its value is saved in the Quixote session,
- behaviour of try_passive_sso is changed:
- if user is logged in or <idp_session_cookie_name> cookie value
differs from the value in '*-passive-auth-tried' cookie, the
'*-passive-auth-tried' cookie is expired,
- if user is logged and <idp_session_cookie_name> cookie cookie value
differs from the one saved in the Quixote session, user is logged
out, if not treatment stop here.
- if the <idp_session_cookie_name> cookie cookie is not valued or if
its value is equal to '*-passive-auth-tried' cookie, treatment stops
here,
- if the <idp_session_cookie_name> cookie is valued and its value
differs from the '*-passive-auth-tried' cookie cookie value, then
'*-passive-auth-tried' cookie is set to the value of
<idp_session_cookie_name> cookie and a passive SSO is tried.
2022-07-06 19:06:03 +02:00
|
|
|
url = request.get_url()
|
|
|
|
query = request.get_query()
|
|
|
|
if query:
|
|
|
|
url += '?' + query
|
|
|
|
return root.tryauth(url)
|
2006-03-04 23:37:56 +01:00
|
|
|
|
2016-06-14 21:52:47 +02:00
|
|
|
def _q_lookup(self, component):
|
2022-10-23 18:04:36 +02:00
|
|
|
if (
|
|
|
|
get_publisher().has_i18n_enabled()
|
|
|
|
and not self.forced_language
|
|
|
|
and component in (get_cfg('language', {}).get('languages') or [])
|
|
|
|
):
|
|
|
|
if component != get_publisher().current_language:
|
|
|
|
get_publisher().activate_language(component, get_request())
|
|
|
|
self.forced_language = True
|
|
|
|
return self
|
|
|
|
|
2006-03-04 23:21:46 +01:00
|
|
|
# is this a category ?
|
|
|
|
try:
|
|
|
|
category = Category.get_by_urlname(component)
|
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
else:
|
2022-10-21 13:14:06 +02:00
|
|
|
# display category unless there's a formdef with same slug
|
2018-07-24 10:13:45 +02:00
|
|
|
try:
|
2021-03-19 22:49:33 +01:00
|
|
|
FormDef.get_by_urlname(component)
|
2018-07-24 10:13:45 +02:00
|
|
|
except KeyError:
|
2019-09-29 20:53:23 +02:00
|
|
|
return root.RootDirectory(category)
|
2006-03-04 23:21:46 +01:00
|
|
|
|
|
|
|
# or a form ?
|
2019-09-29 20:53:23 +02:00
|
|
|
return root.RootDirectory()._q_lookup(component)
|
2005-07-15 20:05:40 +02:00
|
|
|
|
2007-01-15 17:03:07 +01:00
|
|
|
admin = None
|
|
|
|
backoffice = None
|
|
|
|
|
2006-10-27 15:30:33 +02:00
|
|
|
saml = saml2.Saml2Directory()
|
2006-03-04 23:21:46 +01:00
|
|
|
forms = CompatibilityDirectory()
|
2006-09-07 20:49:20 +02:00
|
|
|
login = LoginDirectory()
|
2006-09-09 13:15:45 +02:00
|
|
|
register = RegisterDirectory()
|
2006-09-07 20:49:20 +02:00
|
|
|
ident = IdentDirectory()
|
2007-12-27 21:17:58 +01:00
|
|
|
afterjobs = AfterJobStatusDirectory()
|
2015-05-19 17:17:02 +02:00
|
|
|
preview = PreviewDirectory()
|