Beispiel #1
0
 def __init__(self):
     handlers = []
     add_versioned_resource_urls(handlers, ResourceSet("test", {1: TestResource, 2: V2TestResource}), prefix="/api")
     add_versioned_resource_urls(
         handlers, ResourceSet("another", {1: AnotherResource, 2: AnotherResource}), prefix="/api"
     )
     add_versioned_resource_urls(handlers, MyOwnResourceSet(), prefix="/api")
     Application.__init__(self, handlers, debug=True)
Beispiel #2
0
    def __init__(self):
        self.db_pool = adbapi.ConnectionPool("psycopg2", host="127.0.0.1", database="bench",
                                             user="******", password="******", cp_max=32, cp_reconnect=True)

        handlers = [
            (r"/bench", BenchEndpoint, dict(db=self.db_pool)),
        ]
        Application.__init__(self, handlers, dict(xheaders=True))
Beispiel #3
0
 def __init__(self, root, **settings):
     self.store = InMemoryCardStore()
     handlers = [
         (r"/", root),
         (r"/publish/(?P<channel>.*)/", PublicationHandler,
          dict(store=self.store)),
         (r"/subscribe", SubscriptionHandler,
          dict(store=self.store)),
     ]
     Application.__init__(self, handlers, **settings)
Beispiel #4
0
 def __init__(self, config_file=None, **settings):
     if self.config_required and config_file is None:
         raise ValueError(
             "Please specify a config file using --appopts=<config.yaml>")
     config = self.get_config_settings(config_file)
     self.setup_factory_preprocessor(config)
     self.initialize(settings, config)
     path_prefix = self._get_configured_path_prefix(config)
     routes = self._build_routes(path_prefix)
     Application.__init__(self, routes, **settings)
Beispiel #5
0
    def __init__(self):
        self.db_pool = txpostgres.ConnectionPool("psycopg2", host="127.0.0.1", database="bench", 
                                                 user="******", password="******", min=32)

        d = self.db_pool.start()
        d.addCallback(lambda _: log.msg("DB connected"))

        handlers = [
            (r"/bench", BenchEndpoint, dict(db=self.db_pool)),
        ]
        Application.__init__(self, handlers, dict(xheaders=True))
Beispiel #6
0
    def load(self):
        if "secret" not in self.data:
            self.logger.warn("Generating secret. DO NOT SHARE IT WITH ANYONE!")
            self.logger.warn("It's stored in data/plugins/web/data.json - "
                             "keep this file secure!")
            with self.data:
                self.data["secret"] = mkpasswd(60, 20, 20, 20)

        self.template_loader = TemplateLoader(self)

        if self.config.get("output_requests", True):
            log_function = self.log_request
        else:
            log_function = self.null_log

        self.application = Application(
            list(self.handlers.items()),  # Handler list

            ## General settings
            xheaders=True,
            log_function=log_function,
            gzip=True,  # Are there browsers that don't support this now?
            # error_handler=ErrorHandler,

            ## Security settings
            cookie_secret=self.data["secret"],
            login_url="/login",

            ## Template settings
            template_loader=self.template_loader,

            ## Static file settings
            static_path="web/static"
        )

        if self.config.get("hosted", False):
            hosted = self.config["hosted"]

            if isinstance(hosted, dict):
                self.interface = os.environ.get(hosted["hostname"], False)
                self.port = os.environ.get(hosted["port"], False)

                if not self.interface:
                    self.logger.error(
                        "Unknown env var: %s" % hosted["hostname"]
                    )
                    return False
                if not self.port:
                    self.logger.error(
                        "Unknown env var: %s" % hosted["port"]
                    )
                    return False
            else:
                if hosted in ["openshift"]:
                    self.interface = os.environ.get("OPENSHIFT__IP", False)
                    self.port = os.environ.get("OPENSHIFT__PORT", False)

                    if not self.interface:
                        self.logger.error(
                            "Unknown env var: OPENSHIFT__IP - Are you on "
                            "OpenShift?"
                        )
                        return False
                    if not self.port:
                        self.logger.error(
                            "Unknown env var: OPENSHIFT__PORT - Are you on "
                            "OpenShift?"
                        )
                        return False
                else:
                    self.logger.error("Unknown hosted service: %s" % hosted)
                    return False

        else:
            if self.config.get("hostname", "0.0.0.0").strip() == "0.0.0.0":
                self.interface = ""
            else:
                self.interface = self.config.get("hostname")

            self.listen_port = self.config.get("port", 8080)

        return True
