def __init__(self, template='', content_type=None, exclude_names=None, custom_format=None, render_params=None, inherit=False): if exclude_names is None: exclude_names = [] if template in config.get('renderers', []): engine, template = template, '' elif ':' in template: engine, template = template.split(':', 1) elif template: # Use the default templating engine from the config engine = config.get('default_renderer') else: engine, template = None, None if content_type is None: if engine == 'json': content_type = 'application/json' else: content_type = 'text/html' if engine in ('json', 'amf') and 'tmpl_context' not in exclude_names: exclude_names.append('tmpl_context') self.engine = engine self.template = template self.content_type = content_type self.exclude_names = exclude_names self.custom_format = custom_format self.render_params = render_params self.inherit = inherit
def setup_i18n(): """Set languages from the request header and the session. The session language(s) take priority over the request languages. Automatically called by tg controllers to setup i18n. Should only be manually called if you override controllers function. """ session_ = pylons.session._current_obj() if session_: session_existed = session_.accessed() # If session is available, we try to see if there are languages set languages = session_.get(config.get('lang_session_key', 'tg_lang')) if not session_existed and config.get('beaker.session.tg_avoid_touch'): session_.__dict__['_sess'] = None if languages: if isinstance(languages, basestring): languages = [languages] else: languages = [] else: languages = [] languages.extend(map(sanitize_language_code, pylons.request.accept_language.best_matches())) set_temporary_lang(languages)
def _call(self, controller, params, remainder=None): """ _call is called by _perform_call in Pylons' WSGIController. Any of the before_validate hook, the validation, the before_call hook, and the controller method can return a FormEncode Invalid exception, which will give the validation error handler the opportunity to provide a replacement decorated controller method and output that will subsequently be rendered. This allows for validation to display the original page or an abbreviated form with validation errors shown on validation failure. The before_render hook provides a place for functions that are called before the template is rendered. For example, you could use it to add and remove from the dictionary returned by the controller method, before it is passed to rendering. The after_render hook can act upon and modify the response out of rendering. """ self._initialize_validation_context() pylons.request.start_response = getattr(self, 'start_response', None) remainder = remainder or [] remainder = [url2pathname(r) for r in remainder] try: if 'tg_format' in params: pylons.request.headers['tg_format'] = params['tg_format'] controller.decoration.run_hooks('before_validate', remainder, params) validate_params = self._get_params_with_argspec( controller, params, remainder) for ignore in config.get('ignore_parameters', []): if params.get(ignore): del params[ignore] # Validate user input params = self._perform_validate(controller, validate_params) pylons.tmpl_context.form_values = params controller.decoration.run_hooks('before_call', remainder, params) # call controller method params, remainder = self._remove_argspec_params_from_params( controller, params, remainder) output = controller(*remainder, **dict(params)) except formencode.api.Invalid, inv: controller, output = self._handle_validation_errors( controller, remainder, params, inv)
def _call(self, controller, params, remainder=None): """ _call is called by _perform_call in Pylons' WSGIController. Any of the before_validate hook, the validation, the before_call hook, and the controller method can return a FormEncode Invalid exception, which will give the validation error handler the opportunity to provide a replacement decorated controller method and output that will subsequently be rendered. This allows for validation to display the original page or an abbreviated form with validation errors shown on validation failure. The before_render hook provides a place for functions that are called before the template is rendered. For example, you could use it to add and remove from the dictionary returned by the controller method, before it is passed to rendering. The after_render hook can act upon and modify the response out of rendering. """ self._initialize_validation_context() pylons.request.start_response = getattr(self, 'start_response', None) remainder = remainder or [] remainder = [url2pathname(r) for r in remainder] try: if 'tg_format' in params: pylons.request.headers['tg_format'] = params['tg_format'] controller.decoration.run_hooks('before_validate', remainder, params) validate_params = self._get_params_with_argspec(controller, params, remainder) for ignore in config.get('ignore_parameters', []): if params.get(ignore): del params[ignore] # Validate user input params = self._perform_validate(controller, validate_params) pylons.tmpl_context.form_values = params controller.decoration.run_hooks('before_call', remainder, params) # call controller method params, remainder = self._remove_argspec_params_from_params(controller, params, remainder) output = controller(*remainder, **dict(params)) except formencode.api.Invalid, inv: controller, output = self._handle_validation_errors(controller, remainder, params, inv)
def render_mako(template_name, template_vars, **kwargs): if asbool(config.get('use_dotted_templatenames', 'true')): template_name = tg.config['pylons.app_globals'].\ dotted_filename_finder.get_dotted_filename(template_name, template_extension='.mak') return templating.render_mako(template_name, extra_vars=template_vars, **kwargs)
def register_template_engine(self, content_type, engine, template, exclude_names, render_params): """Registers an engine on the controller. Multiple engines can be registered, but only one engine per content_type. If no content type is specified the engine is registered at */* which is the default, and will be used whenever no content type is specified. exclude_names keeps track of a list of keys which will be removed from the controller's dictionary before it is loaded into the template. This allows you to exclude some information from JSONification, and other 'automatic' engines which don't require a template. render_params registers extra parameters which will be sent to the rendering method. This allows you to influence things like the rendering method or the injected doctype. """ default_renderer = config.get('default_renderer') available_renderers = config.get('renderers', []) if engine and engine not in available_renderers: log.debug( 'Registering template %s for engine %s not available. Skipping it', template, engine) return content_type = content_type or '*/*' if content_type in self.engines and engine != default_renderer: #Avoid overwriting the default renderer when there is already a template registered return self.engines[content_type] = (engine, template, exclude_names, render_params or {}) # this is a work-around to make text/html prominent in respect # to other common choices when they have the same weight for # paste.util.mimeparse.best_match. self.engines_keys = sorted(self.engines, reverse=True)
def set_lang(languages, **kwargs): """Set the current language(s) used for translations in current call and session. languages should be a string or a list of strings. First lang will be used as main lang, others as fallbacks. """ set_temporary_lang(languages) if pylons.session: session[config.get("lang_session_key", "tg_lang")] = languages session.save()
def __init__(self, template='', content_type=None, exclude_names=None, custom_format=None): if exclude_names is None: exclude_names = [] if template in config.get('renderers', []): engine, template = template, '' elif ':' in template: engine, template = template.split(':', 1) elif template: # Use the default templating engine from the config if config.get('use_legacy_renderer'): engine = config['buffet.template_engines'][0]['engine'] else: engine = config.get('default_renderer') else: engine, template = None, None if content_type is None: if engine == 'json': content_type = 'application/json' else: content_type = 'text/html' if (engine == 'json' or engine == 'amf') and 'tmpl_context' not in exclude_names: exclude_names.append('tmpl_context') self.engine = engine self.template = template self.content_type = content_type self.exclude_names = exclude_names self.custom_format = custom_format
def __call__(self, template_name, template_vars, **kwargs): """Render the template_vars with the Chameleon-Genshi template.""" # Gets template format from content type or from config options format = kwargs.get('format') if not format: format = self.format_for_content_type.get(response.content_type) if not format: format = config.get('templating.chameleon.genshi.format') if not format: format = config.get('templating.genshi.method') if not format or format not in ('xml', 'text'): format = 'xml' def render_template(): template_vars.update(my_pylons_globals()) template = self.load_template(template_name, format=format) return literal(template.render(**template_vars)) return templating.cached_template( template_name, render_template, ns_options=('doctype', 'method'), **kwargs)
def render_genshi(template_name, template_vars, **kwargs): """Render the template_vars with the Genshi template""" global HTML, XML if not HTML or not XML: from genshi import HTML, XML template_vars.update(HTML=HTML, XML=XML) if config.get('use_dotted_templatenames', False): template_name = tg.config['pylons.app_globals' ].dotted_filename_finder.get_dotted_filename( template_name, template_extension='.html') if 'method' not in kwargs: kwargs['method'] = {'text/xml': 'xml', 'text/plain': 'text'}.get( response.content_type, config.get('templating.genshi.method')) # (in a similar way, we could pass other serialization options when they # will be supported - see http://pylonshq.com/project/pylonshq/ticket/613) return templating.render_genshi(template_name, extra_vars=template_vars, **kwargs)
def set_lang(languages, **kwargs): """Set the current language(s) used for translations in current call and session. languages should be a string or a list of strings. First lang will be used as main lang, others as fallbacks. """ set_temporary_lang(languages) if pylons.session: session[config.get('lang_session_key', 'tg_lang')] = languages session.save()
def register_template_engine(self, content_type, engine, template, exclude_names, render_params): """Registers an engine on the controller. Multiple engines can be registered, but only one engine per content_type. If no content type is specified the engine is registered at */* which is the default, and will be used whenever no content type is specified. exclude_names keeps track of a list of keys which will be removed from the controller's dictionary before it is loaded into the template. This allows you to exclude some information from JSONification, and other 'automatic' engines which don't require a template. render_params registers extra parameters which will be sent to the rendering method. This allows you to influence things like the rendering method or the injected doctype. """ default_renderer = config.get('default_renderer') available_renderers = config.get('renderers', []) if engine and engine not in available_renderers: log.debug('Registering template %s for engine %s not available. Skipping it', template, engine) return content_type = content_type or '*/*' if content_type in self.engines and engine != default_renderer: #Avoid overwriting the default renderer when there is already a template registered return self.engines[content_type] = (engine, template, exclude_names, render_params or {}) # this is a work-around to make text/html prominent in respect # to other common choices when they have the same weight for # paste.util.mimeparse.best_match. self.engines_keys = sorted(self.engines, reverse=True)
def postpone_commits(func, *args, **kwargs): """Turns SQLAlchemy commits into flushes in the decorated method. This has the end-result of postponing the commit to the normal TG2 transaction boundary. """ #TODO: Test and document this. s = config.get('DBSession', None) assert hasattr(s, 'commit') old_commit = s.commit s.commit = s.flush retval = func(*args, **kwargs) s.commit = old_commit return retval
def __call__(self, template_name, template_vars, **kwargs): """Render the template_vars with the Genshi template.""" template_vars.update(self.genshi_functions) # Gets document type from content type or from config options doctype = kwargs.get('doctype') if not doctype: doctype = config.get('templating.genshi.doctype') if not doctype: method = kwargs.get('method') or config.get( 'templating.genshi.method') or 'xhtml' doctype = self.doctypes_for_methods.get(method) doctypes = self.doctypes_for_content_type.get(response.content_type) if doctypes and (not doctype or doctype not in doctypes): doctype = doctypes[0] kwargs['doctype'] = doctype # Gets rendering method from content type or from config options method = kwargs.get('method') if not method: method = config.get('templating.genshi.method') if not method: method = self.method_for_doctype(doctype) methods = self.methods_for_content_type.get(response.content_type) if methods and (not method or method not in methods): method = methods[0] kwargs['method'] = method def render_template(): template_vars.update(my_pylons_globals()) template = self.load_template(template_name) return literal(template.generate(**template_vars).render( doctype=doctype, method=method, encoding=None)) return templating.cached_template( template_name, render_template, ns_options=('doctype', 'method'), **kwargs)
def render_genshi(template_name, template_vars, **kwargs): """Render the template_vars with the Genshi template""" global HTML, XML if not HTML or not XML: from genshi import HTML, XML template_vars.update(HTML=HTML, XML=XML) if config.get('use_dotted_templatenames', False): template_name = tg.config[ 'pylons.app_globals'].dotted_filename_finder.get_dotted_filename( template_name, template_extension='.html') if 'method' not in kwargs: kwargs['method'] = { 'text/xml': 'xml', 'text/plain': 'text' }.get(response.content_type, config.get('templating.genshi.method')) # (in a similar way, we could pass other serialization options when they # will be supported - see http://pylonshq.com/project/pylonshq/ticket/613) return templating.render_genshi(template_name, extra_vars=template_vars, **kwargs)
def get_package_name(): """Try to find out the package name of the current directory.""" package = config.get("modules") if package: return package if "--egg" in sys.argv: projectname = sys.argv[sys.argv.index("--egg") + 1] egg = pkg_resources.get_distribution(projectname) top_level = egg._get_metadata("top_level.txt") else: fname = get_project_meta('top_level.txt') top_level = fname and open(fname) or [] for package in top_level: package = package.rstrip() if package and package != 'locales': return package
def get_package_name(): """Try to find out the package name of the current directory.""" package = config.get("modules") if package: return package if "--egg" in sys.argv: projectname = sys.argv[sys.argv.index("--egg")+1] egg = pkg_resources.get_distribution(projectname) top_level = egg._get_metadata("top_level.txt") else: fname = get_project_meta('top_level.txt') top_level = fname and open(fname) or [] for package in top_level: package = package.rstrip() if package and package != 'locales': return package
def setup_i18n(): """Set languages from the request header and the session. The session language(s) take priority over the request languages. Automatically called by tg controllers to setup i18n. Should only be manually called if you override controllers function. """ if pylons.session: # If session is available, we try to see if there are languages set languages = pylons.session.get(config.get("lang_session_key", "tg_lang")) if languages: if isinstance(languages, basestring): languages = [languages] else: languages = [] else: languages = [] languages.extend(pylons.request.accept_language.best_matches()) set_temporary_lang(languages)
def setup_i18n(): """Set languages from the request header and the session. The session language(s) take priority over the request languages. Automatically called by tg controllers to setup i18n. Should only be manually called if you override controllers function. """ if pylons.session: # If session is available, we try to see if there are languages set languages = pylons.session.get( config.get('lang_session_key', 'tg_lang')) if languages: if isinstance(languages, basestring): languages = [languages] else: languages = [] else: languages = [] languages.extend(map(sanitize_language_code, pylons.request.accept_language.best_matches())) set_temporary_lang(languages)
def make_base_app(global_conf, wrap_app=None, full_stack=True, **app_conf): """Create a tg WSGI application and return it. ``wrap_app`` a WSGI middleware component which takes the core turbogears application and wraps it -- inside all the WSGI-components provided by TG and Pylons. This allows you to work with the full environment that your TG application would get before anything happens in the application itself. ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether or not this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) app = TGApp() if wrap_app: app = wrap_app(app) app = self.add_core_middleware(app) if self.use_toscawidgets: app = self.add_tosca_middleware(app) if self.use_toscawidgets2: app = self.add_tosca2_middleware(app) if self.auth_backend: # Skipping authentication if explicitly requested. Used by # repoze.who-testutil: skip_authentication = app_conf.get('skip_authentication', False) app = self.add_auth_middleware(app, skip_authentication) if self.use_transaction_manager: app = self.add_tm_middleware(app) if self.use_sqlalchemy: if not hasattr(self, 'DBSession'): # If the user hasn't specified a scoped_session, assume # he/she uses the default DBSession in model self.DBSession = self.model.DBSession app = self.add_dbsession_remover_middleware(app) if pylons_config.get('make_body_seekable'): app = maybe_make_body_seekable(app) if asbool(full_stack): if (self.auth_backend is None and 401 not in self.handle_status_codes): # If there's no auth backend configured which traps 401 # responses we redirect those responses to a nicely # formatted error page self.handle_status_codes.append(401) # This should never be true for internal nested apps app = self.add_error_middleware(global_conf, app) # Establish the registry for this application app = RegistryManager(app) # Static files (if running in production, and Apache or another # web server is serving static files) #if the user has set the value in app_config, don't pull it from the ini if not hasattr(self, 'serve_static'): self.serve_static = asbool(config.get('serve_static', 'true')) if self.serve_static: app = self.add_static_file_middleware(app) return app
def do_request(self, anOtpVal, transactionid=None, user=None): ''' Here we contact the Radius Server to verify the pass ''' reply = {} res = False otp_count = -1 radiusServer = self.getFromTokenInfo("radius.server") radiusUser = self.getFromTokenInfo("radius.user") # Read the secret!!! secObj = self._get_secret_object() radiusSecret = binascii.unhexlify(secObj.getKey()) if radiusSecret == VOID_RADIUS_SECRET: log.warning("Usage of default radius secret is not recomended!!") # here we also need to check for radius.user log.debug("[do_request] checking OTP len:%s on radius server: %s," " user: %s" % (len(anOtpVal), radiusServer, radiusUser)) try: # pyrad does not allow to set timeout and retries. # it defaults to retries=3, timeout=5 # TODO: At the moment we support only one radius server. # No round robin. server = radiusServer.split(':') r_server = server[0] r_authport = 1812 nas_identifier = env.get("radius.nas_identifier", "LinOTP") r_dict = env.get("radius.dictfile", "/etc/linotp2/dictionary") if len(server) >= 2: r_authport = int(server[1]) log.debug("[do_request] [RadiusToken] NAS Identifier: %r, " "Dictionary: %r" % (nas_identifier, r_dict)) log.debug("[do_request] [RadiusToken] constructing client object " "with server: %r, port: %r, secret: %r" % (r_server, r_authport, radiusSecret)) srv = Client(server=r_server, authport=r_authport, secret=radiusSecret, dict=Dictionary(r_dict)) req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest, User_Name=radiusUser.encode('ascii'), NAS_Identifier=nas_identifier.encode('ascii')) req["User-Password"] = req.PwCrypt(anOtpVal) if transactionid is not None: req["State"] = str(transactionid) response = srv.SendPacket(req) if response.code == pyrad.packet.AccessChallenge: opt = {} for attr in response.keys(): opt[attr] = response[attr] res = False log.debug("challenge returned %r " % opt) # now we map this to a linotp challenge if "State" in opt: reply["transactionid"] = opt["State"][0] if "Reply-Message" in opt: reply["message"] = opt["Reply-Message"][0] # preserve challenge reply for later self.isRemoteChallengeRequest = True self.remote_challenge_response = reply elif response.code == pyrad.packet.AccessAccept: log.info("[do_request] [RadiusToken] Radiusserver %s granted " "access to user %s." % (r_server, radiusUser)) otp_count = 0 res = True else: log.warning("[do_request] [RadiusToken] Radiusserver %s" "rejected access to user %s." % (r_server, radiusUser)) res = False except Exception as ex: log.exception( "[do_request] [RadiusToken] Error contacting radius Server: %r" % (ex)) return (res, otp_count, reply)
def wrap_controller(self, controller): controller_callable = controller for wrapper in config.get('controller_wrappers', []): controller_callable = wrapper(self, controller_callable) return controller_callable
def _render_response(self, controller, response): """ Render response takes the dictionary returned by the controller calls the appropriate template engine. It uses information off of the decoration object to decide which engine and template to use, and removes anything in the exclude_names list from the returned dictionary. The exclude_names functionality allows you to pass variables to some template rendering engines, but not others. This behavior is particularly useful for rendering engines like JSON or other "web service" style engines which don't use and explicit template, or use a totally generic template. All of these values are populated into the context object by the expose decorator. """ req = pylons.request._current_obj() resp = pylons.response._current_obj() (content_type, engine_name, template_name, exclude_names, render_params ) = controller.decoration.lookup_template_engine(req) result = dict(response=response, content_type=content_type, engine_name=engine_name, template_name=template_name) if content_type is not None: resp.headers['Content-Type'] = content_type # if it's a string return that string and skip all the stuff if not isinstance(response, dict): if engine_name == 'json' and isinstance(response, list): raise JsonEncodeError( 'You may not expose with JSON a list return value because' ' it leaves your application open to CSRF attacks.') return result # Save these objects as locals from the SOP to avoid expensive lookups tmpl_context = pylons.tmpl_context._current_obj() use_legacy_renderer = pylons.configuration.config.get( 'use_legacy_renderer', True) # what causes this condition? there are no tests for it. # this is caused when someone specifies a content_type, but no template # because their controller returns a string. if template_name is None: return result # Prepare the engine, if it's not already been prepared. # To be removed? Buffet is not included in Pylons 1.0 any more! if use_legacy_renderer == engine_name: # get the buffet handler buffet = pylons.buffet._current_obj() if engine_name not in _configured_engines(): template_options = config.get('buffet.template_options', {}) buffet.prepare(engine_name, **template_options) _configured_engines().add(engine_name) # If there is an identity, push it to the Pylons template context tmpl_context.identity = req.environ.get('repoze.who.identity') # Set up the ToscaWidgets renderer if engine_name in ('genshi','mako') and config['use_toscawidgets']: global tw if not tw: try: import tw except ImportError: pass if tw: tw.framework.default_view = engine_name # Setup the template namespace, removing anything that the user # has marked to be excluded. namespace = dict(tmpl_context=tmpl_context) if isinstance(response, dict): namespace.update(response) for name in exclude_names: namespace.pop(name) # If we are in a test request put the namespace where it can be # accessed directly if req.environ.get('paste.testing'): testing_variables = req.environ['paste.testing_variables'] testing_variables['namespace'] = namespace testing_variables['template_name'] = template_name testing_variables['exclude_names'] = exclude_names testing_variables['render_params'] = render_params testing_variables['controller_output'] = response # Render the result. if use_legacy_renderer == engine_name: rendered = buffet.render(engine_name=engine_name, template_name=template_name, include_pylons_variables=False, namespace=namespace, **render_params) else: rendered = tg_render(template_vars=namespace, template_engine=engine_name, template_name=template_name, **render_params) if isinstance(result, unicode) and not pylons.response.charset: resp.charset = 'UTF-8' result['response'] = rendered return result
def make_base_app(global_conf, wrap_app=None, full_stack=True, **app_conf): """Create a tg WSGI application and return it. ``wrap_app`` a WSGI middleware component which takes the core turbogears application and wraps it -- inside all the WSGI-components provided by TG and Pylons. This allows you to work with the full environment that your TG application would get before anything happens in the application itself. ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether or not this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) app = TGApp() if wrap_app: app = wrap_app(app) for hook in self.hooks['before_config']: app = hook(app) avoid_sess_touch = config.get('beaker.session.tg_avoid_touch', 'false') config['beaker.session.tg_avoid_touch'] = asbool(avoid_sess_touch) app = self.add_core_middleware(app) if self.use_toscawidgets: app = self.add_tosca_middleware(app) if self.use_toscawidgets2: app = self.add_tosca2_middleware(app) if self.auth_backend: # Skipping authentication if explicitly requested. Used by # repoze.who-testutil: skip_authentication = app_conf.get('skip_authentication', False) app = self.add_auth_middleware(app, skip_authentication) if self.use_transaction_manager: app = self.add_tm_middleware(app) if self.use_sqlalchemy: if not hasattr(self, 'DBSession'): # If the user hasn't specified a scoped_session, assume # he/she uses the default DBSession in model self.DBSession = self.model.DBSession app = self.add_dbsession_remover_middleware(app) if self.use_ming: app = self.add_ming_middleware(app) if pylons_config.get('make_body_seekable'): app = maybe_make_body_seekable(app) if 'PYTHONOPTIMIZE' in os.environ: warnings.warn("Forcing full_stack=False due to PYTHONOPTIMIZE enabled. "+\ "Error Middleware will be disabled", RuntimeWarning, stacklevel=2) full_stack = False if asbool(full_stack): if (self.auth_backend is None and 401 not in self.handle_status_codes): # If there's no auth backend configured which traps 401 # responses we redirect those responses to a nicely # formatted error page self.handle_status_codes.append(401) # This should never be true for internal nested apps app = self.add_error_middleware(global_conf, app) # Establish the registry for this application app = RegistryManager(app) # Static files (if running in production, and Apache or another # web server is serving static files) #if the user has set the value in app_config, don't pull it from the ini if not hasattr(self, 'serve_static'): self.serve_static = asbool(config.get('serve_static', 'true')) if self.serve_static: app = self.add_static_file_middleware(app) for hook in self.hooks['after_config']: app = hook(app) return app
def _call(self, controller, params, remainder=None): """Run the controller with the given parameters. _call is called by _perform_call in Pylons' WSGIController. Any of the before_validate hook, the validation, the before_call hook, and the controller method can return a FormEncode Invalid exception, which will give the validation error handler the opportunity to provide a replacement decorated controller method and output that will subsequently be rendered. This allows for validation to display the original page or an abbreviated form with validation errors shown on validation failure. The before_render hook provides a place for functions that are called before the template is rendered. For example, you could use it to add and remove from the dictionary returned by the controller method, before it is passed to rendering. The after_render hook can act upon and modify the response out of rendering. """ self._initialize_validation_context() #This is necessary to prevent spurious Content Type header which would #cause problems to paste.response.replace_header calls and cause #responses wihout content type to get out with a wrong content type if not pylons.response.headers.get('Content-Type'): pylons.response.headers.pop('Content-Type', None) pylons.request.start_response = getattr(self, 'start_response', None) remainder = map(url2pathname, remainder or []) tg_decoration = controller.decoration try: if 'tg_format' in params: pylons.request.headers['tg_format'] = params['tg_format'] tg_decoration.run_hooks('before_validate', remainder, params) validate_params = get_params_with_argspec(controller, params, remainder) for ignore in config.get('ignore_parameters', []): if params.get(ignore): del params[ignore] # Validate user input params = self._perform_validate(controller, validate_params) pylons.tmpl_context.form_values = params tg_decoration.run_hooks('before_call', remainder, params) params, remainder = remove_argspec_params_from_params( controller, params, remainder) #apply controller wrappers controller_callable = tg_decoration.wrap_controller(controller) # call controller method output = controller_callable(*remainder, **dict(params)) except validation_errors, inv: controller, output = self._handle_validation_errors( controller, remainder, params, inv)
def run_hooks(self, hook, *l, **kw): for func in config.get('hooks', {}).get(hook, []): func(*l, **kw) for func in self.hooks[hook]: func(*l, **kw)
try: h = config.package.lib.helpers except AttributeError, ImportError: h = Bunch() root_vars = Bunch(c=tmpl_context, tmpl_context=tmpl_context, response=response, request=request, url=tg.url, helpers=h, h=h, tg=tg_vars) #Allow users to provide a callable that defines extra vars to be #added to the template namespace variable_provider = config.get('variable_provider', None) if variable_provider: root_vars.update(variable_provider()) return root_vars def render(template_vars, template_engine=None, template_name=None, **kwargs): render_function = None if template_engine is not None: # the engine was defined in the @expose() render_function = config['render_functions'].get(template_engine) if render_function is None: # engine was forced in @expose() but is not present in the # engine list, warn developer
def do_request(self, anOtpVal, transactionid=None, user=None): ''' Here we contact the Radius Server to verify the pass ''' reply = {} res = False otp_count = -1 radiusServer = self.getFromTokenInfo("radius.server") radiusUser = self.getFromTokenInfo("radius.user") # Read the secret!!! secObj = self._get_secret_object() radiusSecret = binascii.unhexlify(secObj.getKey()) if radiusSecret == VOID_RADIUS_SECRET: log.warning("Usage of default radius secret is not recomended!!") # here we also need to check for radius.user log.debug("[do_request] checking OTP len:%s on radius server: %s," " user: %s" % (len(anOtpVal), radiusServer, radiusUser)) try: # pyrad does not allow to set timeout and retries. # it defaults to retries=3, timeout=5 # TODO: At the moment we support only one radius server. # No round robin. server = radiusServer.split(':') r_server = server[0] r_authport = 1812 nas_identifier = env.get("radius.nas_identifier", "LinOTP") r_dict = env.get("radius.dictfile", "/etc/linotp2/dictionary") if len(server) >= 2: r_authport = int(server[1]) log.debug("[do_request] [RadiusToken] NAS Identifier: %r, " "Dictionary: %r" % (nas_identifier, r_dict)) log.debug("[do_request] [RadiusToken] constructing client object " "with server: %r, port: %r, secret: %r" % (r_server, r_authport, radiusSecret)) srv = Client(server=r_server, authport=r_authport, secret=radiusSecret, dict=Dictionary(r_dict)) req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest, User_Name=radiusUser.encode('ascii'), NAS_Identifier=nas_identifier.encode('ascii')) req["User-Password"] = req.PwCrypt(anOtpVal) if transactionid is not None: req["State"] = str(transactionid) response = srv.SendPacket(req) if response.code == pyrad.packet.AccessChallenge: opt = {} for attr in response.keys(): opt[attr] = response[attr] res = False log.debug("challenge returned %r " % opt) # now we map this to a linotp challenge if "State" in opt: reply["transactionid"] = opt["State"][0] if "Reply-Message" in opt: reply["message"] = opt["Reply-Message"][0] # preserve challenge reply for later self.isRemoteChallengeRequest = True self.remote_challenge_response = reply elif response.code == pyrad.packet.AccessAccept: log.info("[do_request] [RadiusToken] Radiusserver %s granted " "access to user %s." % (r_server, radiusUser)) otp_count = 0 res = True else: log.warning("[do_request] [RadiusToken] Radiusserver %s" "rejected access to user %s." % (r_server, radiusUser)) res = False except Exception as ex: log.exception("[do_request] [RadiusToken] Error contacting radius" " Server: %r", ex) return (res, otp_count, reply)
except AttributeError, ImportError: h = Bunch() root_vars = Bunch( c = tmpl_context, tmpl_context = tmpl_context, response = response, request = request, url = tg.url, helpers = h, h = h, tg = tg_vars ) #Allow users to provide a callable that defines extra vars to be #added to the template namespace variable_provider = config.get('variable_provider', None) if variable_provider: root_vars.update(variable_provider()) return root_vars def render(template_vars, template_engine=None, template_name=None, **kwargs): render_function = None if template_engine is not None: # the engine was defined in the @expose() render_function = config['render_functions'].get(template_engine) if render_function is None: # engine was forced in @expose() but is not present in the # engine list, warn developer
class DecoratedController(object): """Creates an interface to hang decoration attributes on controller methods for the purpose of rendering web content. """ def __init__(self, *args, **kwargs): if hasattr(self, 'allow_only') and self.allow_only is not None: # Let's turn Controller.allow_only into something useful for # the @allow_only decorator. predicate = self.allow_only #self = allow_only(predicate)(self) super(DecoratedController, self).__init__(*args, **kwargs) def _is_exposed(self, controller, name): if hasattr(controller, name): method = getattr(controller, name) if inspect.ismethod(method) and hasattr(method, 'decoration'): return method.decoration.exposed def _call(self, controller, params, remainder=None): """ _call is called by _perform_call in Pylons' WSGIController. Any of the before_validate hook, the validation, the before_call hook, and the controller method can return a FormEncode Invalid exception, which will give the validation error handler the opportunity to provide a replacement decorated controller method and output that will subsequently be rendered. This allows for validation to display the original page or an abbreviated form with validation errors shown on validation failure. The before_render hook provides a place for functions that are called before the template is rendered. For example, you could use it to add and remove from the dictionary returned by the controller method, before it is passed to rendering. The after_render hook can act upon and modify the response out of rendering. """ self._initialize_validation_context() pylons.request.start_response = getattr(self, 'start_response', None) remainder = remainder or [] remainder = [url2pathname(r) for r in remainder] try: if 'tg_format' in params: pylons.request.headers['tg_format'] = params['tg_format'] controller.decoration.run_hooks('before_validate', remainder, params) validate_params = self._get_params_with_argspec( controller, params, remainder) for ignore in config.get('ignore_parameters', []): if params.get(ignore): del params[ignore] # Validate user input params = self._perform_validate(controller, validate_params) pylons.tmpl_context.form_values = params controller.decoration.run_hooks('before_call', remainder, params) # call controller method params, remainder = self._remove_argspec_params_from_params( controller, params, remainder) output = controller(*remainder, **dict(params)) except formencode.api.Invalid, inv: controller, output = self._handle_validation_errors( controller, remainder, params, inv) except Exception, e: if config.get('use_toscawidgets2'): from tw2.core import ValidationError if isinstance(e, ValidationError): controller, output = self._handle_validation_errors( controller, remainder, params, e) else: raise else: raise
def _get_tg_vars(): """Create a Bunch of variables that should be available in all templates. These variables are: WARNING: This function should not be called from outside of the render() code. Please consider this function as private. quote_plus the urllib quote_plus function url the turbogears.url function for creating flexible URLs identity the current visitor's identity information session the current beaker.session if the session_filter.on it set in the app.cfg configuration file. If it is not set then session will be None. locale the default locale inputs input values from a form errors validation errors request the WebOb Request Object config the app's config object auth_stack_enabled A boolean that determines if the auth stack is present in the environment predicates The :mod:`repoze.what.predicates` module. """ # TODO: Implement user_agent and other missing features. tg_vars = Bunch( config = tg.config, flash_obj = tg.flash, flash = DeprecatedFlashVariable( lambda: tg.flash.message, "flash is deprecated, please use flash_obj.message instead " "or use the new flash_obj.render() method" ), flash_status = DeprecatedFlashVariable( lambda: 'status_' + tg.flash.status, "flash_status is deprecated, please use flash_obj.status instead " "or use the new flash_obj.render() method" ), quote_plus = quote_plus, url = tg.url, # this will be None if no identity identity = request.environ.get('repoze.who.identity'), session = session, locale = tg.request.accept_language.best_matches(), errors = getattr(tmpl_context, "form_errors", {}), inputs = getattr(tmpl_context, "form_values", {}), request = tg.request, auth_stack_enabled = 'repoze.who.plugins' in tg.request.environ, predicates = predicates, ) # TODO in 2.2: we should actually just get helpers from the package's helpers # module and dump the use of the SOP. ######### #try: # helpers = config['package'].lib.helpers #except ImportError: # helpers = Bunch() ######### helpers = config.get('pylons.h') or config.get('pylons.helpers') root_vars = Bunch( c = tmpl_context, tmpl_context = tmpl_context, response = response, request = request, url = tg.url, helpers = helpers, tg = tg_vars ) #Allow users to provide a callable that defines extra vars to be #added to the template namespace variable_provider = config.get('variable_provider', None) if variable_provider: root_vars.update(variable_provider()) return root_vars
def _call(self, controller, params, remainder=None): """Run the controller with the given parameters. _call is called by _perform_call in Pylons' WSGIController. Any of the before_validate hook, the validation, the before_call hook, and the controller method can return a FormEncode Invalid exception, which will give the validation error handler the opportunity to provide a replacement decorated controller method and output that will subsequently be rendered. This allows for validation to display the original page or an abbreviated form with validation errors shown on validation failure. The before_render hook provides a place for functions that are called before the template is rendered. For example, you could use it to add and remove from the dictionary returned by the controller method, before it is passed to rendering. The after_render hook can act upon and modify the response out of rendering. """ self._initialize_validation_context() #This is necessary to prevent spurious Content Type header which would #cause problems to paste.response.replace_header calls and cause #responses wihout content type to get out with a wrong content type if not pylons.response.headers.get('Content-Type'): pylons.response.headers.pop('Content-Type', None) pylons.request.start_response = getattr(self, 'start_response', None) remainder = map(url2pathname, remainder or []) tg_decoration = controller.decoration try: if 'tg_format' in params: pylons.request.headers['tg_format'] = params['tg_format'] tg_decoration.run_hooks('before_validate', remainder, params) validate_params = self._get_params_with_argspec(controller, params, remainder) for ignore in config.get('ignore_parameters', []): if params.get(ignore): del params[ignore] # Validate user input params = self._perform_validate(controller, validate_params) pylons.tmpl_context.form_values = params tg_decoration.run_hooks('before_call', remainder, params) params, remainder = self._remove_argspec_params_from_params(controller, params, remainder) #apply controller wrappers controller_callable = tg_decoration.wrap_controller(controller) # call controller method output = controller_callable(*remainder, **dict(params)) except formencode.api.Invalid, inv: controller, output = self._handle_validation_errors( controller, remainder, params, inv)