Ejemplo n.º 1
0
 def _send_confirmation(self, email):
     token_storage = GenericCache('confirm-email')
     data = {'email': email, 'user_id': self.user.id}
     token = make_unique_token(lambda t: not token_storage.get(t))
     token_storage.set(token, data, 24 * 3600)
     send_email(make_email(email, template=get_template_module('users/emails/verify_email.txt',
                                                               user=self.user, email=email, token=token)))
Ejemplo n.º 2
0
def principal_from_identifier(identifier, allow_groups=False, allow_external_users=False):
    # XXX: this is currently only used in PrincipalList
    # if we ever need to support more than just users and groups,
    # make sure to add it in here as well
    from indico.modules.groups import GroupProxy
    from indico.modules.users import User

    try:
        type_, data = identifier.split(':', 1)
    except ValueError:
        raise ValueError('Invalid data')
    if type_ == 'User':
        try:
            user_id = int(data)
        except ValueError:
            raise ValueError('Invalid data')
        user = User.get(user_id, is_deleted=False)
        if user is None:
            raise ValueError('Invalid user: {}'.format(user_id))
        return user
    elif type_ == 'ExternalUser':
        if not allow_external_users:
            raise ValueError('External users are not allowed')
        cache = GenericCache('external-user')
        external_user_data = cache.get(data)
        if not external_user_data:
            raise ValueError('Invalid data')
        user = User.query.filter(User.all_emails == external_user_data['email'], ~User.is_deleted).first()
        if user:
            return user
        # create a pending user. this user isn't sent to the DB unless it gets added
        # to the sqlalchemy session somehow (e.g. by adding it to an ACL).
        # like this processing form data does not result in something being stored in
        # the database, which is good!
        return User(first_name=external_user_data['first_name'], last_name=external_user_data['last_name'],
                    email=external_user_data['email'], affiliation=external_user_data['affiliation'],
                    address=external_user_data['address'], phone=external_user_data['phone'], is_pending=True)
    elif type_ == 'Group':
        if not allow_groups:
            raise ValueError('Groups are not allowed')
        try:
            provider, name = data.split(':', 1)
        except ValueError:
            raise ValueError('Invalid data')
        if not provider:
            # local group
            try:
                group_id = int(name)
            except ValueError:
                raise ValueError('Invalid data')
            group = GroupProxy(group_id)
        else:
            # multipass group
            group = GroupProxy(name, provider)
        if group.group is None:
            raise ValueError('Invalid group: {}'.format(data))
        return group
    else:
        raise ValueError('Invalid data')
Ejemplo n.º 3
0
def unlock_task(name):
    """Unlock a locked task.

    :return: ``True`` if the task has been unlocked; ``False`` if it was not locked.
    """
    cache = GenericCache('task-locks')
    if not cache.get(name):
        return False
    cache.delete(name)
    return True
Ejemplo n.º 4
0
class ZeepCache(Base):
    _instance = None

    def __init__(self, duration=DEFAULT_CACHE_TTL):
        self._cache = GenericCache("ZeepCache")
        self._duration = duration

    def get(self, url):
        self._cache.get(url)

    def add(self, url, content):
        self._cache.set(url, content, self._duration)
Ejemplo n.º 5
0
 def _get_user_data(self):
     user_id = request.args.get('user')
     if user_id is None:
         return {}
     elif user_id.isdigit():
         # existing indico user
         user = User.find_first(id=user_id, is_deleted=False)
         user_data = {t.name: getattr(user, t.name, None) if user else '' for t in PersonalDataType}
     else:
         # non-indico user
         data = GenericCache('pending_identities').get(user_id, {})
         user_data = {t.name: data.get(t.name) for t in PersonalDataType}
     user_data['title'] = get_title_uuid(self.regform, user_data['title'])
     return user_data
Ejemplo n.º 6
0
 def has_member(self, user):
     if not user:
         return False
     cache = GenericCache('group-membership')
     key = '{}:{}:{}'.format(self.provider, self.name, user.id)
     rv = cache.get(key)
     if rv is not None:
         return rv
     elif self.group is None:
         warn('Tried to check if {} is in invalid group {}'.format(user, self))
         rv = False
     else:
         rv = any(x[1] in self.group for x in user.iter_identifiers(check_providers=True, providers={self.provider}))
     cache.set(key, rv, 1800)
     return rv
Ejemplo n.º 7
0
    def get(cls, *args, **kwargs):
        """Create and return a serializable Report object, retrieved from cache if possible"""

        from indico_piwik.plugin import PiwikPlugin

        if not PiwikPlugin.settings.get('cache_enabled'):
            return cls(*args, **kwargs).to_serializable()

        cache = GenericCache('Piwik.Report')
        key = u'{}-{}-{}'.format(cls.__name__, args, kwargs)

        report = cache.get(key)
        if not report:
            report = cls(*args, **kwargs)
            cache.set(key, report, PiwikPlugin.settings.get('cache_ttl'))
        return report.to_serializable()
Ejemplo n.º 8
0
 def wrapper(*args, **kwargs):
     cache = GenericCache('task-locks')
     name = current_task.name
     if cache.get(name):
         Logger.get('celery').warning('Task %s is locked; not executing it. '
                                      'To manually unlock it, run `indico celery unlock %s`',
                                      name, name)
         return
     cache.set(name, True, 86400)
     try:
         return f(*args, **kwargs)
     finally:
         cache.delete(name)