Beispiel #7
0
    def request(self, jbody=None, role=None, user_id=None, headers=None, body='',
                remote_ip='0.0.0.0', method='MOCK', kwargs={}):

        """
        Function userful for performing mock requests.

        Args:

            jbody:
                The body of the request as a dict (it will be automatically
                converted to string)

            body:
                The body of the request as a string

            role:
                If we should perform authentication role can be either "admin",
                "receiver" or "wb"

            user_id:
                If when performing authentication the session should be bound
                to a certain user_id.

            method:
                HTTP method, e.g. "GET" or "POST"

            uri:
                URL to fetch

            role:
                the role

            headers:
                (dict or :class:`cyclone.httputil.HTTPHeaders` instance) HTTP
                headers to pass on the request

            remote_ip:
                If a particular remote_ip should be set.

        """
        if jbody and not body:
            body = json.dumps(jbody)
        elif body and jbody:
            raise ValueError('jbody and body in conflict')

        application = Application([])

        tr = proto_helpers.StringTransport()
        connection = GLHTTPConnection()
        connection.factory = application
        connection.makeConnection(tr)

        request = httpserver.HTTPRequest(uri='mock',
                                         method=method,
                                         headers=headers,
                                         body=body,
                                         remote_ip=remote_ip,
                                         connection=connection)

        handler = self._handler(application, request, **kwargs)

        if role:
            session = authentication.GLSession(user_id, role, 'enabled')
            handler.request.headers['X-Session'] = session.id
        return handler
Beispiel #8
0
def mock_app_builder():
    return Application([
        (r'/testing/', _TestHandler),
        (r'/deferred_testing/', DeferredTestHandler),
        (r'/cookie_testing/', CookieTestHandler),
    ], cookie_secret="insecure")
