Esempio n. 1
0
def update(args, config={}):
    if config == {}:
        config = load_config(args)[0]
    previous_version = parse_version(
        import_module("cherrydoor.__version__").__version__)
    if step_enabled("pip", args):
        pip_update()
    current_version = parse_version(
        import_module("cherrydoor.__version__").__version__)
    database_enabled = step_enabled("database", args)
    if database_enabled:
        from pymongo import MongoClient

        db = MongoClient(
            f"mongodb://{config.get('mongo', {}).get('url', 'localhost:27017')}/{config.get('mongo', {}).get('name', 'cherrydoor')}"
        )[config.get("mongo", {}).get("name", "cherrydoor")]
        database_version = db.settings.find_one({"setting": "version"})
        if database_version == None:
            database_version = previous_version
    config_enabled = step_enabled("config", args)
    if config_enabled:
        config_version = parse_version(str(config.get("version", "")))
    path = find_spec(
        "cherrydoor.cli.update_scripts").submodule_search_locations[0]
    for script_name in iglob(f"{path}/[a-zA-Z0-9]*.*py"):
        update_script = import_module(
            f"cherrydoor.cli.update_scripts.{basename(script_name)[:-3]}")
        script_version = parse_version(update_script.__version__)

        if script_version > previous_version:
            try:
                update_script.update()
            except AttributeError:
                pass
        if database_enabled and script_version > database_version:
            try:
                update_script.update_database(db)
            except AttributeError:
                pass
        if config_enabled and script_version > config_version:
            try:
                update_script.update_config(config)
            except AttributeError:
                pass
Esempio n. 2
0
def cherrydoor():
    parser = argparse.ArgumentParser(prog="cherrydoor",
                                     description="Cherrydoor management")
    parser.add_argument(
        "-v",
        "--version",
        help="Print Cherrydoor version and exit",
        action="version",
        version=f"Cherrydoor {__version__}",
    )
    subparsers = parser.add_subparsers(dest="subcommand")
    install_parser = subparsers.add_parser(
        "install", help="Install some possible requirements")
    install_parser.set_defaults(install_steps_excluded=[],
                                install_steps=[],
                                fail=False)
    install_parser.add_argument(
        "--exit-on-fail",
        help="If any step fails, stop the installer",
        dest="fail",
        action="store_true",
    )
    install_steps_group = install_parser.add_argument_group(
        "steps",
        "installation steps you want to run (if none are selected all will be run)",
    )
    install_steps = {
        "dependencies":
        "install all dependencies that weren't installed with pip",
        "service": "set up a systemd unit file",
        "config": "create a config file",
        "database": "set up MongoDB user, collections, etc.",
        "user": "******",
    }
    for (step, description) in install_steps.items():
        install_steps_group.add_argument(
            f"--{step}",
            dest="install_steps",
            action="append_const",
            const=step,
            help=description,
        )
        install_steps_group.add_argument(
            f"--no-{step}",
            dest="install_steps_excluded",
            action="append_const",
            const=step,
            help=f"don't {description}",
        )
    update_parser = subparsers.add_parser(
        "update", help="update Cherrydoor to the newest version")
    update_parser.set_defaults(update_steps_excluded=[],
                               update_steps=[],
                               fail=False)
    update_parser.add_argument(
        "-d",
        "--dev",
        help="Install latest development version",
        dest="dev",
        action="store_true",
    )
    update_parser.add_argument(
        "-v",
        "--verison",
        help="Install specific version",
        dest="version",
        action="store",
    )
    update_parser.add_argument(
        "--exit-on-fail",
        help="If any step fails, stop the updater",
        dest="fail",
        action="store_true",
    )
    update_steps_group = update_parser.add_argument_group(
        "steps",
        "update steps you want to run (if none are selected all will be run)",
    )
    update_steps = {
        "pip": "install the newest version of Cherrydoor via pip",
        "config": "update your config file",
        "database": "Update database schema and settings",
    }
    for (step, description) in update_steps.items():
        update_steps_group.add_argument(
            f"--{step}",
            dest="update_steps",
            action="append_const",
            const=step,
            help=description,
        )
        update_steps_group.add_argument(
            f"--no-{step}",
            dest="update_steps_excluded",
            action="append_const",
            const=step,
            help=f"don't {description}",
        )

    start_parser = subparsers.add_parser(
        "start",
        help=
        "Explicitly start the server (this action is preformed if no other argument is passed too)",
    )
    add_args(parser)
    add_args(start_parser)
    args = parser.parse_args()
    config, _ = load_config(args)
    log_level = getattr(logging, config.get("log_level", "WARN").upper())
    if not isinstance(log_level, int):
        log_level = logging.WARN
        logging.warn(
            "Invalid log level %s - defaulting to WARN",
            config.get("log_level", "WARN").upper(),
        )
    logging.basicConfig(
        level=log_level,
        format="%(asctime)s:%(name)s:%(levelname)s: %(message)s",
    )
    if args.subcommand == "install":
        from cherrydoor.cli.install import install

        install(args)
    if args.subcommand == "update":
        from cherrydoor.cli.update import update

        update(args)
    # if start argument was passed or no arguments were used, start the server
    if args.subcommand in ["start", None]:
        from cherrydoor.app import setup_app
        from cherrydoor.interface.serial import Serial

        try:
            import uvloop

            uvloop.install()
        except ModuleNotFoundError:
            pass
        loop = asyncio.get_event_loop()
        app = setup_app(loop, config)
        interface = Serial(app["db"], loop)
        app["serial"] = interface
        app.on_startup.append(interface.aiohttp_startup)
        app.on_cleanup.append(interface.cleanup)

        web.run_app(
            app,
            host=config.get("host", "127.0.0.1"),
            port=config.get("port", 5000),
            path=config.get("path", None),
        )
