Example #1
0
def example_policies(cls):
    """
    This function gets registered under 'example' in the
    :attr:`gateone.ApplicationWebSocket.security` dict and is called by the
    :func:`auth.require` decorator by way of the :class:`auth.policies`
    sub-function. It returns ``True`` or ``False`` depending on what is defined
    in the settings dir and what function is being called.
    """
    instance = cls.instance # Your Application instance
    function = cls.function # Wrapped function
    f_args = cls.f_args     # Wrapped function's arguments
    f_kwargs = cls.f_kwargs # Wrapped function's keyword arguments
    # This is a convenient way to map function/method names to specific policy
    # functions:
    policy_functions = {
        'test_example': policy_test_example,
    }
    user = instance.current_user
    # The applicable_policies() function takes an application 'scope', a user
    # dict (must have a 'upn' key), and a dict that contains all of Gate One's
    # settings (always available via ApplicationWebSocket.prefs) and returns
    # a single dict containing the merged settings (aka policies) for that
    # scope.
    # In other words, if you have this inside a file in gateone/settings/:
    #    {
    #        "*": {
    #            "example": {
    #                "foo": "bar"
    #            }
    #        },
    #        "[email protected]": {
    #            "example": {
    #                "foo": "joe!"
    #            }
    #        }
    #    }
    #
    # applicable_policies() would return:
    #
    #    {"foo": "bar"}
    #
    # for regular users but [email protected] would get:
    #
    #    {"foo": "joe!"}
    policy = applicable_policies('example', user, instance.ws.prefs)
    if not policy: # No policies found for the given scope
        return True # A world without limits!
    # Check the basics first...  Is {"allow": true}?
    if 'allow' in policy: # Only check this if there's an "allow" somewhere
        if not policy['allow']: # User is DENIED!
            example_log.error(_(
                "%s denied access to the Example application by policy."
                % user['upn']))
            return False
    # Here we run through our policy_functions dict and call the appropriate
    # policy-checking function that matches the decorated method's name:
    if function.__name__ in policy_functions:
        return policy_functions[function.__name__](cls, policy)
    return True # Default to permissive if we made it this far
Example #2
0
def example_policies(cls):
    """
    This function gets registered under 'example' in the
    :attr:`gateone.ApplicationWebSocket.security` dict and is called by the
    :func:`auth.require` decorator by way of the :class:`auth.policies`
    sub-function. It returns ``True`` or ``False`` depending on what is defined
    in the settings dir and what function is being called.
    """
    instance = cls.instance  # Your Application instance
    function = cls.function  # Wrapped function
    f_args = cls.f_args  # Wrapped function's arguments
    f_kwargs = cls.f_kwargs  # Wrapped function's keyword arguments
    # This is a convenient way to map function/method names to specific policy
    # functions:
    policy_functions = {
        'test_example': policy_test_example,
    }
    user = instance.current_user
    # The applicable_policies() function takes an application 'scope', a user
    # dict (must have a 'upn' key), and a dict that contains all of Gate One's
    # settings (always available via ApplicationWebSocket.prefs) and returns
    # a single dict containing the merged settings (aka policies) for that
    # scope.
    # In other words, if you have this inside a file in gateone/settings/:
    #    {
    #        "*": {
    #            "example": {
    #                "foo": "bar"
    #            }
    #        },
    #        "[email protected]": {
    #            "example": {
    #                "foo": "joe!"
    #            }
    #        }
    #    }
    #
    # applicable_policies() would return:
    #
    #    {"foo": "bar"}
    #
    # for regular users but [email protected] would get:
    #
    #    {"foo": "joe!"}
    policy = applicable_policies('example', user, instance.ws.prefs)
    if not policy:  # No policies found for the given scope
        return True  # A world without limits!
    # Check the basics first...  Is {"allow": true}?
    if 'allow' in policy:  # Only check this if there's an "allow" somewhere
        if not policy['allow']:  # User is DENIED!
            example_log.error(
                _("%s denied access to the Example application by policy." %
                  user['upn']))
            return False
    # Here we run through our policy_functions dict and call the appropriate
    # policy-checking function that matches the decorated method's name:
    if function.__name__ in policy_functions:
        return policy_functions[function.__name__](cls, policy)
    return True  # Default to permissive if we made it this far