Beispiel #9
0
class WebPlugin(PluginObject):
    """
    Web plugin object
    """

    api_log = None
    api_keys = None

    api_key_data = {}
    config = {}
    data = {}

    namespace = {}  # Global, not used right now

    handlers = {}  # Cyclone handlers

    interface = ""  # Listening interface
    listen_port = 8080

    running = False

    application = None  # Cyclone application
    port = None  # Twisted's server port
    storage = None
    template_loader = None

    navbar_items = {}

    ## Stuff plugins might find useful

    commands = None
    events = None
    packages = None
    plugins = None
    sessions = None
    stats = None

    ## Internal(ish) functions

    def setup(self):
        self.storage = StorageManager()

        try:
            self.config = self.storage.get_file(self, "config", YAML,
                                                "plugins/web.yml")
            self.logger.debug("Config loaded")
        except Exception:
            self.logger.exception(_("Error loading configuration"))
            self._disable_self()
            return
        if not self.config.exists:
            self.logger.error(_("Unable to find config/plugins/web.yml"))
            self._disable_self()
            return

        try:
            self.data = self.storage.get_file(self, "data", JSON,
                                              "plugins/web/data.json")
            self.logger.debug("Data loaded")
        except Exception:
            self.logger.exception("Error loading data file!")
            return self._disable_self()

        try:
            _sessions = self.storage.get_file(self, "data", JSON,
                                              "plugins/web/sessions.json")
            self.logger.debug("Sessions loaded")
        except Exception:
            self.logger.exception("Error loading sessions file!")
            return self._disable_self()

        try:
            self.api_log = open("logs/api.log", "w")
        except Exception:
            self.logger.exception("Unable to open api log file!")
            return self._disable_self()

        try:
            self.api_key_data = self.storage.get_file(
                self, "data", JSON, "plugins/web/apikeys.json")
            self.logger.debug("Sessions loaded")
        except Exception:
            self.logger.exception("Error loading API keys!")
            return self._disable_self()

        try:
            self.api_log = open("logs/api.log", "w")
        except Exception:
            self.logger.exception("Unable to open api log file!")
            return self._disable_self()

        self.config.add_callback(self.restart)
        self.data.add_callback(self.restart)

        # Index page

        self.add_handler(r"/", "plugins.web.routes.index.Route")

        # Login-related

        self.add_handler(r"/login", "plugins.web.routes.login.Route")
        self.add_handler(r"/logout", "plugins.web.routes.logout.Route")
        self.add_handler(r"/login/reset",
                         "plugins.web.routes.login-reset.Route")

        # Accounts-related

        self.add_handler(r"/account", "plugins.web.routes.account.index.Route")
        self.add_handler(r"/account/password/change",
                         "plugins.web.routes.account.password.change.Route")
        self.add_handler(r"/account/apikeys/create",
                         "plugins.web.routes.account.apikeys.create.Route")
        self.add_handler(r"/account/apikeys/delete",
                         "plugins.web.routes.account.apikeys.delete.Route")
        self.add_handler(r"/account/users/logout",
                         "plugins.web.routes.account.users.logout.Route")

        # Admin-related

        self.add_handler(r"/admin", "plugins.web.routes.admin.index.Route")
        self.add_handler(r"/admin/files",
                         "plugins.web.routes.admin.files.Route")
        self.add_handler(r"/admin/files/(config|data)/(.*)",
                         "plugins.web.routes.admin.file.Route")
        self.add_handler(r"/api/admin/get_stats",
                         "plugins.web.routes.api.admin.get_stats.Route")

        self.add_navbar_entry("admin", "/admin", "settings")

        # API routes

        self.add_api_handler(
            r"/plugins/web/get_username",
            "plugins.web.routes.api.plugins.web.get_username.Route")

        # Stuff routes might find useful

        self.api_keys = APIKeys(self, self.api_key_data)
        self.commands = CommandManager()
        self.events = EventManager()
        self.packages = Packages(False)
        self.plugins = PluginManager()
        self.sessions = Sessions(self, _sessions)
        self.stats = Stats()

        # Load 'er up!

        r = self.load()

        if not r:
            self._disable_self()
            return

        if not self.factory_manager.running:
            self.events.add_callback("ReactorStarted", self, self.start, 0)
        else:
            self.start()

    def load(self):
        if "secret" not in self.data:
            self.logger.warn("Generating secret. DO NOT SHARE IT WITH ANYONE!")
            self.logger.warn("It's stored in data/plugins/web/data.json - "
                             "keep this file secure!")
            with self.data:
                self.data["secret"] = mkpasswd(60, 20, 20, 20)

        self.template_loader = TemplateLoader(self)

        if self.config.get("output_requests", True):
            log_function = self.log_request
        else:
            log_function = self.null_log

        self.application = Application(
            list(self.handlers.items()),  # Handler list

            ## General settings
            xheaders=self.config.get("x_forwarded_for", False),
            log_function=log_function,
            gzip=True,  # Are there browsers that don't support this now?
            # error_handler=ErrorHandler,

            ## Security settings
            cookie_secret=self.data["secret"],
            login_url="/login",

            ## Template settings
            template_loader=self.template_loader,

            ## Static file settings
            static_path="web/static")

        if self.config.get("hosted", False):
            hosted = self.config["hosted"]

            if isinstance(hosted, dict):
                self.interface = os.environ.get(hosted["hostname"], False)
                self.port = os.environ.get(hosted["port"], False)

                if not self.interface:
                    self.logger.error("Unknown env var: %s" %
                                      hosted["hostname"])
                    return False
                if not self.port:
                    self.logger.error("Unknown env var: %s" % hosted["port"])
                    return False
            else:
                if hosted in ["openshift"]:
                    self.interface = os.environ.get("OPENSHIFT__IP", False)
                    self.port = os.environ.get("OPENSHIFT__PORT", False)

                    if not self.interface:
                        self.logger.error(
                            "Unknown env var: OPENSHIFT__IP - Are you on "
                            "OpenShift?")
                        return False
                    if not self.port:
                        self.logger.error(
                            "Unknown env var: OPENSHIFT__PORT - Are you on "
                            "OpenShift?")
                        return False
                else:
                    self.logger.error("Unknown hosted service: %s" % hosted)
                    return False

        else:
            if self.config.get("hostname", "0.0.0.0").strip() == "0.0.0.0":
                self.interface = ""
            else:
                self.interface = self.config["hostname"]

            self.listen_port = self.config.get("port", 8080)

        return True

    def start(self, _=None):
        self.stats.start()

        self.port = reactor.listenTCP(self.listen_port,
                                      self.application,
                                      interface=self.interface)

        self.logger.info("Server started")
        self.running = True

        self.events.run_callback("Web/ServerStartedEvent",
                                 ServerStartedEvent(self, self.application))

    def stop(self):
        self.application.doStop()
        d = self.port.stopListening()

        d.addCallback(lambda _: self.logger.info("Server stopped"))
        d.addCallback(lambda _: setattr(self, "running", False))
        d.addCallback(lambda _: self.events.run_callback(
            "Web/ServerStopped", ServerStoppedEvent(self)))

        d.addErrback(lambda f: self.logger.error("Failed to stop: %s" % f))

        self.stats.stop()

        return d

    def restart(self):
        d = self.stop()

        d.addCallback(lambda _: [self.load(), self.start()])

    def deactivate(self):
        d = self.stop()

        self.handlers.clear()
        self.navbar_items.clear()

        return d

    def log_request(self, request):
        log = self.logger.info

        status_code = request.get_status()

        if status_code >= 500:
            log = self.logger.error
        elif status_code >= 400:
            log = self.logger.warn

        path = request.request.path

        # Check if this is an API method and hide the key if so

        matched = re.match(r"/api/v[0-9]/([a-zA-Z0-9]+)/.*", path)

        if matched:
            key = matched.groups()[0]
            user = self.api_keys.get_username(key)

            if user:
                path = path.replace(key, "<API: %s>" % user)
            else:
                path = path.replace(key, "<API: Invalid key>")

        log("[%s] %s %s -> HTTP %s" %
            (request.request.remote_ip, request.request.method, path,
             request.get_status()))

    def null_log(self, *args, **kwargs):
        pass

    ## Public API functions

    def add_api_handler(self, pattern, handler, version=1):
        if not pattern.startswith("/"):
            pattern = "/%s" % pattern
        pattern = "/api/v%s/([A-Za-z0-9]+)%s" % (version, pattern)

        return self.add_handler(pattern, handler)

    def add_handler(self, pattern, handler):
        self.logger.debug("Adding route: %s -> %s" % (pattern, handler))

        if pattern in self.handlers:
            self.logger.debug("Route already exists.")
            return False

        self.handlers[pattern] = handler

        if self.application is not None:
            self.application.add_handlers(r".*$", [(pattern, handler)])

        self.logger.debug("Handlers list: %s" % list(self.handlers.values()))

    def add_navbar_entry(self, title, url, icon="question"):
        if title in self.navbar_items:
            return False
        self.logger.debug("Adding navbar entry: %s -> %s" % (title, url))
        self.navbar_items[title] = {"url": url, "active": False, "icon": icon}
        return True

    def check_permission(self, perm, session=None):
        if session is None:
            username = None
        elif isinstance(session, str) or isinstance(session, unicode):
            username = session
        else:
            username = session["username"]

        return self.commands.perm_handler.check(perm, username, "web",
                                                "plugin-web")

    def remove_api_handlers(self, *names, **kwargs):
        """
        :param names:
        :param version:
        :return:
        """

        version = kwargs.get("version", 1)
        patterns = []

        for pattern in names:
            if not pattern.startswith("/"):
                pattern = "/%s" % pattern
            pattern = "/api/v%s/([A-Za-z0-9]+)%s" % (version, pattern)

            patterns.append(pattern)

        return self.remove_handlers(*patterns)

    def remove_handlers(self, *names):
        found = False

        for name in names:
            if name in self.handlers:
                found = True
                del self.handlers[name]

        if found:
            self.restart()

    def write_api_log(self, address, key, username, message):
        self.api_log.write("%s | %s (%s) | %s\n" %
                           (address, key, username, message))