Esempio n. 3
0
def setup_app(loop=asyncio.get_event_loop(), config=load_config()[0]):
    if config.get("sentry_dsn", None):
        sentry_sdk.init(
            dsn=config["sentry_dsn"],
            integrations=[AioHttpIntegration()],
            release=f"cherrydoor@{__version__}",
        )
    # create app
    app = web.Application(loop=loop)
    # make config accessible through the app
    app["config"] = config
    # setup database and add it to the app
    db = init_db(config, loop)
    app["db"] = db
    # create a token generator/validator and add make it accessible through the app
    api_tokens = ApiTokens(app, config.get("secret_key", ""))
    app["api_tokens"] = api_tokens

    app.on_startup.append(setup_db)
    # set up aiohttp-session with aiohttp-session-mongo for storage
    setup_session(
        app,
        MongoStorage(
            db["sessions"],
            max_age=None,
            cookie_name="session_id",
        ),
    )
    # set up aiohttp-security
    setup_security(
        app,
        SessionIdentityPolicy("uid", config.get("max_session_age", 31536000)),
        AuthorizationPolicy(app),
    )
    # set up secure.py
    secure_setup(app)
    app.middlewares.append(set_secure_headers)

    csrf_policy = aiohttp_csrf.policy.FormAndHeaderPolicy(
        CSRF_HEADER_NAME, CSRF_FIELD_NAME
    )
    csrf_storage = aiohttp_csrf.storage.SessionStorage(CSRF_SESSION_NAME)
    aiohttp_csrf.setup(app, policy=csrf_policy, storage=csrf_storage)
    # app.middlewares.append(aiohttp_csrf.csrf_middleware)

    load_and_connect_all_endpoints_from_folder(
        path=f"{os.path.dirname(os.path.realpath(__file__))}/api",
        app=app,
        version_prefix="api/v1",
    )
    redoc_url = "/api/v1/docs"
    setup_redoc(
        app,
        redoc_url=redoc_url,
        description=openapi_description,
        title="Cherrydoor API",
        page_title="Cherrydocs",
        openapi_info=get_openapi_documentation(overrides=openapi_overrides),
        redoc_options=redoc_options,
        contact=openapi_contact,
    )
    app["redoc_url"] = redoc_url
    app.router.add_routes(redoc_routes)
    setup_static_routes(app)

    jinja2_loader = PackageLoader("cherrydoor", "templates")
    setup_jinja2(app, loader=jinja2_loader, auto_reload=True)
    get_env(app).globals["sri"] = sri_for
    get_env(app).globals["csrf_field_name"] = CSRF_FIELD_NAME
    get_env(app).filters["vue"] = vue
    setup_routes(app)
    sio.attach(app)
    app.on_startup.append(setup_socket_tasks)

    return app
Esempio n. 4
0
def get_config():
    from cherrydoor.config import load_config

    config, _ = load_config()
    return config
Esempio n. 5
0
def get_config():
    """Load AttrDict with configuration."""
    from cherrydoor.config import load_config  # pylint: disable=import-outside-toplevel

    config, _ = load_config()
    return config