def webtool_callback(func = None, require_login = True, do_lookup_user = False): """ lib.webtool - standard interface wrapper When calling this function without keyword arguments, you will want to keep the first argument None since this is a hack to make the function multisyntax compatible, see note at end of function code. require_login: When enabled, page will reject users without authorisation. Opposingly disabling will render the page without problems. lookup_user: When enabled, decorator will lookup the current user, and provide it as an additional argument. provides the following variables: evn['verified_user'] = Result of lookup_user operation. """ # All hail closures ################################ ### Optional arguments hack ### ################################ def owhy(func): deep_func = detach_deep_func(func) # Validate env argument if inspect.getargspec(deep_func)[0][0] != 'env': raise AppSemanticException('webtool_callback', deep_func, [(0, 'env')]) ################################ ### Actual wrapping function ### ################################ def webtool_func(env, *args, **key_args): """ webtool internal function wrapper """ # Force a login if necessary if require_login: if not loggedin_and_require(env): return handle_login(env) # Lookup user try: user_name = env['beaker.session']['user_name'] user = lookup_user(user_name) except KeyError, e: user = None env['verified_user'] = user # Pass argument if requested if do_lookup_user: key_args['user'] = user return func(env, *args, **key_args) return attach_deep_func(webtool_func, deep_func)
def require_rtorrent(func): """ Wrap a function requiring an RTorrent object. """ deep_func = detach_deep_func(func) # Validate torrent argument if 'rtorrent' not in inspect.getargspec(deep_func)[0]: raise AppStandardsViolation('require_rtorrent', deep_func, [(-1, 'rtorrent')]) ################################ ### Actual wrapping function ### ################################ def rtorrent_func(env, *args, **key_args): """ webtool internal torrent argument wrapper """ # Setup torrent object. r = RTorrent(key_args['target']) key_args['rtorrent'] = r return func(env, *args, **key_args) return attach_deep_func(rtorrent_func, deep_func)
def require_torrent(func): """ Wrap a function working on a specific torrent. This decorator expects webtool to pass a 'torrent_hash' argument. provides: env['torrent'] """ deep_func = detach_deep_func(func) # Validate torrent argument if 'torrent' not in inspect.getargspec(deep_func)[0]: raise AppStandardsViolation('require_torrent', deep_func, [(-1, 'torrent')]) ################################ ### Actual wrapping function ### ################################ def torrent_func(env, target, *args, **key_args): """ webtool internal torrent argument wrapper """ # Grab torrent_hash if not key_args.has_key('torrent_hash'): bugstr = "!!! BUG: Webtool is not passing a 'torrent_hash' " + \ "argument like it should" print bugstr raise AppBugException(bugstr) # Build torrent object torrent_hash = key_args['torrent_hash'] t = Torrent(target, torrent_hash) # torrent_hash is contained by torrent object and thus superfluous del key_args['torrent_hash'] key_args['torrent'] = t return func(env, target = target, *args, **key_args) return attach_deep_func(torrent_func, deep_func)
def require_target(func): """ Wrap a function requiring a target client. Implements automatic rejection semantics to ensure user authorisation. """ deep_func = detach_deep_func(func) # Validate target argument if inspect.getargspec(deep_func)[0][1] != 'target': raise AppStandardsViolation('require_target', deep_func, [(1, 'env')]) ################################ ### Actual wrapping function ### ################################ def target_func(env, target, *args, **key_args): """ webtool internal target argument wrapper. """ # Perform target lookup for callback function target = lookup_target(target) # Return 404 on target not found if target is None: return None # 404 user = env['verified_user'] # Reject user if not allowed to view this target if USE_AUTH: if user == None or target['name'] not in user.targets: return None # 404 return func(env, target = target, *args, **key_args) return attach_deep_func(target_func, deep_func)