Beispiel #10
0
 def setUp(self):
     self.app = Application(some_setting="foo")
     self.request = Mock()
     self.rh = RequestHandler(self.app, self.request)
Beispiel #11
0
    def request(self,
                jbody=None,
                user_id=None,
                role=None,
                headers=None,
                body='',
                remote_ip='0.0.0.0',
                method='MOCK',
                kwargs={}):
        """
        Function userful for performing mock requests.

        Args:

            jbody:
                The body of the request as a dict (it will be automatically
                converted to string)

            body:
                The body of the request as a string

            user_id:
                when simulating authentication the session should be bound
                to a certain user_id.

            role:
                when simulating authentication the session should be bound
                to a certain role.

            method:
                HTTP method, e.g. "GET" or "POST"

            headers:
                (dict or :class:`cyclone.httputil.HTTPHeaders` instance) HTTP
                headers to pass on the request

            remote_ip:
                If a particular remote_ip should be set.

        """
        if jbody and not body:
            body = json.dumps(jbody)
        elif body and jbody:
            raise ValueError('jbody and body in conflict')

        application = Application([])

        tr = proto_helpers.StringTransport()
        connection = GLHTTPConnection()
        connection.factory = application
        connection.makeConnection(tr)

        request = httpserver.HTTPRequest(uri='mock',
                                         method=method,
                                         headers=headers,
                                         body=body,
                                         remote_ip=remote_ip,
                                         connection=connection)

        handler = self._handler(application, request, **kwargs)

        if user_id is None and role is not None:
            if role == 'admin':
                user_id = self.dummyAdminUser['id']
            elif role == 'receiver':
                user_id = self.dummyReceiverUser_1['id']
            elif role == 'custodian':
                user_id = self.dummyCustodianUser['id']

        if role is not None:
            session = GLSession(user_id, role, 'enabled')
            handler.request.headers['X-Session'] = session.id

        return handler