Example #3
0
 def authenticate(self):
     """
     This gets called immediately after the user is authenticated
     successfully at the end of :meth:`ApplicationWebSocket.authenticate`.
     Sends all plugin JavaScript files to the client and triggers the
     'example:authenticate' event.
     """
     example_log.debug('ExampleApplication.authenticate()')
     # This is the log metadata that was mentioned near the top of this file.
     # This log_metadata will be JSON-encoded and included in all log
     # messages that use `self.example_log` which is super useful when
     # you need to parse logs at some later date and want to know the
     # circumstances surrounding any given message.
     self.log_metadata = {
         'upn': self.current_user['upn'],
         'ip_address': self.ws.request.remote_ip,
         # If your app uses the location feature make sure to include it:
         'location': self.ws.location
     }
     self.example_log = go_logger("gateone.example", **self.log_metadata)
     # NOTE:  To include even *more* metadata in a log message on a one-time
     # basis simply pass the metadata to the logger like so:
     #   self.example_log("Some log message", metadata={'foo': 'bar'})
     # That will ensure that {'foo': 'bar'} is included in the JSON portion
     # Assign our user-specific settings/policies for quick reference
     self.policy = applicable_policies('example', self.current_user,
                                       self.ws.prefs)
     # NOTE:  The applicable_policies() function *is* memoized but the above
     #        is still much faster.
     # Start by determining if the user can even use this app
     if 'allow' in self.policy:
         # This is the same check inside example_policies().  Why put it here
         # too?  So we can skip sending the client JS/CSS that they won't be
         # able to use.
         if not self.policy['allow']:
             # User is not allowed to access this application.  Don't
             # bother sending them any static files and whatnot...
             self.example_log.debug(
                 _("User is not allowed to use the Example application.  "
                   "Skipping post-authentication functions."))
             return
     # Render and send the client our example.css
     example_css = os.path.join(APPLICATION_PATH, 'templates',
                                'example.css')
     self.render_and_send_css(example_css, element_id="example.css")
     # NOTE:  See the Gate One docs for gateone.py to see how
     #        render_and_send_css() works.  It auto-minifies and caches!
     # Send the client our application's static JavaScript files
     static_dir = os.path.join(APPLICATION_PATH, 'static')
     js_files = []
     if os.path.isdir(static_dir):
         js_files = os.listdir(static_dir)  # Everything in static/*.js
         js_files.sort()
     for fname in js_files:
         if fname.endswith('.js'):
             js_file_path = os.path.join(static_dir, fname)
             # This is notable:  To ensure that all your JavaScript files
             # get loaded *after* example.js we add 'example.js' as a
             # dependency for all JS files we send to the client.
             if fname == 'example.js':
                 # Adding CSS as a dependency to your app's JS is also a
                 # good idea.  You could also put 'theme.css' if you want to
                 # ensure that the theme gets loaded before your JavaScript
                 # init() function is called.
                 self.send_js(js_file_path, requires=["example.css"])
             else:
                 # Send any other discovered JS files to the client with
                 # example.js as the only dependency.
                 self.send_js(js_file_path, requires='example.js')
     # If you're not using plugins you can disregard this:
     # The send_plugin_static_files() function will locate any JS/CSS files
     # in your plugins' respective static directories and send them to the
     # client.  It is also smart enough to know which plugins are enabled
     # or disabled.
     self.ws.send_plugin_static_files(os.path.join(APPLICATION_PATH,
                                                   'plugins'),
                                      application="example",
                                      requires=["example.js"])
     sess = SESSIONS[self.ws.session]  # A shortcut to save some typing
     # Create a place to store app-specific stuff related to this session
     # (but not necessarily this 'location')
     if "example" not in sess:
         sess['example'] = {}  # A mostly persistent place to store info
     # If you want to call a function whenever Gate One exits just add it
     # to SESSIONS[self.ws.session]["kill_session_callbacks"] like so:
     #if kill_session_func not in sess["kill_session_callbacks"]:
     #sess["kill_session_callbacks"].append(kill_session_func)
     # If you want to call a function whenever a user's session times out
     # just attach it to SESSIONS[self.ws.session]["timeout_callbacks"]
     # like so:
     #if timeout_session_func not in sess["timeout_callbacks"]:
     #sess["timeout_callbacks"].append(timeout_session_func)
     # NOTE: The user will often be authenticated before example.js is
     # loaded.  In fact, the only time this won't be the case is when the
     # user is disconnected (e.g. server restart) and then reconnects.
     self.trigger("example:authenticate")
