Example #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)
     GenericMailer.send(make_email(email, template=get_template_module('users/emails/verify_email.txt',
                                                                       user=self.user, email=email, token=token)))
Example #2
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)
     GenericMailer.send(make_email(email, template=get_template_module('users/emails/verify_email.txt',
                                                                       user=self.user, email=email, token=token)))
Example #3
0
class RHRoomBookingMapOfRoomsWidget(RHRoomBookingBase):
    def __init__(self, *args, **kwargs):
        RHRoomBookingBase.__init__(self, *args, **kwargs)
        self._cache = GenericCache('MapOfRooms')

    def _checkParams(self):
        RHRoomBookingBase._checkParams(self, request.args)
        self._room_id = request.args.get('roomID')

    def _process(self):
        key = str(
            sorted(
                dict(request.args,
                     lang=session.lang,
                     user=session.user.getId()).items()))
        html = self._cache.get(key)
        if not html:
            default_location = Location.default_location
            aspects = [a.to_serializable() for a in default_location.aspects]
            buildings = default_location.get_buildings()
            html = WPRoomBookingMapOfRoomsWidget(
                self,
                aspects=aspects,
                buildings=buildings,
                room_id=self._room_id,
                default_repeat='{}|0'.format(RepeatFrequency.NEVER),
                default_start_dt=datetime.combine(date.today(),
                                                  Location.working_time_start),
                default_end_dt=datetime.combine(date.today(),
                                                Location.working_time_end),
                repeat_mapping=RepeatMapping.mapping).display()
            self._cache.set(key, html, 3600)
        return html
Example #4
0
class RHRoomBookingMapOfRoomsWidget(RHRoomBookingBase):
    def __init__(self, *args, **kwargs):
        RHRoomBookingBase.__init__(self, *args, **kwargs)
        self._cache = GenericCache('MapOfRooms')

    def _checkParams(self):
        RHRoomBookingBase._checkParams(self, request.args)
        self._room_id = request.args.get('roomID')

    def _process(self):
        key = str(sorted(dict(request.args, lang=session.lang, user=session.user.getId()).items()))
        html = self._cache.get(key)
        if not html:
            default_location = Location.default_location
            aspects = [a.to_serializable() for a in default_location.aspects]
            buildings = default_location.get_buildings()
            html = WPRoomBookingMapOfRoomsWidget(self,
                                                 aspects=aspects,
                                                 buildings=buildings,
                                                 room_id=self._room_id,
                                                 default_repeat='{}|0'.format(RepeatFrequency.NEVER),
                                                 default_start_dt=datetime.combine(date.today(),
                                                                                   Location.working_time_start),
                                                 default_end_dt=datetime.combine(date.today(),
                                                                                 Location.working_time_end),
                                                 repeat_mapping=RepeatMapping.getMapping()).display()
            self._cache.set(key, html, 3600)
        return html
Example #5
0
 def wrapper(*args, **kwargs):
     cache = GenericCache('task-locks')
     name = current_task.name
     if cache.get(name):
         Logger.get('celery').warning('Task {} is locked; not executing it'.format(name))
         return
     cache.set(name, True)
     try:
         return f(*args, **kwargs)
     finally:
         cache.delete(name)
Example #6
0
 def wrapper(*args, **kwargs):
     cache = GenericCache('task-locks')
     name = current_task.name
     if cache.get(name):
         Logger.get('celery').warning('Task {} is locked; not executing it'.format(name))
         return
     cache.set(name, True)
     try:
         return f(*args, **kwargs)
     finally:
         cache.delete(name)
