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
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)))
def _get_user_data(self): user_id = request.args.get('user') if user_id is None: return {} elif user_id.isdigit(): # existing fossir 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-fossir 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
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
def _process_identities(obj): if isinstance(obj, IdentityInfo): GenericCache('pending_identities').set( '{}:{}'.format(obj.provider.name, obj.identifier), obj.data) return AvatarProvisionalWrapper(obj) else: return obj.as_avatar
class RHUserEmailsVerify(RHUserBase): flash_user_status = False token_storage = GenericCache('confirm-email') def _validate(self, data): if not data: flash(_('The verification token is invalid or expired.'), 'error') return False, None user = User.get(data['user_id']) if not user or user != self.user: flash( _('This token is for a different fossir user. Please login with the correct account' ), 'error') return False, None existing = UserEmail.find_first(is_user_deleted=False, email=data['email']) if existing and not existing.user.is_pending: if existing.user == self.user: flash( _('This email address is already attached to your account.' )) else: flash( _('This email address is already in use by another account.' ), 'error') return False, existing.user return True, existing.user if existing else None def _process(self): token = request.view_args['token'] data = self.token_storage.get(token) valid, existing = self._validate(data) if valid: self.token_storage.delete(token) if existing and existing.is_pending: logger.info("Found pending user %s to be merged into %s", existing, self.user) # If the pending user has missing names, copy them from the active one # to allow it to be marked as not pending and deleted during the merge. existing.first_name = existing.first_name or self.user.first_name existing.last_name = existing.last_name or self.user.last_name merge_users(existing, self.user) flash( _("Merged data from existing '{}' identity").format( existing.email)) existing.is_pending = False self.user.secondary_emails.add(data['email']) signals.users.email_added.send(self.user, email=data['email']) flash( _('The email address {email} has been added to your account.'). format(email=data['email']), 'success') return redirect(url_for('.user_emails'))
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 `fossir celery unlock %s`', name, name) return cache.set(name, True, 86400) try: return f(*args, **kwargs) finally: cache.delete(name)
def memoize_redis(ttl): """Memoize a function in redis The cached value can be cleared by calling the method ``clear_cached()`` of the decorated function with the same arguments that were used during the function call. To check whether a value has been cached call ``is_cached()`` in the same way. :param ttl: How long the result should be cached. May be a timedelta or a number (seconds). """ from fossir.legacy.common.cache import GenericCache cache = GenericCache('memoize') def decorator(f): def _get_key(args, kwargs): return f.__name__, make_hashable(getcallargs(f, *args, **kwargs)) def _clear_cached(*args, **kwargs): cache.delete(_get_key(args, kwargs)) def _is_cached(*args, **kwargs): return cache.get(_get_key(args, kwargs), _notset) is not _notset @wraps(f) def memoizer(*args, **kwargs): if current_app.config['TESTING'] or current_app.config.get('REPL'): # No memoization during tests or in the shell return f(*args, **kwargs) key = _get_key(args, kwargs) value = cache.get(key, _notset) if value is _notset: value = f(*args, **kwargs) cache.set(key, value, ttl) return value memoizer.clear_cached = _clear_cached memoizer.is_cached = _is_cached return memoizer return decorator
class WPRoomBookingMapOfRoomsWidget(WPNotDecorated): sidemenu_option = 'map' cache = GenericCache('MapOfRooms') def getCSSFiles(self): return WPNotDecorated.getCSSFiles(self) + ['css/mapofrooms.css'] def getJSFiles(self): return WPNotDecorated.getJSFiles(self) + self._includeJSPackage( 'RoomBooking') def _get_widget_params(self): default_location = Location.default_location return { 'aspects': [a.to_serializable() for a in default_location.aspects], 'buildings': default_location.get_buildings(), 'default_repeat': '{}|0'.format(int(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 } def _getBody(self, params): api_key = rb_settings.get('google_maps_api_key') cache_key = str(sorted(dict( request.args, lang=session.lang).items())) + str(crc32(api_key)) html = self.cache.get(cache_key) if html is None: params.update(self._get_widget_params()) params['api_key'] = api_key html = WTemplated('RoomBookingMapOfRoomsWidget').getHTML(params) self.cache.set(cache_key, html, 3600) return html
class OAuthGrant(object): """OAuth grant token""" #: cache entry to store grant tokens _cache = GenericCache('oauth-grant-tokens') def __init__(self, client_id, code, redirect_uri, user, scopes, expires): self.client_id = client_id self.code = code self.redirect_uri = redirect_uri self.user = user self.scopes = scopes self.expires = expires @property def key(self): return self.make_key(self.client_id, self.code) @property def ttl(self): return self.expires - datetime.utcnow() @classmethod def get(cls, client_id, code): key = cls.make_key(client_id, code) return cls._cache.get(key) @classmethod def make_key(cls, client_id, code): return '{}:{}'.format(client_id, code) def delete(self): self._cache.delete(self.key) def save(self): self._cache.set(key=self.key, val=self, time=self.ttl)
def principal_from_fossil(fossil, allow_pending=False, allow_groups=True, allow_missing_groups=False, allow_emails=False, allow_networks=False, existing_data=None): from fossir.modules.networks.models.networks import IPNetworkGroup from fossir.modules.groups import GroupProxy from fossir.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 fossir account in case some of the search criteria did not # match the fossir account user = User.find_first(User.all_emails.contains(email), ~User.is_deleted) 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 else: raise ValueError('Unexpected fossil type: {}'.format(type_))
import posixpath from io import BytesIO from flask import redirect from fossir.core.config import config from fossir.legacy.common.cache import GenericCache from fossir.modules.rb.models.photos import Photo from fossir.modules.rb.models.rooms import Room from fossir.web.flask.util import send_file _cache = GenericCache('Rooms') def _redirect_no_photo(size): return redirect( posixpath.join(config.IMAGES_BASE_URL, 'rooms/{}_photos/NoPhoto.jpg'.format(size))) def room_photo(roomID, size, **kw): cache_key = 'photo-{}-{}'.format(roomID, size) photo_data = _cache.get(cache_key) if photo_data == '*': return _redirect_no_photo(size) elif photo_data is None: photo = Photo.find_first(Room.id == roomID, _join=Photo.room) if photo is None: _cache.set(cache_key, '*') return _redirect_no_photo(size)
import uuid from flask import request from werkzeug.exceptions import Forbidden, NotFound from fossir.legacy.common.cache import GenericCache from fossir.modules.designer.models.templates import DesignerTemplate from fossir.modules.events.management.controllers import RHManageEventBase from fossir.modules.events.management.forms import PosterPrintingForm from fossir.modules.events.posters import PosterPDF from fossir.util.i18n import _ from fossir.web.flask.util import send_file, url_for from fossir.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')
import fossir from fossir.core import signals from fossir.core.config import config from fossir.core.db import db from fossir.core.plugins import url_for_plugin from fossir.legacy.common.cache import GenericCache from fossir.modules.events.layout import layout_settings from fossir.modules.events.layout.models.menu import MenuEntry, MenuEntryType, TransientMenuEntry from fossir.util.caching import memoize_request from fossir.util.signals import named_objects_from_signal, values_from_signal from fossir.util.string import crc32, return_ascii from fossir.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
class fossirSessionInterface(SessionInterface): pickle_based = True serializer = cPickle session_class = fossirSession 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)
def __init__(self): self.storage = GenericCache('flask-session')
from fossir.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 fossir.modules.events.registration.views import WPManageRegistration from fossir.modules.events.util import ZipGeneratorMixin from fossir.modules.users import User from fossir.util.fs import secure_filename from fossir.util.i18n import _, ngettext from fossir.util.placeholders import replace_placeholders from fossir.util.spreadsheets import send_csv, send_xlsx from fossir.web.flask.templating import get_template_module from fossir.web.flask.util import send_file, url_for from fossir.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: return redirect(self.list_generator.get_list_url()) reg_list_kwargs = self.list_generator.get_list_kwargs()