Example #4
0
 def authenticate(self):
     """
     This gets called immediately after the user is authenticated
     successfully at the end of :meth:`ApplicationWebSocket.authenticate`.
     Sends all plugin JavaScript files to the client and triggers the
     'example:authenticate' event.
     """
     example_log.debug('ExampleApplication.authenticate()')
     # This is the log metadata that was mentioned near the top of this file.
     # This log_metadata will be JSON-encoded and included in all log
     # messages that use `self.example_log` which is super useful when
     # you need to parse logs at some later date and want to know the
     # circumstances surrounding any given message.
     self.log_metadata = {
         'upn': self.current_user['upn'],
         'ip_address': self.ws.request.remote_ip,
         # If your app uses the location feature make sure to include it:
         'location': self.ws.location
     }
     self.example_log = go_logger("gateone.example", **self.log_metadata)
     # NOTE:  To include even *more* metadata in a log message on a one-time
     # basis simply pass the metadata to the logger like so:
     #   self.example_log("Some log message", metadata={'foo': 'bar'})
     # That will ensure that {'foo': 'bar'} is included in the JSON portion
     # Assign our user-specific settings/policies for quick reference
     self.policy = applicable_policies(
         'example', self.current_user, self.ws.prefs)
     # NOTE:  The applicable_policies() function *is* memoized but the above
     #        is still much faster.
     # Start by determining if the user can even use this app
     if 'allow' in self.policy:
         # This is the same check inside example_policies().  Why put it here
         # too?  So we can skip sending the client JS/CSS that they won't be
         # able to use.
         if not self.policy['allow']:
             # User is not allowed to access this application.  Don't
             # bother sending them any static files and whatnot...
             self.example_log.debug(_(
                 "User is not allowed to use the Example application.  "
                 "Skipping post-authentication functions."))
             return
     # Render and send the client our example.css
     example_css = os.path.join(
         APPLICATION_PATH, 'templates', 'example.css')
     self.render_and_send_css(example_css, element_id="example.css")
     # NOTE:  See the Gate One docs for gateone.py to see how
     #        render_and_send_css() works.  It auto-minifies and caches!
     # Send the client our application's static JavaScript files
     static_dir = os.path.join(APPLICATION_PATH, 'static')
     js_files = os.listdir(static_dir) # Everything in static/*.js
     js_files.sort()
     for fname in js_files:
         if fname.endswith('.js'):
             js_file_path = os.path.join(static_dir, fname)
             # This is notable:  To ensure that all your JavaScript files
             # get loaded *after* example.js we add 'example.js' as a
             # dependency for all JS files we send to the client.
             if fname == 'example.js':
                 # Adding CSS as a dependency to your app's JS is also a
                 # good idea.  You could also put 'theme.css' if you want to
                 # ensure that the theme gets loaded before your JavaScript
                 # init() function is called.
                 self.ws.send_js(js_file_path, requires=["example.css"])
             else:
                 # Send any other discovered JS files to the client with
                 # example.js as the only dependency.
                 self.ws.send_js(js_file_path, requires='example.js')
     # If you're not using plugins you can disregard this:
     # The send_plugin_static_files() function will locate any JS/CSS files
     # in your plugins' respective static directories and send them to the
     # client.  It is also smart enough to know which plugins are enabled
     # or disabled.
     self.ws.send_plugin_static_files(
         os.path.join(APPLICATION_PATH, 'plugins'),
         application="example",
         requires=["example.js"])
     sess = SESSIONS[self.ws.session] # A shortcut to save some typing
     # Create a place to store app-specific stuff related to this session
     # (but not necessarily this 'location')
     if "example" not in sess:
         sess['example'] = {} # A mostly persistent place to store info
     # If you want to call a function whenever Gate One exits just add it
     # to SESSIONS[self.ws.session]["kill_session_callbacks"] like so:
     #if kill_session_func not in sess["kill_session_callbacks"]:
         #sess["kill_session_callbacks"].append(kill_session_func)
     # If you want to call a function whenever a user's session times out
     # just attach it to SESSIONS[self.ws.session]["timeout_callbacks"]
     # like so:
     #if timeout_session_func not in sess["timeout_callbacks"]:
         #sess["timeout_callbacks"].append(timeout_session_func)
     # NOTE: The user will often be authenticated before example.js is
     # loaded.  In fact, the only time this won't be the case is when the
     # user is disconnected (e.g. server restart) and then reconnects.
     self.trigger("example:authenticate")