Ejemplo n.º 9
0
def principal_from_fossil(fossil, allow_pending=False, allow_groups=True, allow_missing_groups=False,
                          allow_emails=False, allow_networks=False, existing_data=None, event=None):
    from indico.modules.networks.models.networks import IPNetworkGroup
    from indico.modules.events.models.roles import EventRole
    from indico.modules.groups import GroupProxy
    from indico.modules.users import User

    if existing_data is None:
        existing_data = set()

    type_ = fossil['_type']
    id_ = fossil['id']
    if type_ == 'Avatar':
        if isinstance(id_, int) or id_.isdigit():
            # regular user
            user = User.get(int(id_))
        elif allow_pending:
            data = GenericCache('pending_identities').get(id_)
            if not data:
                raise ValueError("Cannot find user '{}' in cache".format(id_))

            data = {k: '' if v is None else v for k, v in data.items()}
            email = data['email'].lower()

            # check if there is not already a (pending) user with that e-mail
            # we need to check for non-pending users too since the search may
            # show a user from external results even though the email belongs
            # to an indico account in case some of the search criteria did not
            # match the indico account
            user = User.query.filter(User.all_emails == email, ~User.is_deleted).first()
            if not user:
                user = User(first_name=data.get('first_name') or '', last_name=data.get('last_name') or '',
                            email=email,
                            address=data.get('address', ''), phone=data.get('phone', ''),
                            affiliation=data.get('affiliation', ''), is_pending=True)
                db.session.add(user)
                db.session.flush()
        else:
            raise ValueError("Id '{}' is not a number and allow_pending=False".format(id_))
        if user is None:
            raise ValueError('User does not exist: {}'.format(id_))
        return user
    elif allow_emails and type_ == 'Email':
        return EmailPrincipal(id_)
    elif allow_networks and type_ == 'IPNetworkGroup':
        group = IPNetworkGroup.get(int(id_))
        if group is None or (group.hidden and group not in existing_data):
            raise ValueError('IP network group does not exist: {}'.format(id_))
        return group
    elif allow_groups and type_ in {'LocalGroupWrapper', 'LocalGroup'}:
        group = GroupProxy(int(id_))
        if group.group is None:
            raise ValueError('Local group does not exist: {}'.format(id_))
        return group
    elif allow_groups and type_ in {'LDAPGroupWrapper', 'MultipassGroup'}:
        provider = fossil['provider']
        group = GroupProxy(id_, provider)
        if group.group is None and not allow_missing_groups:
            raise ValueError('Multipass group does not exist: {}:{}'.format(provider, id_))
        return group
    elif event and type_ == 'EventRole':
        role = EventRole.get(id_)
        role_name = fossil.get('name')
        if role is None:
            raise ValueError('Role does not exist: {}:{}'.format(role_name, id_))
        if role.event != event:
            raise ValueError('Role does not belong to provided event: {}:{} - {}'.format(role_name, id_, event))
        return role
    else:
        raise ValueError('Unexpected fossil type: {}'.format(type_))
Ejemplo n.º 10
0
import indico
from indico.core import signals
from indico.core.config import config
from indico.core.db import db
from indico.core.plugins import url_for_plugin
from indico.legacy.common.cache import GenericCache
from indico.modules.events.layout import layout_settings
from indico.modules.events.layout.models.menu import MenuEntry, MenuEntryType, TransientMenuEntry
from indico.util.caching import memoize_request
from indico.util.signals import named_objects_from_signal, values_from_signal
from indico.util.string import crc32, return_ascii
from indico.web.flask.util import url_for


_cache = GenericCache('updated-menus')


def _menu_entry_key(entry_data):
    return entry_data.position == -1, entry_data.position, entry_data.name


@memoize_request
def get_menu_entries_from_signal():
    return named_objects_from_signal(signals.event.sidemenu.send(), plugin_attr='plugin')