Example #7
0
File: mail.py Project: Ictp/indico
def send_login_info(user, event=None):
    token_storage = GenericCache('resetpass')
    endpoint = 'event.confLogin-resetPassword' if event else 'user.signIn-resetPassword'

    idList = user.getIdentityList()
    logins = []
    for id in idList:
        if not hasattr(id, 'setPassword'):
            config = Config.getInstance()
            extra_message = config.getAuthenticatorConfigById(id.getAuthenticatorTag()).get("ResetPasswordMessage")
            msg = _("Sorry, you are using an externally managed account (%s) to login into Indico.") % id.getLogin()
            if extra_message:
                msg += "\n" + extra_message
            logins.append({
                'tag': id.getAuthenticatorTag(),
                'login': id.getLogin(),
                'error': msg
            })
        else:
            tag = id.getAuthenticatorTag()
            login = id.getLogin()
            data = {'tag': tag, 'login': login}
            token = str(uuid.uuid4())
            while token_storage.get(token):
                token = str(uuid.uuid4())
            token_storage.set(token, data, 6*3600)
            url = url_for(endpoint, event, token=token, _external=True, _secure=True)
            logins.append({
                'tag': tag,
                'login': login,
                'link': url
            })
    if not logins:
        url = urlHandlers.UHUserDetails.getURL(user)
        text = _("Sorry, we did not find your login.\nPlease, create one here:\n%s") % url
    else:
        text = _("You can use the following links within the next six hours to reset your password.")
        for entry in logins:
            text += "\n\n==================\n"
            if 'link' in entry:
                text += _("Click below to reset your password for the %s login '%s':\n") % (entry['tag'],
                                                                                            entry['login'])
                text += entry['link']
            else:
                text += entry['error']
            text += "\n==================\n"
    maildata = {
        "fromAddr": "Indico Mailer <%s>" % Config.getInstance().getNoReplyEmail(),
        "toList": [user.getEmail()],
        "subject": _("[%s] Login Information") % getSubjectIndicoTitle(),
        "body": text
    }
    GenericMailer.send(GenericNotification(maildata))
Example #8
0
 def has_member(self, user):
     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
Example #9
0
class SudsCache(Cache):
    _instance = None

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

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

    def put(self, key, val):
        self._cache.set(key, val, self._duration)

    def purge(self, key):
        self._cache.delete(key)
Example #10
0
 def has_member(self, user):
     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
Example #11
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()
Example #12
0
class CachedReport(object):
    """
    This class acts as a wrapper for functions which return a report object,
    by decorating the get<report> methods with the memonize function in the
    BaseStatisticsReport object, the result is wrapped here and its age
    is compared with the TTL if in the cache, either returning said item or
    allowing the method to generate a new one.
    """

    _config = StatisticsConfig()

    def __init__(self, function):
        self._function = function

        # Cache bucket per implementation
        plugin = function.__module__.split('.')[3]
        self._cache = GenericCache(plugin + 'StatisticsCache')

    def getReport(self, *args, **kwargs):
        """
        Ascertain if live updating first, if so disregard and continue.
        """

        ttl = self._config.getUpdateInterval()

        if not self._config.hasCacheEnabled():
            return self._function(*args, **kwargs)

        keyParams = list(args)
        keyParams.extend([self._function.__module__, self._function.__name__])
        key = self._generateKey(keyParams)

        resource = self._cache.get(key, None)

        if not resource:
            result = self._function(*args, **kwargs)
            self._cache.set(key, result, ttl)
            return result
        else:
            return resource

    def _generateKey(self, params):
        """
        Generates a unique key for caching against the params given.
        """
        return reduce(lambda x, y: str(x) + '-' + str(y), params)
Example #13
0
class CachedReport(object):
    """
    This class acts as a wrapper for functions which return a report object,
    by decorating the get<report> methods with the memonize function in the
    BaseStatisticsReport object, the result is wrapped here and its age
    is compared with the TTL if in the cache, either returning said item or
    allowing the method to generate a new one.
    """

    _config = StatisticsConfig()

    def __init__(self, function):
        self._function = function

        # Cache bucket per implementation
        plugin = function.__module__.split('.')[3]
        self._cache = GenericCache(plugin + 'StatisticsCache')

    def getReport(self, *args, **kwargs):
        """
        Ascertain if live updating first, if so disregard and continue.
        """

        ttl = self._config.getUpdateInterval()

        if not self._config.hasCacheEnabled():
            return self._function(*args, **kwargs)

        keyParams = list(args)
        keyParams.extend([self._function.__module__, self._function.__name__])
        key = self._generateKey(keyParams)

        resource = self._cache.get(key, None)

        if not resource:
            result = self._function(*args, **kwargs)
            self._cache.set(key, result, ttl)
            return result
        else:
            return resource

    def _generateKey(self, params):
        """
        Generates a unique key for caching against the params given.
        """
        return reduce(lambda x, y: str(x) + '-' + str(y), params)
Example #14
0
File: cache.py Project: Ictp/indico
class SudsCache(Cache):
    _instance = None

    @classmethod
    def getInstance(cls, duration=None):
        if cls._instance is None:
            cls._instance = SudsCache(duration)
        return cls._instance

    def __init__(self, duration=None):
        self._cache = GenericCache("SudsCache")
        if duration is None:
            duration = 24 * 3600 # we put as default 1 day cache
        self._duration = duration

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

    def put(self, key, val):
        self._cache.set(key, val, self._duration)

    def purge(self, key):
        self._cache.delete(key)