Beispiel #12
0
    def request(self,
                jbody=None,
                user_id=None,
                role=None,
                headers=None,
                body='',
                remote_ip='0.0.0.0',
                method='MOCK',
                attached_file={},
                kwargs={}):
        """
        Function userful for performing mock requests.

        Args:

            jbody:
                The body of the request as a dict (it will be automatically
                converted to string)

            body:
                The body of the request as a string

            user_id:
                when simulating authentication the session should be bound
                to a certain user_id.

            role:
                when simulating authentication the session should be bound
                to a certain role.

            method:
                HTTP method, e.g. "GET" or "POST"

            headers:
                (dict or :class:`cyclone.httputil.HTTPHeaders` instance) HTTP
                headers to pass on the request

            remote_ip:
                If a particular remote_ip should be set.

            attached_file:
                A cyclone.httputil.HTTPFiles or a dict to place in the request.files obj

        """
        if jbody and not body:
            body = json.dumps(jbody)
        elif body and jbody:
            raise ValueError('jbody and body in conflict')

        if attached_file is None:
            fake_files = {}
        else:
            fake_files = {
                'file': [attached_file]
            }  # Yes this is ugly, but it's the format

        application = Application([])

        tr = proto_helpers.StringTransport()
        connection = GLHTTPConnection()
        connection.factory = application
        connection.makeConnection(tr)

        request = httpserver.HTTPRequest(uri='mock',
                                         method=method,
                                         headers=headers,
                                         body=body,
                                         remote_ip=remote_ip,
                                         connection=connection,
                                         files=fake_files)

        def mock_write(cls, response=None):
            if response:
                self.responses.append(response)

        self._handler.write = mock_write

        def mock_finish(cls):
            pass

        self._handler.finish = mock_finish

        handler = self._handler(application, request, **kwargs)  # pylint: disable=not-callable

        if user_id is None and role is not None:
            if role == 'admin':
                user_id = self.dummyAdminUser['id']
            elif role == 'receiver':
                user_id = self.dummyReceiverUser_1['id']
            elif role == 'custodian':
                user_id = self.dummyCustodianUser['id']

        if role is not None:
            session = GLSession(user_id, role, 'enabled')
            handler.request.headers['X-Session'] = session.id

        return handler
Beispiel #13
0
            for k, v in request.get('http_request_headers', {}).iteritems():
                http_request_headers[str(k)] = map(str, v)
            self.control_measurement(
                http_url=str(request['http_request']),
                include_http_responses=include_http_responses,
                http_request_headers=http_request_headers,
                socket_list=request['tcp_connect'],
                invalid_sockets=invalid_sockets
            )
        except HTTPError:
            raise
        except Exception as exc:
            log.msg("Got invalid request")
            log.exception(exc)
            raise HTTPError(400, 'invalid request')