def build_menu_entry_name(name, plugin=None):
    """ Builds the proper name for a menu entry.

    Given a menu entry's name and optionally a plugin, returns the
Ejemplo n.º 11
0
import uuid

from flask import request
from werkzeug.exceptions import Forbidden, NotFound

from indico.legacy.common.cache import GenericCache
from indico.modules.designer.models.templates import DesignerTemplate
from indico.modules.events.management.controllers import RHManageEventBase
from indico.modules.events.management.forms import PosterPrintingForm
from indico.modules.events.posters import PosterPDF
from indico.util.i18n import _
from indico.web.flask.util import send_file, url_for
from indico.web.util import jsonify_data, jsonify_form

poster_cache = GenericCache('poster-printing')


class RHPosterPrintSettings(RHManageEventBase):
    ALLOW_LOCKED = True

    def _process_args(self):
        RHManageEventBase._process_args(self)
        self.template_id = request.args.get('template_id')

    def _process(self):
        self.commit = False
        form = PosterPrintingForm(self.event, template=self.template_id)
        if form.validate_on_submit():
            data = dict(form.data)
            template_id = data.pop('template')
Ejemplo n.º 12
0
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    clearCache()  # init fossil cache
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = [(key, [x.encode('utf-8') for x in values])
                       for key, values in request.form.iterlists()]
        query = urllib.urlencode(queryParams, doseq=1)
        # we only need/keep multiple values so we can properly validate the signature.
        # the legacy code below expects a dict with just the first value.
        # if you write a new api endpoint that needs multiple values get them from
        # ``request.values.getlist()`` directly
        queryParams = {key: values[0] for key, values in queryParams}
    else:
        # Parse the actual query string
        queryParams = dict((key, value.encode('utf-8'))
                           for key, value in request.args.iteritems())
        query = request.query_string

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    cookieAuth = get_query_parameter(queryParams, ['ca', 'cookieauth'],
                                     'no') == 'yes'
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'],
                                    0,
                                    integer=True)
    noCache = get_query_parameter(queryParams, ['nc', 'nocache'],
                                  'no') == 'yes'
    pretty = get_query_parameter(queryParams, ['p', 'pretty'], 'no') == 'yes'
    onlyPublic = get_query_parameter(queryParams, ['op', 'onlypublic'],
                                     'no') == 'yes'
    onlyAuthed = get_query_parameter(queryParams, ['oa', 'onlyauthed'],
                                     'no') == 'yes'
    scope = 'read:legacy_api' if request.method == 'GET' else 'write:legacy_api'
    try:
        oauth_valid, oauth_request = oauth.verify_request([scope])
        if not oauth_valid and oauth_request and oauth_request.error_message != 'Bearer token not found.':
            raise BadRequest('OAuth error: {}'.format(
                oauth_request.error_message))
        elif g.get(
                'received_oauth_token'
        ) and oauth_request.error_message == 'Bearer token not found.':
            raise BadRequest('OAuth error: Invalid token')
    except ValueError:
        # XXX: Dirty hack to workaround a bug in flask-oauthlib that causes it
        #      not to properly urlencode request query strings
        #      Related issue (https://github.com/lepture/flask-oauthlib/issues/213)
        oauth_valid = False

    # Get our handler function and its argument and response type
    hook, dformat = HTTPAPIHook.parseRequest(path, queryParams)
    if hook is None or dformat is None:
        raise NotFound

    # Disable caching if we are not just retrieving data (or the hook requires it)
    if request.method == 'POST' or hook.NO_CACHE:
        noCache = True

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    responseUtil = ResponseUtil()
    is_response = False
    try:
        used_session = None
        if cookieAuth:
            used_session = session
            if not used_session.user:  # ignore guest sessions
                used_session = None

        if apiKey or oauth_valid or not used_session:
            if not oauth_valid:
                # Validate the API key (and its signature)
                ak, enforceOnlyPublic = checkAK(apiKey, signature, timestamp,
                                                path, query)
                if enforceOnlyPublic:
                    onlyPublic = True
                # Create an access wrapper for the API key's user
                user = ak.user if ak and not onlyPublic else None
            else:  # Access Token (OAuth)
                at = load_token(oauth_request.access_token.access_token)
                user = at.user if at and not onlyPublic else None
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and user is None:
                cacheKey = normalizeQuery(
                    path,
                    query,
                    remove=('_', 'ak', 'apiKey', 'signature', 'timestamp',
                            'nc', 'nocache', 'oa', 'onlyauthed'))
            else:
                cacheKey = normalizeQuery(path,
                                          query,
                                          remove=('_', 'signature',
                                                  'timestamp', 'nc', 'nocache',
                                                  'oa', 'onlyauthed'))
                if signature:
                    # in case the request was signed, store the result under a different key
                    cacheKey = 'signed_' + cacheKey
        else:
            # We authenticated using a session cookie.
            token = request.headers.get(
                'X-CSRF-Token', get_query_parameter(queryParams,
                                                    ['csrftoken']))
            if used_session.csrf_protected and used_session.csrf_token != token:
                raise HTTPAPIError('Invalid CSRF token', 403)
            user = used_session.user if not onlyPublic else None
            userPrefix = 'user-{}_'.format(used_session.user.id)
            cacheKey = userPrefix + normalizeQuery(
                path,
                query,
                remove=('_', 'nc', 'nocache', 'ca', 'cookieauth', 'oa',
                        'onlyauthed', 'csrftoken'))

        # Bail out if the user requires authentication but is not authenticated
        if onlyAuthed and not user:
            raise HTTPAPIError('Not authenticated', 403)

        addToCache = not hook.NO_CACHE
        cache = GenericCache('HTTPAPI')
        cacheKey = RE_REMOVE_EXTENSION.sub('', cacheKey)
        if not noCache:
            obj = cache.get(cacheKey)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            g.current_api_user = user
            # Perform the actual exporting
            res = hook(user)
            if isinstance(res, current_app.response_class):
                addToCache = False
                is_response = True
                result, extra, complete, typeMap = res, {}, True, {}
            elif isinstance(res, tuple) and len(res) == 4:
                result, extra, complete, typeMap = res
            else:
                result, extra, complete, typeMap = res, {}, True, {}
        if result is not None and addToCache:
            ttl = api_settings.get('cache_ttl')
            if ttl > 0:
                cache.set(cacheKey, (result, extra, ts, complete, typeMap),
                          ttl)
    except HTTPAPIError as e:
        error = e
        if e.getCode():
            responseUtil.status = e.getCode()
            if responseUtil.status == 405:
                responseUtil.headers[
                    'Allow'] = 'GET' if request.method == 'POST' else 'POST'

    if result is None and error is None:
        # TODO: usage page
        raise NotFound
    else:
        if ak and error is None:
            # Commit only if there was an API key and no error
            norm_path, norm_query = normalizeQuery(path,
                                                   query,
                                                   remove=('signature',
                                                           'timestamp'),
                                                   separate=True)
            uri = to_unicode('?'.join(filter(None, (norm_path, norm_query))))
            ak.register_used(request.remote_addr, uri, not onlyPublic)
            db.session.commit()
        else:
            # No need to commit stuff if we didn't use an API key (nothing was written)
            # XXX do we even need this?
            db.session.rollback()

        # Log successful POST api requests
        if error is None and request.method == 'POST':
            logger.info('API request: %s?%s', path, query)
        if is_response:
            return result
        serializer = Serializer.create(dformat,
                                       query_params=queryParams,
                                       pretty=pretty,
                                       typeMap=typeMap,
                                       **hook.serializer_args)
        if error:
            if not serializer.schemaless:
                # if our serializer has a specific schema (HTML, ICAL, etc...)
                # use JSON, since it is universal
                serializer = Serializer.create('json')

            result = fossilize(error)
        else:
            if serializer.encapsulate:
                result = fossilize(
                    HTTPAPIResult(result, path, query, ts, complete, extra),
                    IHTTPAPIExportResultFossil)
                del result['_fossil']

        try:
            data = serializer(result)
            serializer.set_headers(responseUtil)
            return responseUtil.make_response(data)
        except:
            logger.exception('Serialization error in request %s?%s', path,
                             query)
            raise
Ejemplo n.º 13
0
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    clearCache()  # init fossil cache
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = [(key, [x.encode('utf-8') for x in values]) for key, values in request.form.iterlists()]
        query = urllib.urlencode(queryParams, doseq=1)
        # we only need/keep multiple values so we can properly validate the signature.
        # the legacy code below expects a dict with just the first value.
        # if you write a new api endpoint that needs multiple values get them from
        # ``request.values.getlist()`` directly
        queryParams = {key: values[0] for key, values in queryParams}
    else:
        # Parse the actual query string
        queryParams = dict((key, value.encode('utf-8')) for key, value in request.args.iteritems())
        query = request.query_string

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    cookieAuth = get_query_parameter(queryParams, ['ca', 'cookieauth'], 'no') == 'yes'
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'], 0, integer=True)
    noCache = get_query_parameter(queryParams, ['nc', 'nocache'], 'no') == 'yes'
    pretty = get_query_parameter(queryParams, ['p', 'pretty'], 'no') == 'yes'
    onlyPublic = get_query_parameter(queryParams, ['op', 'onlypublic'], 'no') == 'yes'
    onlyAuthed = get_query_parameter(queryParams, ['oa', 'onlyauthed'], 'no') == 'yes'
    scope = 'read:legacy_api' if request.method == 'GET' else 'write:legacy_api'
    try:
        oauth_valid, oauth_request = oauth.verify_request([scope])
        if not oauth_valid and oauth_request and oauth_request.error_message != 'Bearer token not found.':
            raise BadRequest('OAuth error: {}'.format(oauth_request.error_message))
        elif g.get('received_oauth_token') and oauth_request.error_message == 'Bearer token not found.':
            raise BadRequest('OAuth error: Invalid token')
    except ValueError:
        # XXX: Dirty hack to workaround a bug in flask-oauthlib that causes it
        #      not to properly urlencode request query strings
        #      Related issue (https://github.com/lepture/flask-oauthlib/issues/213)
        oauth_valid = False

    # Get our handler function and its argument and response type
    hook, dformat = HTTPAPIHook.parseRequest(path, queryParams)
    if hook is None or dformat is None:
        raise NotFound

    # Disable caching if we are not just retrieving data (or the hook requires it)
    if request.method == 'POST' or hook.NO_CACHE:
        noCache = True

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    responseUtil = ResponseUtil()
    is_response = False
    try:
        used_session = None
        if cookieAuth:
            used_session = session
            if not used_session.user:  # ignore guest sessions
                used_session = None

        if apiKey or oauth_valid or not used_session:
            if not oauth_valid:
                # Validate the API key (and its signature)
                ak, enforceOnlyPublic = checkAK(apiKey, signature, timestamp, path, query)
                if enforceOnlyPublic:
                    onlyPublic = True
                # Create an access wrapper for the API key's user
                user = ak.user if ak and not onlyPublic else None
            else:  # Access Token (OAuth)
                at = load_token(oauth_request.access_token.access_token)
                user = at.user if at and not onlyPublic else None
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and user is None:
                cacheKey = normalizeQuery(path, query,
                                          remove=('_', 'ak', 'apiKey', 'signature', 'timestamp', 'nc', 'nocache',
                                                  'oa', 'onlyauthed'))
            else:
                cacheKey = normalizeQuery(path, query,
                                          remove=('_', 'signature', 'timestamp', 'nc', 'nocache', 'oa', 'onlyauthed'))
                if signature:
                    # in case the request was signed, store the result under a different key
                    cacheKey = 'signed_' + cacheKey
        else:
            # We authenticated using a session cookie.
            token = request.headers.get('X-CSRF-Token', get_query_parameter(queryParams, ['csrftoken']))
            if used_session.csrf_protected and used_session.csrf_token != token:
                raise HTTPAPIError('Invalid CSRF token', 403)
            user = used_session.user if not onlyPublic else None
            userPrefix = 'user-{}_'.format(used_session.user.id)
            cacheKey = userPrefix + normalizeQuery(path, query,
                                                   remove=('_', 'nc', 'nocache', 'ca', 'cookieauth', 'oa', 'onlyauthed',
                                                           'csrftoken'))

        # Bail out if the user requires authentication but is not authenticated
        if onlyAuthed and not user:
            raise HTTPAPIError('Not authenticated', 403)

        addToCache = not hook.NO_CACHE
        cache = GenericCache('HTTPAPI')
        cacheKey = RE_REMOVE_EXTENSION.sub('', cacheKey)
        if not noCache:
            obj = cache.get(cacheKey)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            g.current_api_user = user
            # Perform the actual exporting
            res = hook(user)
            if isinstance(res, current_app.response_class):
                addToCache = False
                is_response = True
                result, extra, complete, typeMap = res, {}, True, {}
            elif isinstance(res, tuple) and len(res) == 4:
                result, extra, complete, typeMap = res
            else:
                result, extra, complete, typeMap = res, {}, True, {}
        if result is not None and addToCache:
            ttl = api_settings.get('cache_ttl')
            if ttl > 0:
                cache.set(cacheKey, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError, e:
        error = e
        if e.getCode():
            responseUtil.status = e.getCode()
            if responseUtil.status == 405:
                responseUtil.headers['Allow'] = 'GET' if request.method == 'POST' else 'POST'
Ejemplo n.º 14
0
 def __init__(self):
     self.storage = GenericCache('flask-session')
Ejemplo n.º 15
0
 def __init__(self):
     self.storage = GenericCache('flask-session')
Ejemplo n.º 16
0
def principal_from_identifier(identifier,
                              allow_groups=False,
                              allow_external_users=False,
                              allow_event_roles=False,
                              allow_category_roles=False,
                              allow_registration_forms=False,
                              allow_emails=False,
                              allow_networks=False,
                              event_id=None,
                              category_id=None,
                              soft_fail=False):
    from indico.modules.categories.models.categories import Category
    from indico.modules.categories.models.roles import CategoryRole
    from indico.modules.events.models.events import Event
    from indico.modules.events.models.roles import EventRole
    from indico.modules.events.registration.models.forms import RegistrationForm
    from indico.modules.groups import GroupProxy
    from indico.modules.networks.models.networks import IPNetworkGroup
    from indico.modules.users import User

    if allow_category_roles and category_id is None and event_id is None:
        raise ValueError(
            'Cannot use category roles without a category/event context')
    if allow_event_roles and event_id is None:
        raise ValueError('Cannot use event roles without an event context')
    if allow_registration_forms and event_id is None:
        raise ValueError(
            'Cannot use registration forms without an event context')

    try:
        type_, data = identifier.split(':', 1)
    except ValueError:
        raise ValueError('Invalid data')

    if type_ == 'User':
        try:
            user_id = int(data)
        except ValueError:
            raise ValueError('Invalid data')
        user = User.get(user_id, is_deleted=(None if soft_fail else False))
        if user is None:
            raise ValueError(f'Invalid user: {user_id}')
        return user
    elif type_ == 'ExternalUser':
        if not allow_external_users:
            raise ValueError('External users are not allowed')
        cache = GenericCache('external-user')
        external_user_data = cache.get(data)
        if not external_user_data:
            raise ValueError('Invalid data')
        user = User.query.filter(
            User.all_emails == external_user_data['email'],
            ~User.is_deleted).first()
        if user:
            return user
        # create a pending user. this user isn't sent to the DB unless it gets added
        # to the sqlalchemy session somehow (e.g. by adding it to an ACL).
        # like this processing form data does not result in something being stored in
        # the database, which is good!
        return User(first_name=external_user_data['first_name'],
                    last_name=external_user_data['last_name'],
                    email=external_user_data['email'],
                    affiliation=external_user_data['affiliation'],
                    address=external_user_data['address'],
                    phone=external_user_data['phone'],
                    is_pending=True)
    elif type_ == 'Group':
        if not allow_groups:
            raise ValueError('Groups are not allowed')
        try:
            provider, name = data.split(':', 1)
        except ValueError:
            raise ValueError('Invalid data')
        if not provider:
            # local group
            try:
                group_id = int(name)
            except ValueError:
                raise ValueError('Invalid data')
            group = GroupProxy(group_id)
        else:
            # multipass group
            group = GroupProxy(name, provider)
        if not soft_fail and group.group is None:
            raise ValueError(f'Invalid group: {data}')
        return group
    elif type_ == 'EventRole':
        if not allow_event_roles:
            raise ValueError('Event roles are not allowed')
        try:
            event_role_id = int(data)
        except ValueError:
            raise ValueError('Invalid data')
        event_role = EventRole.get(event_role_id)
        if event_role is None or event_role.event_id != event_id:
            raise ValueError(f'Invalid event role: {event_role_id}')
        return event_role
    elif type_ == 'CategoryRole':
        if not allow_category_roles:
            raise ValueError('Category roles are not allowed')
        category = None
        if category_id is not None:
            category = Category.get(category_id)
            if category is None:
                raise ValueError(f'Invalid category id: {category_id}')
        elif event_id is not None:
            event = Event.get(event_id)
            if event is None:
                raise ValueError(f'Invalid event id: {event_id}')
            category = event.category
        try:
            category_role_id = int(data)
        except ValueError:
            raise ValueError('Invalid data')
        if soft_fail:
            category_role = CategoryRole.get(category_role_id)
        else:
            category_role = CategoryRole.get_category_role_by_id(
                category, category_role_id)
        if category_role is None:
            raise ValueError(f'Invalid category role: {category_role_id}')
        return category_role
    elif type_ == 'RegistrationForm':
        if not allow_registration_forms:
            raise ValueError('Registration forms are not allowed')

        try:
            reg_form_id = int(data)
        except ValueError:
            raise ValueError('Invalid data')

        registration_form = RegistrationForm.get(
            reg_form_id, is_deleted=(None if soft_fail else False))
        if registration_form is None or registration_form.event_id != event_id:
            raise ValueError(f'Invalid registration form: {reg_form_id}')
        return registration_form
    elif type_ == 'Email':
        if not allow_emails:
            raise ValueError('Emails are not allowed')
        return EmailPrincipal(data)
    elif type_ == 'IPNetworkGroup':
        if not allow_networks:
            raise ValueError('Network groups are not allowed')
        try:
            netgroup_id = int(data)
        except ValueError:
            raise ValueError('Invalid data')
        netgroup = IPNetworkGroup.get(netgroup_id)
        if netgroup is None or (netgroup.hidden and not soft_fail):
            raise ValueError(f'Invalid network group: {netgroup_id}')
        return netgroup
    else:
        raise ValueError('Invalid data')
Ejemplo n.º 17
0
 def __init__(self, duration=DEFAULT_CACHE_TTL):
     self._cache = GenericCache("ZeepCache")
     self._duration = duration
Ejemplo n.º 18
0
 def __init__(self, duration=DEFAULT_CACHE_TTL):
     self._cache = GenericCache("ZeepCache")
     self._duration = duration
Ejemplo n.º 19
0
from indico.modules.events.sessions import Session
from indico.modules.events.timetable.forms import ImportContributionsForm
from indico.modules.events.timetable.operations import update_timetable_entry
from indico.modules.events.tracks.models.tracks import Track
from indico.modules.events.util import check_event_locked, get_field_values, track_time_changes
from indico.util.date_time import format_datetime, format_human_timedelta
from indico.util.i18n import _, ngettext
from indico.util.spreadsheets import send_csv, send_xlsx
from indico.util.string import handle_legacy_description
from indico.web.flask.templating import get_template_module
from indico.web.flask.util import send_file, url_for
from indico.web.forms.base import FormDefaults
from indico.web.forms.fields.principals import serialize_principal
from indico.web.util import jsonify_data, jsonify_form, jsonify_template

export_list_cache = GenericCache('export-list')


def _render_subcontribution_list(contrib):
    tpl = get_template_module(
        'events/contributions/management/_subcontribution_list.html')
    subcontribs = (SubContribution.query.with_parent(contrib).options(
        undefer('attachment_count')).order_by(SubContribution.position).all())
    return tpl.render_subcontribution_list(contrib.event, contrib, subcontribs)


class RHManageContributionsBase(RHManageEventBase):
    """Base class for all contributions management RHs."""
    def _process_args(self):
        RHManageEventBase._process_args(self)
        self.list_generator = ContributionListGenerator(event=self.event)
Ejemplo n.º 20
0
from indico.modules.events.registration.util import (
    create_registration, generate_spreadsheet_from_registrations,
    get_event_section_data, get_ticket_attachments, get_title_uuid,
    make_registration_form)
from indico.modules.events.registration.views import WPManageRegistration
from indico.modules.events.util import ZipGeneratorMixin
from indico.modules.users import User
from indico.util.fs import secure_filename
from indico.util.i18n import _, ngettext
from indico.util.placeholders import replace_placeholders
from indico.util.spreadsheets import send_csv, send_xlsx
from indico.web.flask.templating import get_template_module
from indico.web.flask.util import send_file, url_for
from indico.web.util import jsonify_data, jsonify_template

badge_cache = GenericCache('badge-printing')


def _render_registration_details(registration):
    event = registration.registration_form.event
    tpl = get_template_module(
        'events/registration/management/_registration_details.html')
    return tpl.render_registration_details(
        registration=registration,
        payment_enabled=event.has_feature('payment'))


class RHRegistrationsListManage(RHManageRegFormBase):
    """List all registrations of a specific registration form of an event"""
    def _process(self):
        if self.list_generator.static_link_used:
Ejemplo n.º 21
0
 def _process_pending_users(self, results):
     cache = GenericCache('external-user')
     for entry in results:
         ext_id = entry.pop('_ext_id', None)
         if ext_id is not None:
             cache.set(ext_id, self.externals[ext_id], 86400)
Ejemplo n.º 22
0
                                       reservation_occurrences_schema,
                                       reservation_user_event_schema)
from indico.modules.rb.util import (
    generate_spreadsheet_from_occurrences, get_linked_object,
    group_by_occurrence_date, is_booking_start_within_grace_period,
    serialize_availability, serialize_booking_details, serialize_occurrences)
from indico.util.date_time import now_utc, utc_to_server
from indico.util.i18n import _
from indico.util.spreadsheets import send_csv, send_xlsx
from indico.web.args import use_args, use_kwargs
from indico.web.flask.util import url_for
from indico.web.util import ExpectedError

NUM_SUGGESTIONS = 5

_export_cache = GenericCache('bookings-export')


class RHTimeline(RHRoomBookingBase):
    def _process_args(self):
        self.room = None
        if 'room_id' in request.view_args:
            self.room = Room.get_one(request.view_args['room_id'],
                                     is_deleted=False)

    @use_kwargs({
        'start_dt': fields.DateTime(required=True),
        'end_dt': fields.DateTime(required=True),
        'repeat_frequency': EnumField(RepeatFrequency, missing='NEVER'),
        'repeat_interval': fields.Int(missing=1),
        'room_ids': fields.List(fields.Int(), missing=[]),
Ejemplo n.º 23
0
def load_error_data(uuid):
    return GenericCache('errors').get(uuid)
Ejemplo n.º 24
0
class IndicoSessionInterface(SessionInterface):
    pickle_based = True
    serializer = cPickle
    session_class = IndicoSession
    temporary_session_lifetime = timedelta(days=7)

    def __init__(self):
        self.storage = GenericCache('flask-session')

    def generate_sid(self):
        return str(uuid.uuid4())

    def get_cookie_secure(self, app):
        return request.is_secure

    def get_storage_lifetime(self, app, session):
        # Permanent sessions are stored for exactly the same duration as the session id cookie.
        # "Temporary" session are stored for a period that is not too short/long as some people
        # close their browser very rarely and thus shouldn't be logged out that often.
        if session.permanent:
            return app.permanent_session_lifetime
        else:
            return self.temporary_session_lifetime

    def should_refresh_session(self, app, session):
        if session.new or '_expires' not in session:
            return False
        threshold = self.get_storage_lifetime(app, session) / 2
        return session['_expires'] - datetime.now() < threshold

    def should_refresh_sid(self, app, session):
        if not session.new and self.get_cookie_secure(app) and not session.get('_secure'):
            return True
        if getattr(session, '_refresh_sid', False):
            return True
        return False

    def open_session(self, app, request):
        sid = request.cookies.get(app.session_cookie_name)
        if not sid:
            return self.session_class(sid=self.generate_sid(), new=True)
        data = self.storage.get(sid)
        if data is not None:
            return self.session_class(self.serializer.loads(data), sid=sid)
        return self.session_class(sid=self.generate_sid(), new=True)

    def save_session(self, app, session, response):
        domain = self.get_cookie_domain(app)
        secure = self.get_cookie_secure(app)
        refresh_sid = self.should_refresh_sid(app, session)
        if not session and not session.new:
            # empty session, delete it from storage and cookie
            self.storage.delete(session.sid)
            response.delete_cookie(app.session_cookie_name, domain=domain)
            return

        if not refresh_sid and not session.modified and not self.should_refresh_session(app, session):
            # If the session has not been modified we only store if it needs to be refreshed
            return

        if config.SESSION_LIFETIME > 0:
            # Setting session.permanent marks the session as modified so we only set it when we
            # are saving the session anyway!
            session.permanent = True

        storage_ttl = self.get_storage_lifetime(app, session)
        cookie_lifetime = self.get_expiration_time(app, session)
        session['_expires'] = datetime.now() + storage_ttl

        if refresh_sid:
            self.storage.delete(session.sid)
            session.sid = self.generate_sid()

        session['_secure'] = request.is_secure
        self.storage.set(session.sid, self.serializer.dumps(dict(session)), storage_ttl)
        response.set_cookie(app.session_cookie_name, session.sid, expires=cookie_lifetime, httponly=True,
                            secure=secure)
Ejemplo n.º 25
0
from indico.modules.rb.models.equipment import EquipmentType, RoomEquipmentAssociation
from indico.modules.rb.models.favorites import favorite_room_table
from indico.modules.rb.models.principals import RoomPrincipal
from indico.modules.rb.models.reservation_occurrences import ReservationOccurrence
from indico.modules.rb.models.reservations import Reservation
from indico.modules.rb.models.room_attributes import RoomAttribute, RoomAttributeAssociation
from indico.modules.rb.models.room_bookable_hours import BookableHours
from indico.modules.rb.models.room_nonbookable_periods import NonBookablePeriod
from indico.modules.rb.util import rb_is_admin
from indico.util.i18n import _
from indico.util.serializer import Serializer
from indico.util.string import format_repr, natural_sort_key
from indico.web.flask.util import url_for


_cache = GenericCache('Rooms')


class Room(ProtectionManagersMixin, db.Model, Serializer):
    __tablename__ = 'rooms'
    __table_args__ = (db.UniqueConstraint('id', 'location_id'),  # useless but needed for the LocationMixin fkey
                      db.CheckConstraint("verbose_name != ''", 'verbose_name_not_empty'),
                      {'schema': 'roombooking'})

    default_protection_mode = ProtectionMode.public
    disallowed_protection_modes = frozenset({ProtectionMode.inheriting})

    __api_public__ = (
        'id', 'building', 'name', 'floor', 'longitude', 'latitude', ('number', 'roomNr'), ('location_name', 'location'),
        ('full_name', 'fullName')
    )
Ejemplo n.º 26
0
class IndicoSessionInterface(SessionInterface):
    pickle_based = True
    serializer = pickle
    session_class = IndicoSession
    temporary_session_lifetime = timedelta(days=7)

    def __init__(self):
        self.storage = GenericCache('flask-session')

    def generate_sid(self):
        return str(uuid.uuid4())

    def get_cookie_secure(self, app):
        return request.is_secure

    def get_storage_lifetime(self, app, session):
        # Permanent sessions are stored for exactly the same duration as the session id cookie.
        # "Temporary" session are stored for a period that is not too short/long as some people
        # close their browser very rarely and thus shouldn't be logged out that often.
        if session.permanent:
            return app.permanent_session_lifetime
        else:
            return self.temporary_session_lifetime

    def should_refresh_session(self, app, session):
        if session.new or '_expires' not in session:
            return False
        threshold = self.get_storage_lifetime(app, session) / 2
        return session['_expires'] - datetime.now() < threshold

    def should_refresh_sid(self, app, session):
        if not session.new and self.get_cookie_secure(app) and not session.get('_secure'):
            return True
        if getattr(session, '_refresh_sid', False):
            return True
        return False

    def open_session(self, app, request):
        sid = request.cookies.get(app.session_cookie_name)
        if not sid:
            return self.session_class(sid=self.generate_sid(), new=True)
        data = self.storage.get(sid)
        if data is not None:
            return self.session_class(self.serializer.loads(data), sid=sid)
        return self.session_class(sid=self.generate_sid(), new=True)

    def save_session(self, app, session, response):
        domain = self.get_cookie_domain(app)
        secure = self.get_cookie_secure(app)
        refresh_sid = self.should_refresh_sid(app, session)
        if not session and not session.new:
            # empty session, delete it from storage and cookie
            self.storage.delete(session.sid)
            response.delete_cookie(app.session_cookie_name, domain=domain)
            return

        if not refresh_sid and not session.modified and not self.should_refresh_session(app, session):
            # If the session has not been modified we only store if it needs to be refreshed
            return

        if config.SESSION_LIFETIME > 0:
            # Setting session.permanent marks the session as modified so we only set it when we
            # are saving the session anyway!
            session.permanent = True

        storage_ttl = self.get_storage_lifetime(app, session)
        cookie_lifetime = self.get_expiration_time(app, session)
        session['_expires'] = datetime.now() + storage_ttl

        if refresh_sid:
            self.storage.delete(session.sid)
            session.sid = self.generate_sid()

        session['_secure'] = request.is_secure
        self.storage.set(session.sid, self.serializer.dumps(dict(session)), storage_ttl)
        response.set_cookie(app.session_cookie_name, session.sid, expires=cookie_lifetime, httponly=True,
                            secure=secure)
Ejemplo n.º 27
0
 def _process_pending_users(self, results):
     cache = GenericCache('external-user')
     for entry in results:
         ext_id = entry.pop('_ext_id', None)
         if ext_id is not None:
             cache.set(ext_id, self.externals[ext_id], 86400)
Ejemplo n.º 28
0
from indico.legacy.common.cache import GenericCache
from indico.modules.events.contributions.models.contributions import Contribution
from indico.modules.events.editing.controllers.base import (
    RHEditablesBase, RHEditableTypeEditorBase, RHEditableTypeManagementBase)
from indico.modules.events.editing.models.editable import Editable
from indico.modules.events.editing.models.revision_files import EditingRevisionFile
from indico.modules.events.editing.models.revisions import EditingRevision
from indico.modules.events.editing.operations import assign_editor, generate_editables_zip, unassign_editor
from indico.modules.events.editing.schemas import EditableBasicSchema, EditingEditableListSchema, FilteredEditableSchema
from indico.modules.files.models.files import File
from indico.util.i18n import _
from indico.util.marshmallow import Principal
from indico.web.args import use_kwargs
from indico.web.flask.util import url_for

archive_cache = GenericCache('editables-archive')


class RHEditableList(RHEditableTypeEditorBase):
    """Return the list of editables of the event for a given type."""
    def _process_args(self):
        RHEditableTypeEditorBase._process_args(self)
        self.contributions = (Contribution.query.with_parent(
            self.event).options(joinedload('editables')).order_by(
                Contribution.friendly_id).all())

    def _process(self):
        return (EditingEditableListSchema(many=True,
                                          context={
                                              'editable_type':
                                              self.editable_type