Example #15
0
class SudsCache(Cache):
    _instance = None

    @classmethod
    def getInstance(cls, duration=None):
        if cls._instance is None:
            cls._instance = SudsCache(duration)
        return cls._instance

    def __init__(self, duration=None):
        self._cache = GenericCache("SudsCache")
        if duration is None:
            duration = 24 * 3600  # we put as default 1 day cache
        self._duration = duration

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

    def put(self, key, val):
        self._cache.set(key, val, self._duration)

    def purge(self, key):
        self._cache.delete(key)
Example #16
0
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    ContextManager.destroy()
    clearCache()  # init fossil cache
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict((key, value.encode('utf-8')) for key, value in request.form.iteritems())
        query = urllib.urlencode(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

    dbi = DBMgr.getInstance()
    dbi.startRequest()

    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()
    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
                aw = buildAW(ak, onlyPublic)
            else:  # Access Token (OAuth)
                at = load_token(oauth_request.access_token.access_token)
                aw = buildAW(at, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() 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.
            if Config.getInstance().getCSRFLevel() >= 2:
                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)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(used_session.avatar)
            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 aw.getUser():
            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:
            ContextManager.set("currentAW", aw)
            # Perform the actual exporting
            res = hook(aw)
            if 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')
            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'
Example #17
0
File: user.py Project: NIIF/indico
    def _confirm_email_address(self, email, data_type):
        email = email.strip().lower()

        if not validMail(email):
            raise NoReportError(_("Invalid email address: {0}").format(email))

        # Prevent adding the primary email as a secondary email
        if data_type == 'secondaryEmails' and email == self._avatar.getEmail():
            raise NoReportError(_("{0} is already the primary email address "
                                  "and cannot be used as a secondary email address.").format(email))

        # When setting a secondary email as primary, set it automatically and
        # re-index the user's emails without sending a confirmation email
        # (We assume the secondary emails are valid)
        if data_type == 'email' and email in self._avatar.getSecondaryEmails():
            self._avatar.removeSecondaryEmail(email)
            self._avatar.setEmail(email, reindex=True)
            return False

        existing = AvatarHolder().match({'email': email}, searchInAuthenticators=False)
        if existing:
            if any(av for av in existing if av != self._avatar):
                raise NoReportError(_("The email address {0} is already used by another user.").format(email))
            else:  # The email is already set correctly for the user: Do nothing
                return False

        # New email address
        token_storage = GenericCache('confirm-email')
        data = {'email': email, 'data_type': data_type, 'uid': self._avatar.getId()}
        token = str(uuid.uuid4())
        while token_storage.get(token):
            token = str(uuid.uuid4())
        token_storage.set(token, data, 24 * 3600)
        url = url_for('user.confirm_email', token=token, _external=True, _secure=True)

        if data_type == 'email':
            body_format = _(
                "Dear {0},\n"
                "You requested to change your account's primary email address.\n"
                "Please open the link below within 24 hours to confirm and activate this email address:\n"
                "\n{1}\n\n"
                "--\n"
                "Indico"
            )
        else:
            body_format = _(
                "Dear {0},\n"
                "You added this email address to your account's secondary emails list.\n"
                "Please open the link below within 24 hours to confirm and activate this email address:\n"
                "\n{1}\n\n"
                "--\n"
                "Indico"
            )

        confirmation = {
            'toList': [email],
            'fromAddr': Config.getInstance().getSupportEmail(),
            'subject': _("[Indico] Verify your email address"),
            'body': body_format.format(self._avatar.getFirstName(), url)
        }

        # Send mail with template message and link
        GenericMailer.send(GenericNotification(confirmation))
        return True
Example #18
0
def handler(req, **params):
    ContextManager.destroy()
    logger = Logger.get('httpapi')
    path, query = req.URLFields['PATH_INFO'], req.URLFields['QUERY_STRING']
    if req.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict(req.form)
        for key, value in queryParams.iteritems():
            queryParams[key] = [str(value)]
        query = urllib.urlencode(remove_lists(queryParams))
    else:
        # Parse the actual query string
        queryParams = parse_qs(query)

    dbi = DBMgr.getInstance()
    dbi.startRequest()
    minfo = HelperMaKaCInfo.getMaKaCInfoInstance()
    if minfo.getRoomBookingModuleActive():
        Factory.getDALManager().connect()

    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'

    # 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 apache.SERVER_RETURN, apache.HTTP_NOT_FOUND

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

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    try:
        session = None
        if cookieAuth:
            session = getSessionForReq(req)
            if not session.getUser():  # ignore guest sessions
                session = None

        if apiKey or not session:
            # 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
            aw = buildAW(ak, req, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() 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.
            if Config.getInstance().getCSRFLevel() >= 2:
                token = req.headers_in.get('X-CSRF-Token', get_query_parameter(queryParams, ['csrftoken']))
                if session.csrf_token != token:
                    raise HTTPAPIError('Invalid CSRF token', apache.HTTP_FORBIDDEN)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(session.getUser())
            userPrefix = 'user-' + session.getUser().getId() + '_'
            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 aw.getUser():
            raise HTTPAPIError('Not authenticated', apache.HTTP_FORBIDDEN)

        obj = None
        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:
            # Perform the actual exporting
            res = hook(aw, req)
            if 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 = HelperMaKaCInfo.getMaKaCInfoInstance().getAPICacheTTL()
            cache.set(cacheKey, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError, e:
        error = e
        if e.getCode():
            req.status = e.getCode()
            if req.status == apache.HTTP_METHOD_NOT_ALLOWED:
                req.headers_out['Allow'] = 'GET' if req.method == 'POST' else 'POST'
Example #19
0
def handler(req, **params):
    ContextManager.destroy()
    logger = Logger.get("httpapi")
    path, query = req.URLFields["PATH_INFO"], req.URLFields["QUERY_STRING"]
    if req.method == "POST":
        # Convert POST data to a query string
        queryParams = dict(req.form)
        for key, value in queryParams.iteritems():
            queryParams[key] = [str(value)]
        query = urllib.urlencode(remove_lists(queryParams))
    else:
        # Parse the actual query string
        queryParams = parse_qs(query)

    dbi = DBMgr.getInstance()
    dbi.startRequest()
    minfo = HelperMaKaCInfo.getMaKaCInfoInstance()
    if minfo.getRoomBookingModuleActive():
        Factory.getDALManager().connect()

    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"

    # 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 apache.SERVER_RETURN, apache.HTTP_NOT_FOUND

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

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    try:
        sessionUser = getSessionForReq(req).getUser() if cookieAuth else None
        if apiKey or not sessionUser:
            # 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
            aw = buildAW(ak, req, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() 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.
            # Reject POST for security reasons (CSRF)
            if req.method == "POST":
                raise HTTPAPIError("Cannot POST when using cookie authentication", apache.HTTP_FORBIDDEN)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(sessionUser)
            userPrefix = "user-" + sessionUser.getId() + "_"
            cacheKey = userPrefix + normalizeQuery(
                path, query, remove=("nc", "nocache", "ca", "cookieauth", "oa", "onlyauthed")
            )

        # Bail out if the user requires authentication but is not authenticated
        if onlyAuthed and not aw.getUser():
            raise HTTPAPIError("Not authenticated", apache.HTTP_FORBIDDEN)

        obj = None
        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:
            # Perform the actual exporting
            res = hook(aw, req)
            if 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 = HelperMaKaCInfo.getMaKaCInfoInstance().getAPICacheTTL()
            cache.set(cacheKey, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError, e:
        error = e
        if e.getCode():
            req.status = e.getCode()
            if req.status == apache.HTTP_METHOD_NOT_ALLOWED:
                req.headers_out["Allow"] = "GET" if req.method == "POST" else "POST"
Example #20
0
def send_login_info(user, event=None):
    token_storage = GenericCache('resetpass')
    endpoint = 'event.confLogin-resetPassword' if event else 'user.signIn-resetPassword'

    idList = user.getIdentityList()
    logins = []
    for id in idList:
        if not hasattr(id, 'setPassword'):
            config = Config.getInstance()
            extra_message = config.getAuthenticatorConfigById(
                id.getAuthenticatorTag()).get("ResetPasswordMessage")
            msg = _(
                "Sorry, you are using an externally managed account (%s) to login into Indico."
            ) % id.getLogin()
            if extra_message:
                msg += "\n" + extra_message
            logins.append({
                'tag': id.getAuthenticatorTag(),
                'login': id.getLogin(),
                'error': msg
            })
        else:
            tag = id.getAuthenticatorTag()
            login = id.getLogin()
            data = {'tag': tag, 'login': login}
            token = str(uuid.uuid4())
            while token_storage.get(token):
                token = str(uuid.uuid4())
            token_storage.set(token, data, 6 * 3600)
            url = url_for(endpoint,
                          event,
                          token=token,
                          _external=True,
                          _secure=True)
            logins.append({'tag': tag, 'login': login, 'link': url})
    if not logins:
        url = urlHandlers.UHUserDetails.getURL(user)
        text = _(
            "Sorry, we did not find your login.\nPlease, create one here:\n%s"
        ) % url
    else:
        text = _(
            "You can use the following links within the next six hours to reset your password."
        )
        for entry in logins:
            text += "\n\n==================\n"
            if 'link' in entry:
                text += _(
                    "Click below to reset your password for the %s login '%s':\n"
                ) % (entry['tag'], entry['login'])
                text += entry['link']
            else:
                text += entry['error']
            text += "\n==================\n"
    maildata = {
        "fromAddr":
        "Indico Mailer <%s>" % Config.getInstance().getNoReplyEmail(),
        "toList": [user.getEmail()],
        "subject": _("[%s] Login Information") % getSubjectIndicoTitle(),
        "body": text
    }
    GenericMailer.send(GenericNotification(maildata))
Example #21
0
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    ContextManager.destroy()
    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

    dbi = DBMgr.getInstance()
    dbi.startRequest()

    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
                aw = buildAW(ak, onlyPublic)
            else:  # Access Token (OAuth)
                at = load_token(oauth_request.access_token.access_token)
                aw = buildAW(at, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() 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.
            if Config.getInstance().getCSRFLevel() >= 2:
                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)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(used_session.avatar)
            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 aw.getUser():
            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:
            ContextManager.set("currentAW", aw)
            # Perform the actual exporting
            res = hook(aw)
            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'
Example #22
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):
        return self.get_cookie_secure(app) and not session.get('_secure')

    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 app.config['INDICO_SESSION_PERMANENT']:
            # 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)
Example #23
0
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    ContextManager.destroy()
    clearCache()  # init fossil cache
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict((key, value.encode('utf-8')) for key, value in request.form.iteritems())
        query = urllib.urlencode(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

    dbi = DBMgr.getInstance()
    dbi.startRequest()
    minfo = HelperMaKaCInfo.getMaKaCInfoInstance()
    if minfo.getRoomBookingModuleActive():
        Factory.getDALManager().connect()

    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'
    oauthToken = 'oauth_token' in queryParams

    # 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()
    try:
        used_session = None
        if cookieAuth:
            used_session = session
            if not used_session.user:  # ignore guest sessions
                used_session = None

        if apiKey or oauthToken or not used_session:
            if not oauthToken:
                # 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
                aw = buildAW(ak, onlyPublic)
            else: # Access Token (OAuth)
                at = OAuthUtils.OAuthCheckAccessResource()
                aw = buildAW(at, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() 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.
            if Config.getInstance().getCSRFLevel() >= 2:
                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)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(used_session.user)
            userPrefix = 'user-' + used_session.user.getId() + '_'
            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 aw.getUser():
            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:
            # Perform the actual exporting
            res = hook(aw)
            if 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 = HelperMaKaCInfo.getMaKaCInfoInstance().getAPICacheTTL()
            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'
Example #24
0
def handler(req, **params):
    ContextManager.destroy()
    logger = Logger.get('httpapi')
    path, query = req.URLFields['PATH_INFO'], req.URLFields['QUERY_STRING']
    if req.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict(req.form)
        for key, value in queryParams.iteritems():
            queryParams[key] = [str(value)]
        query = urllib.urlencode(remove_lists(queryParams))
    else:
        # Parse the actual query string
        queryParams = parse_qs(query)

    dbi = DBMgr.getInstance()
    dbi.startRequest()
    minfo = HelperMaKaCInfo.getMaKaCInfoInstance()
    if minfo.getRoomBookingModuleActive():
        Factory.getDALManager().connect()

    mode = path.split('/')[1]

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'],
                                    0,
                                    integer=True)
    no_cache = 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'

    # Disable caching if we are not exporting
    if mode != 'export':
        no_cache = True

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

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    try:
        # 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
        aw = buildAW(ak, req, onlyPublic)
        # Get rid of API key in cache key if we did not impersonate a user
        if ak and aw.getUser() is None:
            cache_key = normalizeQuery(path,
                                       query,
                                       remove=('ak', 'apiKey', 'signature',
                                               'timestamp', 'nc', 'nocache'))
        else:
            cache_key = normalizeQuery(path,
                                       query,
                                       remove=('signature', 'timestamp', 'nc',
                                               'nocache'))
            if signature:
                # in case the request was signed, store the result under a different key
                cache_key = 'signed_' + cache_key

        obj = None
        addToCache = True
        cache = GenericCache('HTTPAPI')
        cache_key = RE_REMOVE_EXTENSION.sub('', cache_key)
        if not no_cache:
            obj = cache.get(cache_key)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            # Perform the actual exporting
            res = func(aw, req)
            if 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 = HelperMaKaCInfo.getMaKaCInfoInstance().getAPICacheTTL()
            cache.set(cache_key, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError, e:
        error = e
        if e.getCode():
            req.status = e.getCode()
            if req.status == apache.HTTP_METHOD_NOT_ALLOWED:
                req.headers_out[
                    'Allow'] = 'GET' if req.method == 'POST' else 'POST'
Example #25
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 app.config['INDICO_SESSION_PERMANENT']:
            # 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)
Example #26
0
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    ContextManager.destroy()
    clearCache()  # init fossil cache
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict((key, value.encode('utf-8'))
                           for key, value in request.form.iteritems())
        query = urllib.urlencode(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

    dbi = DBMgr.getInstance()
    dbi.startRequest()

    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'
    oauthToken = 'oauth_token' in queryParams
    # Check if OAuth data is supplied in the Authorization header
    if not oauthToken and request.headers.get('Authorization') is not None:
        oauthToken = 'oauth_token' in request.headers.get('Authorization')

    # 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()
    try:
        used_session = None
        if cookieAuth:
            used_session = session
            if not used_session.avatar:  # ignore guest sessions
                used_session = None

        if apiKey or oauthToken or not used_session:
            if not oauthToken:
                # 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
                aw = buildAW(ak, onlyPublic)
            else:  # Access Token (OAuth)
                at = OAuthUtils.OAuthCheckAccessResource()
                aw = buildAW(at, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() 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.
            if Config.getInstance().getCSRFLevel() >= 2:
                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)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(used_session.avatar)
            userPrefix = 'user-' + used_session.avatar.getId() + '_'
            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 aw.getUser():
            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:
            ContextManager.set("currentAW", aw)
            # Perform the actual exporting
            res = hook(aw)
            if 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')
            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'
Example #27
0
def handler(req, **params):
    ContextManager.destroy()
    logger = Logger.get('httpapi')
    path, query = req.URLFields['PATH_INFO'], req.URLFields['QUERY_STRING']
    if req.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict(req.form)
        for key, value in queryParams.iteritems():
            queryParams[key] = [str(value)]
        query = urllib.urlencode(remove_lists(queryParams))
    else:
        # Parse the actual query string
        queryParams = parse_qs(query)

    dbi = DBMgr.getInstance()
    dbi.startRequest()
    minfo = HelperMaKaCInfo.getMaKaCInfoInstance()
    if minfo.getRoomBookingModuleActive():
        Factory.getDALManager().connect()

    mode = path.split('/')[1]

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'], 0, integer=True)
    no_cache = 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'

    # Disable caching if we are not exporting
    if mode != 'export':
        no_cache = True

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

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    try:
        # 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
        aw = buildAW(ak, req, onlyPublic)
        # Get rid of API key in cache key if we did not impersonate a user
        if ak and aw.getUser() is None:
            cache_key = normalizeQuery(path, query, remove=('ak', 'apiKey', 'signature', 'timestamp', 'nc', 'nocache'))
        else:
            cache_key = normalizeQuery(path, query, remove=('signature', 'timestamp', 'nc', 'nocache'))
            if signature:
                # in case the request was signed, store the result under a different key
                cache_key = 'signed_' + cache_key

        obj = None
        addToCache = True
        cache = GenericCache('HTTPAPI')
        cache_key = RE_REMOVE_EXTENSION.sub('', cache_key)
        if not no_cache:
            obj = cache.get(cache_key)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            # Perform the actual exporting
            res = func(aw, req)
            if 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 = HelperMaKaCInfo.getMaKaCInfoInstance().getAPICacheTTL()
            cache.set(cache_key, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError, e:
        error = e
        if e.getCode():
            req.status = e.getCode()
            if req.status == apache.HTTP_METHOD_NOT_ALLOWED:
                req.headers_out['Allow'] = 'GET' if req.method == 'POST' else 'POST'