class WebConnectivityStatus(RequestHandler):
    def get(self):
        self.write({"status": "ok"})


HTTPRandomPageHelper = Application([
    # XXX add regexps here
    (r"/(.*)/(.*)", HTTPRandomPage)
], log_function=log_function)

WebConnectivityHelper = Application([
    (r"/status", WebConnectivityStatus),
    (r"/", WebConnectivity)
], log_function=log_function)
Beispiel #14
0
    def log_request(self, handler):
        if getattr(handler, 'suppress_request_log', False):
            # The handler doesn't want to be logged, so we're done.
            return

        return Application.log_request(self, handler)
Beispiel #15
0
class WebPlugin(PluginObject):
    """
    Web plugin object
    """

    api_log = None
    api_keys = None

    api_key_data = {}
    config = {}
    data = {}

    namespace = {}  # Global, not used right now

    handlers = {}  # Cyclone handlers

    interface = ""  # Listening interface
    listen_port = 8080

    running = False

    application = None  # Cyclone application
    port = None  # Twisted's server port
    storage = None
    template_loader = None

    navbar_items = {}

    ## Stuff plugins might find useful

    commands = None
    events = None
    packages = None
    plugins = None
    sessions = None
    stats = None

    ## Internal(ish) functions

    def setup(self):
        self.storage = StorageManager()

        try:
            self.config = self.storage.get_file(self, "config", YAML,
                                                "plugins/web.yml")
            self.logger.debug("Config loaded")
        except Exception:
            self.logger.exception(_("Error loading configuration"))
            self._disable_self()
            return
        if not self.config.exists:
            self.logger.error(_("Unable to find config/plugins/web.yml"))
            self._disable_self()
            return

        try:
            self.data = self.storage.get_file(self, "data", JSON,
                                              "plugins/web/data.json")
            self.logger.debug("Data loaded")
        except Exception:
            self.logger.exception("Error loading data file!")
            return self._disable_self()

        try:
            _sessions = self.storage.get_file(self, "data", JSON,
                                              "plugins/web/sessions.json")
            self.logger.debug("Sessions loaded")
        except Exception:
            self.logger.exception("Error loading sessions file!")
            return self._disable_self()

        try:
            self.api_log = open("logs/api.log", "w")
        except Exception:
            self.logger.exception("Unable to open api log file!")
            return self._disable_self()

        try:
            self.api_key_data = self.storage.get_file(
                self, "data", JSON, "plugins/web/apikeys.json"
            )
            self.logger.debug("Sessions loaded")
        except Exception:
            self.logger.exception("Error loading API keys!")
            return self._disable_self()

        try:
            self.api_log = open("logs/api.log", "w")
        except Exception:
            self.logger.exception("Unable to open api log file!")
            return self._disable_self()

        self.config.add_callback(self.restart)
        self.data.add_callback(self.restart)

        # Index page

        self.add_handler(r"/", "plugins.web.routes.index.Route")

        # Login-related

        self.add_handler(r"/login", "plugins.web.routes.login.Route")
        self.add_handler(r"/logout", "plugins.web.routes.logout.Route")
        self.add_handler(
            r"/login/reset",
            "plugins.web.routes.login-reset.Route"
        )

        # Accounts-related

        self.add_handler(r"/account", "plugins.web.routes.account.index.Route")
        self.add_handler(
            r"/account/password/change",
            "plugins.web.routes.account.password.change.Route"
        )
        self.add_handler(
            r"/account/apikeys/create",
            "plugins.web.routes.account.apikeys.create.Route"
        )
        self.add_handler(
            r"/account/apikeys/delete",
            "plugins.web.routes.account.apikeys.delete.Route"
        )
        self.add_handler(
            r"/account/users/logout",
            "plugins.web.routes.account.users.logout.Route"
        )

        # Admin-related

        self.add_handler(
            r"/admin",
            "plugins.web.routes.admin.index.Route"
        )
        self.add_handler(
            r"/admin/files",
            "plugins.web.routes.admin.files.Route"
        )
        self.add_handler(
            r"/admin/files/(config|data)/(.*)",
            "plugins.web.routes.admin.file.Route"
        )
        self.add_handler(
            r"/api/admin/get_stats",
            "plugins.web.routes.api.admin.get_stats.Route"
        )

        self.add_navbar_entry("admin", "/admin", "settings")

        # API routes

        self.add_api_handler(
            r"/plugins/web/get_username",
            "plugins.web.routes.api.plugins.web.get_username.Route"
        )

        # Stuff routes might find useful

        self.api_keys = APIKeys(self, self.api_key_data)
        self.commands = CommandManager()
        self.events = EventManager()
        self.packages = Packages(False)
        self.plugins = PluginManager()
        self.sessions = Sessions(self, _sessions)
        self.stats = Stats()

        # Load 'er up!

        r = self.load()

        if not r:
            self._disable_self()
            return

        if not self.factory_manager.running:
            self.events.add_callback(
                "ReactorStarted", self, self.start, 0
            )
        else:
            self.start()

    def load(self):
        if "secret" not in self.data:
            self.logger.warn("Generating secret. DO NOT SHARE IT WITH ANYONE!")
            self.logger.warn("It's stored in data/plugins/web/data.json - "
                             "keep this file secure!")
            with self.data:
                self.data["secret"] = mkpasswd(60, 20, 20, 20)

        self.template_loader = TemplateLoader(self)

        if self.config.get("output_requests", True):
            log_function = self.log_request
        else:
            log_function = self.null_log

        self.application = Application(
            list(self.handlers.items()),  # Handler list

            ## General settings
            xheaders=True,
            log_function=log_function,
            gzip=True,  # Are there browsers that don't support this now?
            # error_handler=ErrorHandler,

            ## Security settings
            cookie_secret=self.data["secret"],
            login_url="/login",

            ## Template settings
            template_loader=self.template_loader,

            ## Static file settings
            static_path="web/static"
        )

        if self.config.get("hosted", False):
            hosted = self.config["hosted"]

            if isinstance(hosted, dict):
                self.interface = os.environ.get(hosted["hostname"], False)
                self.port = os.environ.get(hosted["port"], False)

                if not self.interface:
                    self.logger.error(
                        "Unknown env var: %s" % hosted["hostname"]
                    )
                    return False
                if not self.port:
                    self.logger.error(
                        "Unknown env var: %s" % hosted["port"]
                    )
                    return False
            else:
                if hosted in ["openshift"]:
                    self.interface = os.environ.get("OPENSHIFT__IP", False)
                    self.port = os.environ.get("OPENSHIFT__PORT", False)

                    if not self.interface:
                        self.logger.error(
                            "Unknown env var: OPENSHIFT__IP - Are you on "
                            "OpenShift?"
                        )
                        return False
                    if not self.port:
                        self.logger.error(
                            "Unknown env var: OPENSHIFT__PORT - Are you on "
                            "OpenShift?"
                        )
                        return False
                else:
                    self.logger.error("Unknown hosted service: %s" % hosted)
                    return False

        else:
            if self.config.get("hostname", "0.0.0.0").strip() == "0.0.0.0":
                self.interface = ""
            else:
                self.interface = self.config.get("hostname")

            self.listen_port = self.config.get("port", 8080)

        return True

    def start(self, _=None):
        self.stats.start()

        self.port = reactor.listenTCP(
            self.listen_port, self.application, interface=self.interface
        )

        self.logger.info("Server started")
        self.running = True

        self.events.run_callback(
            "Web/ServerStartedEvent",
            ServerStartedEvent(self, self.application)
        )

    def stop(self):
        self.application.doStop()
        d = self.port.stopListening()

        d.addCallback(lambda _: self.logger.info("Server stopped"))
        d.addCallback(lambda _: setattr(self, "running", False))
        d.addCallback(lambda _: self.events.run_callback(
            "Web/ServerStopped", ServerStoppedEvent(self)
        ))

        d.addErrback(lambda f: self.logger.error("Failed to stop: %s" % f))

        self.stats.stop()

        return d

    def restart(self):
        d = self.stop()

        d.addCallback(lambda _: [self.load(), self.start()])

    def deactivate(self):
        d = self.stop()

        self.handlers.clear()
        self.navbar_items.clear()

        return d

    def log_request(self, request):
        log = self.logger.info

        status_code = request.get_status()

        if status_code >= 500:
            log = self.logger.error
        elif status_code >= 400:
            log = self.logger.warn

        path = request.request.path

        # Check if this is an API method and hide the key if so

        matched = re.match(r"/api/v[0-9]/([a-zA-Z0-9]+)/.*", path)

        if matched:
            key = matched.groups()[0]
            user = self.api_keys.get_username(key)

            if user:
                path = path.replace(key, "<API: %s>" % user)
            else:
                path = path.replace(key, "<API: Invalid key>")

        log(
            "[%s] %s %s -> HTTP %s"
            % (
                request.request.remote_ip,
                request.request.method,
                path,
                request.get_status()
            )
        )

    def null_log(self, *args, **kwargs):
        pass

    ## Public API functions

    def add_api_handler(self, pattern, handler, version=1):
        if not pattern.startswith("/"):
            pattern = "/%s" % pattern
        pattern = "/api/v%s/([A-Za-z0-9]+)%s" % (version, pattern)

        return self.add_handler(pattern, handler)

    def add_handler(self, pattern, handler):
        self.logger.debug("Adding route: %s -> %s" % (pattern, handler))

        if pattern in self.handlers:
            self.logger.debug("Route already exists.")
            return False

        self.handlers[pattern] = handler

        if self.application is not None:
            self.application.add_handlers(r".*$", [(pattern, handler)])

        self.logger.debug("Handlers list: %s" % list(self.handlers.values()))

    def add_navbar_entry(self, title, url, icon="question"):
        if title in self.navbar_items:
            return False
        self.logger.debug("Adding navbar entry: %s -> %s" % (title, url))
        self.navbar_items[title] = {"url": url, "active": False, "icon": icon}
        return True

    def check_permission(self, perm, session=None):
        if session is None:
            username = None
        elif isinstance(session, str) or isinstance(session, unicode):
            username = session
        else:
            username = session["username"]

        return self.commands.perm_handler.check(
            perm, username, "web", "plugin-web"
        )

    def remove_api_handlers(self, *names, **kwargs):
        """
        :param names:
        :param version:
        :return:
        """

        version = kwargs.get("version", 1)
        patterns = []

        for pattern in names:
            if not pattern.startswith("/"):
                pattern = "/%s" % pattern
            pattern = "/api/v%s/([A-Za-z0-9]+)%s" % (version, pattern)

            patterns.append(pattern)

        return self.remove_handlers(*patterns)

    def remove_handlers(self, *names):
        found = False

        for name in names:
            if name in self.handlers:
                found = True
                del self.handlers[name]

        if found:
            self.restart()

    def write_api_log(self, address, key, username, message):
        self.api_log.write(
            "%s | %s (%s) | %s\n" % (address, key, username, message)
        )
