Beispiel #1
0
    def init_prism(self):
        prism.init(self.flask_app, prism.settings.PRISM_CONFIG)

        # Load in prism's plugins
        logging.up('Starting plugin manager')
        prism.plugin_manager()
        logging.down()
Beispiel #2
0
    def init(self):
        logging.up('Searching')
        self._search_plugins(settings.CORE_PLUGINS_PATH, True)
        self._search_plugins(settings.PLUGINS_PATH, False)
        logging.down()

        self._verify_dependencies()

        logging.up('Loading plugins')
        self._load_plugins()
        logging.down()
Beispiel #3
0
def ping_version(output=False):
	global PRISM_VERSIONING

	should_check = True
	if 'last_check' in PRISM_VERSIONING:
		should_check = ((datetime.now() - datetime.strptime(PRISM_VERSIONING['last_check'], "%Y-%m-%d %H:%M:%S")).seconds >= 60 * 60 * 2)

	if output or should_check:
		logging.up('Collecting version info...')

	if should_check:
		rate_limited, dev_changes, recent_releases, num_releases = get_new_versions(prism.__version__)

		if rate_limited:
			logging.error('Rate limited. Version info not checked.')

			# If no values made yet, apply some defaults
			if 'dev_changes' not in PRISM_VERSIONING:
				PRISM_VERSIONING['dev_changes'] = []
			if 'recent_releases' not in PRISM_VERSIONING:
				PRISM_VERSIONING['recent_releases'] = []
			if 'num_releases' not in PRISM_VERSIONING:
				PRISM_VERSIONING['num_releases'] = 0
		else:
			# Reset and reapply cached versioning info
			PRISM_VERSIONING['dev_changes'] = []
			PRISM_VERSIONING['recent_releases'] = []
			PRISM_VERSIONING['num_releases'] = 0

			if 'dev_changes' is not None:
				PRISM_VERSIONING['dev_changes'] = dev_changes
			if 'recent_releases' is not None:
				PRISM_VERSIONING['recent_releases'] = recent_releases
			if 'num_releases' is not None:
				PRISM_VERSIONING['num_releases'] = num_releases

			if 'dev_changes' is not None or 'recent_releases' is not None or 'num_releases' is not None:
				PRISM_VERSIONING['last_check'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

	if output or should_check:
		if PRISM_VERSIONING['dev_changes'] is None:
			logging.error('Failed to check development version.')
		elif len(PRISM_VERSIONING['dev_changes']) > 0:
			logging.info('%s development commit(s) since the latest version.' % len(PRISM_VERSIONING['dev_changes']))
		if PRISM_VERSIONING['recent_releases'] is None:
			logging.error('Failed to check for latest version.')
		elif len(PRISM_VERSIONING['recent_releases']) != 0:
			logging.info('Current version: %s' % prism.__version__)
			if prism.__version__ != PRISM_VERSIONING['recent_releases'][0]['name']:
				logging.error('Your version is out of date. Latest version is %s' % PRISM_VERSIONING['recent_releases'][0]['name'])
			logging.down()
		logging.down()
Beispiel #4
0
    def start(self, opts):
        logging.output('----------=\e[1mPrism\e[0m=----------')
        prism.settings.init(os.getpid())

        logging.up('Starting Prism')

        self.init_flask()
        self.jinja_options()
        self.init_flask_plugins()
        self.init_prism()

        prism.settings.post_init()

        self.start_http()

        return 0
Beispiel #5
0
    def _verify_dependencies(self):
        # These will always be initialized.
        logging.up('Verifying dependencies')
        installed_packages_list = sorted(
            [i.key for i in pip.get_installed_distributions()])
        for plugin_id, plugin_info in self.available_plugins.items():
            if not plugin_info['_is_core']:
                if 'dependencies' not in plugin_info:
                    continue

                if 'os' in plugin_info['dependencies']:
                    if get_general_os() in plugin_info['dependencies']['os']:
                        plugin_info['dependencies'] = data_merge(
                            plugin_info['dependencies'],
                            plugin_info['dependencies']['os'][
                                get_general_os()])

                if 'plugin' in plugin_info['dependencies']:
                    for depend_name in plugin_info['dependencies']['plugin']:
                        installed = 'prism_' + depend_name in self.available_plugins
                        if not installed:
                            plugin_info['_is_satisfied'] = False
                        plugin_info['_dependencies'].append(
                            ('plugin', depend_name, installed))

                if 'binary' in plugin_info['dependencies']:
                    for depend_name in plugin_info['dependencies']['binary']:
                        installed = is_package_installed(depend_name)
                        if not installed:
                            plugin_info['_is_satisfied'] = False
                        plugin_info['_dependencies'].append(
                            ('binary', depend_name, installed))

                if 'module' in plugin_info['dependencies']:
                    for depend_name in plugin_info['dependencies']['module']:
                        installed = (depend_name in installed_packages_list)
                        if not installed:
                            plugin_info['_is_satisfied'] = False
                        plugin_info['_dependencies'].append(
                            ('module', depend_name, installed))

                if not plugin_info['_is_satisfied']:
                    # Create a dummy plugin container
                    self._insert_dummy_plugin(plugin_info)
                    logging.error('Dependency unsatisfied. Offender: %s' %
                                  plugin_id)
        logging.down()
Beispiel #6
0
    def start_http(self):
        logging.output('Verifying SSL')
        has_ssl = False

        try:
            from OpenSSL import SSL
            has_ssl = True
        except ImportError:
            pass

        if has_ssl:
            ssl_crt = os.path.join(prism.settings.CONFIG_FOLDER,
                                   'prism-ssl.crt')
            ssl_key = os.path.join(prism.settings.CONFIG_FOLDER,
                                   'prism-ssl.key')

            ssl_files_exist = os.path.exists(ssl_crt)
            if ssl_files_exist:
                ssl_files_exist = os.path.exists(ssl_key)

            # Generate certificate
            if not ssl_files_exist:
                logging.up()

                logging.up('Generating SSL certificate')
                prism.settings.generate_certificate()
                logging.down()

                logging.down()

            if self.should_bind:
                # Finally, start Prism under a self-signed SSL connection
                self.flask_app.run(host='::',
                                   port=9000,
                                   threaded=True,
                                   debug=prism.settings.is_dev(),
                                   ssl_context=(ssl_crt, ssl_key))
        else:
            if self.should_bind:
                logging.error(
                    'Warning: Prism is starting under an insecure connection!')
                self.flask_app.run(host='::',
                                   port=9000,
                                   threaded=True,
                                   debug=prism.settings.is_dev())
Beispiel #7
0
    def _init_plugin(self, plugin):
        """
		Initializes a plugin:
			1. Runs the plugin's init() function.
			2. Saves the config
			3. Loads the plugin's endpoints into flask
		"""
        logging.up('Starting %s v%s' % (plugin.name, plugin.version))

        def get_wrapper(plugin):
            def func():
                return plugin

            return func

        setattr(plugin.__class__, 'get', get_wrapper(plugin))

        plugin.init(PRISM_STATE)
        plugin.config.save()

        blueprint_name = plugin._endpoint
        # Create the plugin blueprint in flask
        plugin._blueprint = Blueprint(blueprint_name,
                                      plugin._info['_id'],
                                      template_folder='templates')

        if len(plugin._module_views) > 0:
            self.possible_permissions[plugin.plugin_id] = {}

            # Go through each of the module's views and add them to flask
            for view_class in plugin._module_views:
                view = view_class()

                self.possible_permissions[plugin.plugin_id][str(
                    view_class.__name__)] = view.title

                endpoint_id = '%s' % view_class.__name__

                with flask_app().app_context():
                    if view.menu is not None:
                        # Generate the parent menu item
                        if 'parent' in view.menu:
                            if '.' not in view.menu['parent']['id']:
                                parts = ('/' + blueprint_name +
                                         view.endpoint).split('/')
                                flask_app().add_url_rule(
                                    '/'.join(parts[:-1]),
                                    endpoint=blueprint_name + '.' +
                                    view.menu['parent']['id'])
                                item = current_menu.submenu(
                                    view.menu['parent']['id'])
                                item.register(blueprint_name + '.' +
                                              view.menu['parent']['id'],
                                              view.menu['parent']['text'],
                                              view.menu['parent']['order'],
                                              icon=view.menu['parent']['icon'])
                            else:
                                item = current_menu.submenu(
                                    view.menu['parent']['id'])
                                item.register(blueprint_name + '.' +
                                              endpoint_id,
                                              view.menu['parent']['text'],
                                              view.menu['parent']['order'],
                                              icon=view.menu['parent']['icon'])
                        item = current_menu.submenu(view.menu['id'])
                        item.register(blueprint_name + '.' + endpoint_id,
                                      view.title,
                                      view.menu['order'],
                                      icon=view.menu['icon'])
                        if prism.settings.is_dev():
                            logging.info('Registered menu item for /%s: %s' %
                                         (blueprint_name + view.endpoint,
                                          view.menu['id']))
                    else:
                        # Generate a hidden menu item so titles show correctly
                        item = current_menu.submenu(generate_random_string(12))
                        item.register(blueprint_name + '.' + endpoint_id,
                                      view.title,
                                      hidden=True)

                # Find all methods in the view class
                for func_name in [
                        method for method in dir(view)
                        if callable(getattr(view, method))
                ]:
                    if func_name.startswith('_'):
                        continue

                    if func_name not in ['get', 'post', 'put', 'delete']:
                        if not func_name.endswith(
                            ('_get', '_post', '_put', '_delete')):
                            continue
                        else:
                            # Set the fallback http method to the extention of the function name
                            parts = func_name.split('_')
                            if parts[len(parts) - 1] in ('get', 'post', 'put',
                                                         'delete'):
                                fallback_http_methods = [
                                    parts[len(parts) - 1].upper()
                                ]
                    else:
                        # Set the fallback http method to the function name
                        fallback_http_methods = [func_name.upper()]

                    if func_name == 'get':
                        endpoint_id = '%s' % view_class.__name__
                    elif func_name.endswith('_get'):
                        endpoint_id = '%s:%s' % (view_class.__name__, '_'.join(
                            func_name.split('_')[:-1]))
                    else:
                        endpoint_id = '%s:%s' % (view_class.__name__,
                                                 func_name)

                    # Get the method
                    func = getattr(view, func_name)
                    view_func_wrapper = self.func_wrapper(
                        plugin.plugin_id, func)

                    # If the http methods have been specified in the @subroute decorator
                    if hasattr(func, 'http_methods'):
                        fallback_http_methods = func.http_methods

                    fallback_endpoint = '/'
                    # If an endpoint has been specified in the @subroute decorator
                    if hasattr(func, 'endpoint'):
                        fallback_endpoint = func.endpoint

                    # Prepare fallback defaults for the page
                    if hasattr(func, 'defaults'):
                        fallback_defaults = func.defaults
                    elif func.__defaults__ is not None:
                        args, varargs, keywords, defaults = inspect.getargspec(
                            func)
                        fallback_defaults = dict(
                            zip(args[-len(defaults):], defaults))
                    else:
                        fallback_defaults = {}

                    func_routes = list()
                    if not hasattr(func, 'routes'):
                        func_routes.append({
                            'endpoint': fallback_endpoint,
                            'http_methods': fallback_http_methods,
                            'defaults': fallback_defaults
                        })
                    else:
                        func_routes = func.routes

                    # Add a route for the get function with no parameters
                    if func_name == 'get':
                        plugin._blueprint.add_url_rule(
                            view.endpoint + fallback_endpoint,
                            endpoint=endpoint_id,
                            methods=fallback_http_methods,
                            view_func=view_func_wrapper,
                            defaults=fallback_defaults)

                    for route in func_routes:
                        if 'endpoint' not in route:
                            route['endpoint'] = fallback_endpoint
                        if 'http_methods' not in route:
                            route['http_methods'] = fallback_http_methods
                        if 'defaults' not in route:
                            route['defaults'] = fallback_defaults.copy()

                        # Defaults are odd. They cannot be attached to routes with the key in the url
                        # For example: if <id> in in the url rule, it cann't be in defaults.
                        pattern = re.compile(r'<(?:.+?(?=:):)?(.+?)>')
                        if '<' in route['endpoint'] and len(
                                route['defaults']) > 0:
                            for id in re.findall(pattern, route['endpoint']):
                                try:
                                    del route['defaults'][id]
                                except:
                                    pass

                        if prism.settings.is_dev():
                            logging.info(
                                'Registered page /%s: %s %s' %
                                (blueprint_name + view.endpoint +
                                 route['endpoint'], blueprint_name + '.' +
                                 endpoint_id, route['http_methods']))

                        plugin._blueprint.add_url_rule(
                            view.endpoint + route['endpoint'],
                            endpoint=endpoint_id,
                            methods=route['http_methods'],
                            view_func=view_func_wrapper,
                            defaults=route['defaults'])

        flask_app().register_blueprint(plugin._blueprint,
                                       url_prefix='/' +
                                       blueprint_name.replace('.', '/'))

        plugin.post_init(PRISM_STATE)

        logging.down()
Beispiel #8
0
    def _load_plugins(self):
        """ Attempts to load every enabled plugin """
        plugins_loaded = list()

        core_plugins = list()
        plugins_additional = list()

        for plugin_id, plugin_info in self.available_plugins.items():
            if plugin_info['_is_core']:
                core_plugins.append(plugin_info)
            elif plugin_info['_is_satisfied']:
                plugins_additional.append(plugin_info)

        # These will always be initialized.
        logging.info('Loading %s core plugin(s)' % len(core_plugins))
        for plugin_info in core_plugins:
            plugin = self._import_plugin(plugin_info)
            if not plugin:
                logging.error(
                    'Error: Failed to load core plugin. Offender: %s' %
                    plugin_info['id'])
                continue
            else:
                logging.good('Loaded %s' % plugin_info['id'])

            plugins_loaded.append(plugin)
        logging.down()

        logging.info('Sorting dependencies')
        sorted_plugins = []
        while plugins_additional:
            added_any = False
            for plugin in plugins_additional:
                ready_add = True
                if 'dependencies' in plugin and 'plugin' in plugin[
                        'dependencies']:
                    for dependency in plugin['dependencies']['plugin']:
                        found = False
                        for ready_plugin in sorted_plugins:
                            if ready_plugin['id'] == dependency:
                                found = True
                                break
                        if not found:
                            ready_add = False
                if ready_add:
                    added_any = True
                    sorted_plugins.append(plugin)
                    plugins_additional.remove(plugin)
            if not added_any:
                break
        plugins_additional = sorted_plugins

        logging.up('Loading %s additional plugin(s)' % len(plugins_additional))
        # Start plugins if they're set to be enabled.
        for plugin_info in plugins_additional:
            if not self.is_enabled(plugin_info['id']):
                self._insert_dummy_plugin(plugin_info)
                continue

            plugin = self._import_plugin(plugin_info)
            if not plugin:
                logging.error(
                    'Error: Failed to load additional plugin. Offender: %s' %
                    plugin_id)
                continue
            else:
                logging.good('Loaded %s' % plugin_info['id'])

            plugins_loaded.append(plugin)
        logging.down()

        logging.up('Initializing %s plugin(s)' % len(plugins_loaded))
        for plugin in plugins_loaded:
            plugin._info['_is_enabled'] = True
            self._init_plugin(plugin)
        logging.down()