def __init__(self, app, request): self.app = app self.request = request # Alias. self.current_user = self.auth_current_user area_name = self.get_area_name() if area_name not in ("docs", "www"): # TODO instead of 404, redirect to a page to create the area, # if the are doesn't exist. # For now, only 404 is allowed. abort(404) self.area = Area.get_by_key_name(area_name) if self.area is None: self.area = Area.get_or_insert(key_name=area_name, name=area_name) # Get sitename from config or use host minus port as default # sitename. sitename = self.request.host.rsplit(":", 1)[0] # Add some common stuff to context. self.context = self.request.context = { "area": self.area, "current_url": self.request.url, "sitename": get_config("moe", "sitename", sitename), "analytics_code": get_config("moe", "analytics_code", None), "dev": get_config("tipfy", "dev"), "apps_installed": get_config("tipfy", "apps_installed"), }
def __init__(self, app, request): self.app = app self.request = request area_name = self.get_area_name() if area_name not in ('docs', 'www'): # TODO instead of 404, redirect to a page to create the area, # if the are doesn't exist. # For now, only 404 is allowed. abort(404) self.area = Area.get_by_key_name(area_name) if self.area is None: self.area = Area.get_or_insert(key_name=area_name, name=area_name) # Get sitename from config or use host minus port as default # sitename. sitename = self.request.host.rsplit(':', 1)[0] # Add some common stuff to context. self.context = self.request.context = { 'area': self.area, 'current_url': self.request.url, 'sitename': get_config('moe', 'sitename', sitename), 'analytics_code': get_config('moe', 'analytics_code', None), 'dev': get_config('tipfy', 'dev'), 'apps_installed': get_config('tipfy', 'apps_installed'), }
def set_translations_from_request(): """Sets a translations object for the current request. It will use the configuration for ``locale_request_lookup`` to search for a key in ``GET``, ``POST``, cookie or keywords in the current URL rule. The configuration defines the search order. If no locale is set in any of these, uses the default locale set in config. By default it gets the locale from a ``lang`` GET parameter, and if not set tries to get it from a cookie. This is represented by the default configuration value ``[('args', 'lang'), ('cookies', 'tipfy.locale')]``. :returns: None. """ locale = None request = Tipfy.request for method, key in get_config(__name__, 'locale_request_lookup'): if method in ('args', 'form', 'cookies'): # Get locale from GET, POST or cookies. locale = getattr(request, method).get(key, None) elif method == 'rule_args': # Get locale from current URL rule keywords. locale = request.rule_args.get(key, None) if locale is not None: break else: locale = get_config(__name__, 'locale') set_translations(locale)
def get_rules(): """Returns a list of URL rules for the application. The list can be defined entirely here or in separate ``urls.py`` files. Here we show an example of joining all rules from the ``apps_installed`` listed in config. """ entry_points = get_config('tipfy', 'apps_entry_points') if get_config('moe', 'use_subdomain', False): kwargs = {'subdomain': '<area_name>'} else: kwargs = {'defaults': {'area_name': 'www'}} rules = [ # This is a dummy rule pointing to wiki start page. Replace it by # one pointing to a homepage handler. Rule('/', endpoint='home/index', handler='moe.wiki.handlers.WikiViewHandler', **kwargs), ] for app_module in get_config('tipfy', 'apps_installed'): try: # Get the rules from each app installed and extend our rules. app_rules = import_string('%s.urls.get_rules' % app_module)() entry_point = entry_points.get(app_module) if entry_point: # Submount using the entry point. rules.append(Submount(entry_point, app_rules)) else: # Just append the rules. rules.extend(app_rules) except ImportError: pass return rules
def get_rules(): # A protected path (by default '/pages') is used by everything related to # the wiki operation. Everything else is considered a wiki content page. protected_path = '/' + get_config('moe.wiki', 'protected_path') # Take the area name from the subdomain if they are in use. Otherwise # assume that this will be used in a single domain. if get_config('moe', 'use_subdomain', False): kwargs = {'subdomain': '<area_name>'} else: kwargs = {'defaults': {'area_name': 'www'}} rules = [ # Initial page. Rule('/', endpoint='wiki/index', handler='moe.wiki.handlers.WikiViewHandler', **kwargs), Submount(protected_path, [ # Base for the internal pages. Rule('/', endpoint='wiki/pages', handler='moe.wiki.handlers.WikiOverviewHandler', **kwargs), # Lists all pages. Rule('/list', endpoint='wiki/list', handler='moe.wiki.handlers.WikiPageListHandler', **kwargs), # Lists all child pages for a given page. Rule('/list/<path:page_path>', endpoint='wiki/list', handler='moe.wiki.handlers.WikiPageListHandler', **kwargs), # Lists all pages (Atom format). Rule('/list-atom', endpoint='wiki/list-atom', handler='moe.wiki.handlers.WikiPageListFeedHandler', **kwargs), # Lists all child pages for a given page (Atom format). Rule('/list-atom/<path:page_path>', endpoint='wiki/list-atom', handler='moe.wiki.handlers.WikiPageListFeedHandler', **kwargs), # Lists all changes. Rule('/changes', endpoint='wiki/changes', handler='moe.wiki.handlers.WikiChangesHandler', **kwargs), # Lists all changes for a given page. Rule('/changes/<path:page_path>', endpoint='wiki/changes', handler='moe.wiki.handlers.WikiPageChangesHandler', **kwargs), # Lists all changes (Atom format). Rule('/changes-atom', endpoint='wiki/changes-atom', handler='moe.wiki.handlers.WikiChangesFeedHandler', **kwargs), # Lists all changes for a given page (Atom format). Rule('/changes-atom/<path:page_path>', endpoint='wiki/changes-atom', handler='moe.wiki.handlers.WikiPageChangesFeedHandler', **kwargs), # Edition overview. Rule('/edit/', endpoint='wiki/edit', handler='moe.wiki.handlers.WikiEditOverviewHandler', **kwargs), # Edits a page. Rule('/edit/<path:page_path>', endpoint='wiki/edit', handler='moe.wiki.handlers.WikiEditHandler', **kwargs), # Diffs overview. Rule('/diff/', endpoint='wiki/diff', handler='moe.wiki.handlers.WikiDiffOverviewHandler', **kwargs), # Show diffs for a page revision. Rule('/diff/<path:page_path>', endpoint='wiki/diff', handler='moe.wiki.handlers.WikiDiffHandler', **kwargs), # Reparse all pages. # Rule('/reparse/', endpoint='wiki/reparse', handler='moe.wiki.handlers.WikiReparseHandler', **kwargs), ]), # A wiki page. Rule('/<path:page_path>', endpoint='wiki/index', handler='moe.wiki.handlers.WikiViewHandler', **kwargs), ] return rules
def get(self, board, page=0): if page > self.PAGES: raise NotFound() if page == 0: cache = models.Cache.load("board", board) if cache: return Response(cache.data) data = {} data['threads'] = get_threads(board,page=page) # last threads data['show_captcha'] = True data['reply'] = True data['board_name'] = self.NAMES.get(board) or "Woooo???" data['board'] = board # board name data['boards'] = get_config("aib", "boardlist") data['pages'] = range(self.PAGES) data['overlay'] = board in self.OVER html = render_template("board.html", **data) if page == 0: cache = models.Cache.create("board", board) cache.data = html cache.put() return Response(html)
def handle_exception(self, e, handler=None): if get_config('tipfy', 'dev'): # Always raise the exception in dev, so we can debug it. raise return ExceptionHandler(Tipfy.app, Tipfy.request).dispatch('get', exception=e)
def option_modsign(request, data): if data.get('name') != get_config("aib.ib", "mod_name"): return user = users.get_current_user() if users.is_current_user_admin(): data['typ'] = 'modpost'
def user_model(self): """Returns the configured user model. :return: A :class:`tipfy.ext.auth.model.User` class. """ return import_string(get_config(__name__, 'user_model'))
def _validate_recaptcha(self, challenge, response, remote_addr): """Performs the actual validation.""" private_key = get_config('tipfy.ext.wtforms', 'recaptcha_private_key') result = urlfetch.fetch( url=RECAPTCHA_VERIFY_SERVER, method=urlfetch.POST, headers={'Content-Type': 'application/x-www-form-urlencoded'}, payload=url_encode({ 'privatekey': private_key, 'remoteip': remote_addr, 'challenge': challenge, 'response': response })) if result.status_code != 200: return False rv = [l.strip() for l in result.content.splitlines()] if rv and rv[0] == 'true': return True if len(rv) > 1: error = rv[1] if error in self._error_codes: raise RuntimeError(self._error_codes[error]) return False
def get_rules(): """Returns a list of URL rules for the application. The list can be defined entirely here or in separate ``urls.py`` files. Here we show an example of joining all rules from the ``apps_installed`` listed in config. """ rules = [ tipfy.Rule('/', endpoint='home', handler='home.HomeHandler'), tipfy.Rule('/submit', endpoint='submit', handler='submit.SubmitHandler'), tipfy.Rule('/review', endpoint='review-start', handler='review.ReviewStartHandler'), tipfy.Rule('/review/<int:id>', endpoint='review-quote', handler='review.ReviewQuoteHandler'), tipfy.Rule('/review/remind', endpoint='review-remind', handler='review.ReviewRemindHandler'), tipfy.Rule('/quote/<int:id>', endpoint='quote-view', handler='quote.QuoteViewHandler'), tipfy.Rule('/random', endpoint='random-quote', handler='random_quote.RandomQuoteHandler'), tipfy.Rule('/atom', endpoint='atom-view', handler='atom.AtomViewHandler'), ] for app_module in tipfy.get_config('tipfy', 'apps_installed'): try: # Load the urls module from the app and extend our rules. app_rules = tipfy.import_string('%s.urls' % app_module) rules.extend(app_rules.get_rules()) except ImportError: pass return rules
def __init__(self, area, user, roles_map=None, roles_lock=None): """Loads access privileges and roles for a given user in a given area. :param area: An area identifier, as a string. :param user: An user identifier, as a string. :param roles_map: A dictionary of roles mapping to a list of rule tuples. :param roles_lock: Roles lock string to validate cache. If not set, uses the application version id. """ if roles_map is not None: self.roles_map = roles_map if roles_lock is not None: self.roles_lock = roles_lock elif self.roles_lock is None: # Set roles_lock default. self.roles_lock = get_config("tipfy", "version_id") if area and user: self._roles, self._rules = AclRules.get_roles_and_rules(area, user, self.roles_map, self.roles_lock) else: self.reset()
def _validate_recaptcha(self, challenge, response, remote_addr): """Performs the actual validation.""" private_key = get_config('tipfy.ext.wtforms', 'recaptcha_private_key') result = urlfetch.fetch(url=RECAPTCHA_VERIFY_SERVER, method=urlfetch.POST, headers={'Content-Type': 'application/x-www-form-urlencoded'}, payload=url_encode({ 'privatekey': private_key, 'remoteip': remote_addr, 'challenge': challenge, 'response': response })) if result.status_code != 200: return False rv = [l.strip() for l in result.content.splitlines()] if rv and rv[0] == 'true': return True if len(rv) > 1: error = rv[1] if error in self._error_codes: raise RuntimeError(self._error_codes[error]) return False
def _get_format(key, format): """A small helper for the datetime formatting functions. Returns a format name or pattern to be used by Babel date format functions. This function derives from `Flask-Babel <http://pypi.python.org/pypi/Flask-Babel/>`_ :param key: A format key to be get from config: ``date``, ``datetime`` or ``time``. :param format: The format to be returned. Valid values are "short", "medium", "long", "full" or a custom date/time pattern. :returns: A format name or pattern to be used by Babel date format functions. """ config = get_config(__name__)['date_formats'] if format is None: format = config[key] if format in ('short', 'medium', 'full', 'long'): rv = config['%s.%s' % (key, format)] if rv is not None: format = rv return format
def get_roles_and_rules(cls, area, user, roles_map, roles_lock): """Returns a tuple (roles, rules) for a given user in a given area.""" res = None cache_key = cls.get_key_name(area, user) if cache_key in _rules_map: res = _rules_map[cache_key] else: res = memcache.get(cache_key, namespace=cls.__name__) if res is not None: lock, roles, rules = res if res is None or lock != roles_lock or get_config("tipfy", "dev"): entity = cls.get_by_key_name(cache_key) if entity is None: res = (roles_lock, [], []) else: rules = [] # Apply role rules. for role in entity.roles: rules.extend(roles_map.get(role, [])) # Extend with rules, eventually overriding some role rules. rules.extend(entity.rules) # Reverse everything, as rules are checked from last to first. rules.reverse() # Set results for cache, applying current roles_lock. res = (roles_lock, entity.roles, rules) cls.set_cache(cache_key, res) return (res[1], res[2])
def is_default_locale(): """Returns ``True`` if locale is set to the default locale. :return: ``True`` if locale is set to the default locale, ``False`` otherwise. """ return getattr(local, 'locale', None) == get_config(__name__, 'locale')
def get_threads(board, page=0, fmt_name="page"): _fmt = "thread_" + fmt_name if _fmt in globals(): fmt = globals()[_fmt] else: fmt = thread_plain threads = [] board_db = Board.get_by_key_name(board) if board_db: threads = board_db.linked if not threads: threads = [ (board, th) for th in board_db.thread] per_page = get_config('aib.ib', 'thread_per_page') threads = threads[per_page*page:per_page*(page+1)] logging.info("threadlist in %r : %r" % (board, threads)) # grab data from cache data = Thread.load_list(threads) return [ fmt(th) for th in data if th ]
def bump(boards, thread): board_db = Board.get_by_key_name(boards) main = boards[0] per_page = get_config('aib.ib', 'thread_per_page') pages = get_config('aib.ib', 'board_pages') threads = per_page * pages def hide(linked, board): for _board, thread in list(linked): if board == _board: linked.remove((board, thread)) add = 0 for x,(name,board) in enumerate(zip(boards,board_db)): if not board: board = Board(key_name=name) board.linked = [] board_db[x] = board if not board.linked and board.thread: board.linked = [ (board.code, th) for th in board.thread ] if main[-1] == '~': hide(board.linked, main) add = per_page/3 if (main,thread) in board.linked: board.linked.remove((main,thread)) board.linked.insert(add, (main,thread)) board.linked = board.linked[:threads] main_db = board_db[0] if thread in main_db.thread: main_db.thread.remove(thread) main_db.thread.insert(add, thread) main_db.thread = main_db.thread[:threads] db.put(board_db)
def is_default_locale(): """Returns True if locale is set to the default locale. :returns: True if locale is set to the default locale, False otherwise. """ ctx = Tipfy.request.context return ctx.get('locale', None) == get_config(__name__, 'locale')
def get_lookup(): global _lookup if _lookup is None: _lookup = TemplateLookup(directories=[path.join(get_config(__name__, 'templates_dir'))], output_encoding='utf-8', encoding_errors='replace') return _lookup
def check(ip): stat_interval = get_config('aib.antiwipe', "wipe_stat_interval") statnum = int(time()/stat_interval) statkey = "poststat-%d" % statnum poststat = memcache.get(statkey) or 0 logging.info("wipe stat: %d" % poststat) interval = get_config('aib.antiwipe', "interval") maxquota = get_config('aib.antiwipe', "quota") maxquota_all = get_config('aib.antiwipe', "quota_all") if poststat > maxquota_all: interval *= get_config('aib.antiwipe', "wipe_interval_ratio") maxquota /= get_config('aib.antiwipe', "wipe_quota_ratio") logging.info("looks like wipe, increase interval: %d" % interval) elif poststat > (maxquota_all*10): logging.info("increase limit even more!") interval *= get_config('aib.antiwipe', "wipe_huge_interval_ratio") maxquota = 1 memcache.set(statkey, poststat+1, time=stat_interval) qkey = "ip-%s" % ip quota = memcache.get(qkey) or 0 quota += 1 memcache.set(qkey, quota, time=interval) if quota > maxquota: return False return True
def cookie_args(self): """Returns the configured arguments to set an auth cookie. :return: A dictionary of keyword arguments for a cookie. """ keys = ['domain', 'path', 'secure', 'httponly', 'session_expires', 'max_age'] return dict((k, get_config(__name__, 'cookie_' + k)) for k in keys)
def get(self): return render_response( "boardlist.html", boards = get_config("aib", "boardlist"), allboards = map( boardlink, models.BoardCounter.all().fetch(self.BOARDLIM) ), )
def create(self,op): data = { "op" : op, "id" : self.thread, "board" : self.board, "subject" : op.get("subject"), } self.cache = Cache.create("thread", self.board, self.thread) self.cache.data = render_template("thread.html", thread = data, threads = [data], board = self.board, board_name = NAMES.get(self.board) or get_config("aib", "default_name"), boards = get_config("aib", "boardlist"), # context? )
def option_modsign(request, data): mods = get_config("aib.ib", "mod_name") user = users.get_current_user() if not user or user.email() not in mods: return if data.get('name') == mods.get(user.email()): data['typ'] = 'modpost'
def make_rainbow(*a): """ function makes rainbow codes """ secret = get_config('aib.rainbow', 'secret') a = map(str,a) a.insert(0,secret) key = str.join("-", a) rb_hash = md5(key).hexdigest()[:18] logging.info("rainbow code: %s" % rb_hash) return rb_hash
def get_auth_system(): """Returns the configured authentication system. :return: An instance of :class:`tipfy.ext.auth.BaseAuth`. """ global _auth_system if _auth_system is None: _auth_system = import_string(get_config(__name__, 'auth_system'))() return _auth_system
def pre_dispatch(self, handler): if get_config("tipfy", "dev"): return if handler.request.method == 'POST': return if handler.request.host not in FRM: return return redirect(REDIRECT+handler.request.path)
def _get_csrf_token(self, request): token = str(uuid.uuid4()) token_list = self._get_session(request).setdefault('_csrf_token', []) token_list.append(token) # Store a maximum number of tokens. maximum_tokens = get_config('tipfy.ext.wtforms', 'csrf_tokens') while len(token_list) > maximum_tokens: token_list.pop(0) # Set the validation rule for the tokens. self._fields['csrf_token'].validators = [CsrfToken(token_list)] return token
def get_timezone(timezone=None): """Returns a ``datetime.tzinfo`` object for the given timezone. This is called by [[#format_datetime]] and [[#format_time]] when a tzinfo is not provided. :param timezone: The timezone name from the Olson database, e.g.: ``America/Chicago``. If not set, uses the default configuration value. :returns: A ``datetime.tzinfo`` object. """ return pytz.timezone(timezone or get_config(__name__, 'timezone'))
def get_env(): """Returns the Jinja2 environment, a singleton. :return: A ``jinja2.Environment`` instance. """ global _environment if _environment is None: templates_compiled_target = get_config(__name__, 'templates_compiled_target') use_compiled = not get_config('tipfy', 'dev') or get_config(__name__, 'force_use_compiled') if templates_compiled_target is not None and use_compiled: # Use precompiled templates loaded from a module. loader = ModuleLoader(templates_compiled_target) else: # Parse templates on every request. loader = FileSystemLoader(get_config(__name__, 'templates_dir')) # Initialize the environment. _environment = Environment(loader=loader, extensions=['jinja2.ext.i18n']) # Add url_for() by default. _environment.globals['url_for'] =url_for try: from tipfy.ext import i18n # Install i18n, first forcing it to be loaded if not yet. i18n.get_translations() _environment.install_gettext_translations(i18n.translations) _environment.globals.update({ 'format_date': i18n.format_date, 'format_time': i18n.format_time, 'format_datetime': i18n.format_datetime, }) except (ImportError, AttributeError), e: pass
def set_translations(locale): """Sets the locale and translations object for the current request. Most functions in this module depends on the translations object being set to work properly. :param locale: The locale code. For example, ``en_US`` or ``pt_BR``. :returns: None. """ if locale not in _translations: locales = [locale, get_config(__name__, 'locale')] _translations[locale] = support.Translations.load( 'locale', locales, 'messages') ctx = Tipfy.request.context ctx['locale'] = locale ctx['translations'] = _translations[locale]
def _renew_session(self, force=False): """Renews the session id if its expiration time has passed. :param force: True to force the session id to be renewed, False to check if the expiration time has passed. :returns: None. """ if force is False: # Only renew the session id if it is too old. expires = datetime.timedelta(seconds=get_config('tipfy.ext.auth', 'session_max_age')) force = (self.session_updated + expires < datetime.datetime.now()) if force is True: self.session_id = gen_salt(length=32) self.session_updated = datetime.datetime.now() self.put()
def post_dispatch(self, handler, response): """Saves current locale in a cookie. :param handler: The current ``tipfy.RequestHandler`` instance. :param response: The current ``tipfy.Response`` instance. :returns: None. """ ctx = Tipfy.request.context locale = ctx.get('locale', None) if locale is None: # Locale isn't set. return response # Persist locale using a cookie when it differs from default. response.set_cookie(get_config(__name__, 'cookie_name'), value=locale, max_age=(86400 * 30)) return response
def compile_templates(argv=None): """Compiles templates for better performance. This is a command line script. From the buildout directory, run: bin/jinja2_compile It will compile templates from the directory configured for 'templates_dir' to the one configured for 'templates_compiled_target'. At this time it doesn't accept any arguments. """ if argv is None: argv = sys.argv cwd = os.getcwd() app_path = os.path.join(cwd, 'app') gae_path = os.path.join(cwd, 'etc/parts/google_appengine') extra_paths = [ app_path, gae_path, # These paths are required by the SDK. os.path.join(gae_path, 'lib', 'antlr3'), os.path.join(gae_path, 'lib', 'django'), os.path.join(gae_path, 'lib', 'ipaddr'), os.path.join(gae_path, 'lib', 'webob'), os.path.join(gae_path, 'lib', 'yaml', 'lib'), ] sys.path = extra_paths + sys.path from config import config app = make_wsgi_app(config) template_path = get_config('tipfy.ext.jinja2', 'templates_dir') compiled_path = get_config('tipfy.ext.jinja2', 'templates_compiled_target') if compiled_path is None: raise ValueError('Missing configuration key to compile templates.') if isinstance(template_path, basestring): # A single path. source = os.path.join(app_path, template_path) else: # A list of paths. source = [os.path.join(app_path, p) for p in template_path] target = os.path.join(app_path, compiled_path) # Set templates dir and deactivate compiled dir to use normal loader to # find the templates to be compiled. app.config['tipfy.ext.jinja2']['templates_dir'] = source app.config['tipfy.ext.jinja2']['templates_compiled_target'] = None if target.endswith('.zip'): zip_cfg = 'deflated' else: zip_cfg = None old_list_templates = FileSystemLoader.list_templates FileSystemLoader.list_templates = list_templates env = get_env() env.compile_templates(target, extensions=None, filter_func=filter_templates, zip=zip_cfg, log_function=logger, ignore_errors=False, py_compile=False) FileSystemLoader.list_templates = old_list_templates
def __init__(self, backends=None, default_backend=None): self.backends = backends or self.default_backends self.default_backend = default_backend or get_config( __name__, 'default_backend')
def pre_dispatch(self, handler): handler.request.registry['session_store'] = SessionStore( handler.request, get_config(__name__), self.backends, self.default_backend)
def pre_dispatch_handler(self): request = Tipfy.request request.registry['session_store'] = SessionStore( request, get_config(__name__), self.backends, self.default_backend)