Beispiel #16
0
    selected by the user.
    /<length>/<keyword>
    XXX this is currently disabled as it is not of use to any test.
    """
    isLeaf = True

    def _gen_random_string(self, length):
        return ''.join(random.choice(string.letters) for x in range(length))

    def genRandomPage(self, length=100, keyword=None):
        data = self._gen_random_string(length / 2)
        if keyword:
            data += keyword
        data += self._gen_random_string(length - length / 2)
        data += '\n'
        return data

    def all(self, length, keyword):
        self.set_header('Content-Disposition',
                        'attachment; filename="%s.txt"' % randomStr(10))
        length = 100
        if length > 100000:
            length = 100000
        self.write(self.genRandomPage(length, keyword))


HTTPRandomPageHelper = Application([
    # XXX add regexps here
    (r"/(.*)/(.*)", HTTPRandomPage)
])
Beispiel #17
0
    def post(self, *arg, **kw):
        method_hack = self.get_arguments('_method')
        if method_hack and method_hack == 'DELETE':
            return self.delete()

        s = json.dumps(self.handle_upload(), separators=(',',':'))

        if 'application/json' in self.request.headers.get('Accept'):
            self.set_header('Content-Type', 'application/json')
        self.write(s)

    def delete(self):
        pass

static_dir = os.path.abspath(os.path.join('..', '..'))
spec = [(r'/server/php', UploadHandler),
        (r'/(.*)', StaticFileHandler, {'path': static_dir}),
        ]

from twisted.internet import reactor
from cyclone.web import Application

application = Application(spec, debug=True)

reactor.listenTCP(listen_port, application)
reactor.run()