def postgres_handler(sketch: Sketch): if sketch.database == "postgres": sketch.add_requirements("psycopg2") handle_sql_db(sketch) sketch.settings["production"][ "SQLALCHEMY_DATABASE_URI" ] = "postgres://<user>:<password>@<server_ip>/MY_DATABASE" return True
def mysql_handler(sketch: Sketch): if sketch.database == "mysql": sketch.add_requirements("mysqlclient") handle_sql_db(sketch) sketch.settings["production"][ "SQLALCHEMY_DATABASE_URI" ] = "mysql+mysqldb://<user>:<password>@<server_ip>/MY_DATABASE" return True
def handle_mongo_security(sketch: Sketch): if sketch.database == "mongodb" and sketch.auth_framework == "security": sketch.write_template( "user_mongo_security_tpl", templates.models, pjoin(sketch.app_folder, "models", "user.py"), ) return True
def handle_sql_security(sketch: Sketch): if (sketch.database in ["sqlite", "postgres", "mysql"] and sketch.auth_framework == "security"): sketch.write_template( "user_sql_security_tpl", templates.models, pjoin(sketch.app_folder, "models", "user.py"), ) return True
def handle_jwt_mongo(sketch: Sketch): if (sketch.database == "mongodb" and sketch.auth_framework == "none" and sketch.api_auth_framework != "none"): sketch.write_template( "user_mongo_noauth_jwt_tpl", templates.models, pjoin(sketch.app_folder, "models", "user.py"), ) return True
def handle_jwt_sql(sketch: Sketch): if (sketch.database in ["sqlite", "postgres", "mysql"] and sketch.auth_framework == "none" and sketch.api_auth_framework != "none"): sketch.write_template( "user_sql_noauth_jwt_tpl", templates.models, pjoin(sketch.app_folder, "models", "user.py"), ) return True
def handle_mongo_noauth(sketch: Sketch): if (sketch.database == "mongodb" and sketch.auth_framework == "none" and sketch.api_auth_framework == "none"): sketch.write_template( "mongo_noauth_tpl", templates.commands, pjoin( sketch.app_folder, "commands", "__init__.py", ), )
def handle_mongo_security(sketch: Sketch): if sketch.database == "mongodb" and sketch.auth_framework == "security": sketch.write_template( "mongo_security_tpl", templates.commands, pjoin( sketch.app_folder, "commands", "__init__.py", ), ) return True
def restx_handler(sketch: Sketch): if sketch.api_framework == "restx": sketch.add_requirements(reqs.FLASK_RESTX) os.makedirs(pjoin(sketch.app_folder, "api", "resources", "examples")) open( pjoin( sketch.app_folder, "api", "resources", "examples", "__init__.py", ), "a", ).close() if sketch.api_auth_framework == "jwt_extended": sketch.write_template( "api_init_restx_jwtext_tpl", templates.api, pjoin(sketch.app_folder, "api", "__init__.py"), ) else: sketch.write_template( "api_init_restx_noauth_tpl", templates.api, pjoin(sketch.app_folder, "api", "__init__.py"), ) if sketch.api_auth_framework == "none": resource_tpl = "api_examples_restx_pet_tpl" else: resource_tpl = "api_examples_restx_pet_auth_tpl" sketch.write_template( resource_tpl, templates.api.resources.examples, pjoin(sketch.app_folder, "api", "resources", "examples", "pet.py"), ) if sketch.database == "mongodb": example_tpl_model = "pet_mongo_tpl" else: example_tpl_model = "pet_sql_tpl" sketch.write_template( example_tpl_model, templates.models.examples, pjoin(sketch.app_folder, "models", "examples", "pet.py"), ) return True
def handle_sql_noauth(sketch: Sketch): if (sketch.database in ["sqlite", "postgres", "mysql"] and sketch.auth_framework == "none" and sketch.api_auth_framework == "none"): sketch.write_template( "sql_noauth_tpl", templates.commands, pjoin( sketch.app_folder, "commands", "__init__.py", ), )
def handle_sql_security(sketch: Sketch): if (sketch.database in ["sqlite", "postgres", "mysql"] and sketch.auth_framework == "security"): sketch.write_template( "sql_security_tpl", templates.commands, pjoin( sketch.app_folder, "commands", "__init__.py", ), ) return True
def handle_debugtoolbar(sketch: Sketch): sketch.add_requirements(reqs.FLASK_DEBUGTOOLBAR, dev=True) sketch.add_extensions("debugtoolbar", dev=True) sketch.settings["development"]["DEBUG_TB_INTERCEPT_REDIRECTS"] = False if sketch.database == "mongodb": sketch.settings["development"]["DEBUG_TB_PANELS"] = [ "flask_debugtoolbar.panels.versions.VersionDebugPanel", "flask_debugtoolbar.panels.timer.TimerDebugPanel", "flask_debugtoolbar.panels.headers.HeaderDebugPanel", "flask_debugtoolbar.panels.request_vars.RequestVarsDebugPanel", "flask_debugtoolbar.panels.template.TemplateDebugPanel", "flask_debugtoolbar.panels.route_list.RouteListDebugPanel", "flask_debugtoolbar.panels.logger.LoggingPanel", "flask_debugtoolbar.panels.profiler.ProfilerDebugPanel", "flask_debugtoolbar.panels.config_vars.ConfigVarsDebugPanel", ] if sketch.config_framework != "dynaconf": sketch.write_template( "ext_debugtoolbar_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "debugtoolbar.py",), )
def handle_mongo_jwt_default(sketch: Sketch): if (sketch.database == "mongodb" and sketch.auth_framework == "none" and sketch.api_auth_framework != "none"): print("é vdd esse bilete") sketch.write_template( "mongo_default_tpl", templates.commands, pjoin( sketch.app_folder, "commands", "__init__.py", ), ) return True
def none_handler(sketch: Sketch): if sketch.api_auth_framework == "none": sketch.template_args["API_RBAC_IMPORT"] = "" sketch.template_args["ROLES_REQUIRED_DECORATOR"] = "" sketch.template_args["ROLES_ACCEPTED_DECORATOR"] = "" if sketch.api_framework == "none" or sketch.api_framework == "smorest": sketch.write_template( "api_init_noauth_tpl", templates.api, pjoin(sketch.app_folder, "api", "__init__.py"), ) return True
def __call__(self, sketch: Sketch): for handler in self.handlers: r = handler(sketch) if r: if not handler.__name__ == "none_handler": sketch.write_template( "models_auth_tpl", templates.models, pjoin( sketch.app_folder, "models", "__init__.py", ), ) return r
def none_handler(sketch: Sketch): if sketch.auth_framework == "none": sketch.write_template( "site_web_only_init_tpl", templates.site, pjoin(sketch.app_folder, "site", "__init__.py"), ) sketch.write_template( "site_web_only_views_tpl", templates.site, pjoin(sketch.app_folder, "site", "views.py"), ) return True
def sqlite_handler(sketch: Sketch): if sketch.database == "sqlite": handle_sql_db(sketch) sketch.settings["production"][ "SQLALCHEMY_DATABASE_URI" ] = "sqlite:///production_db.sqlite3" return True
def handle_sql_default(sketch: Sketch): if sketch.database in [ "sqlite", "postgres", "mysql", ] and sketch.auth_framework not in ["security", "none"]: sketch.write_template( "sql_default_tpl", templates.commands, pjoin( sketch.app_folder, "commands", "__init__.py", ), ) return True
def create_project(args: Namespace, answers: dict): pf = pjoin(str(pathlib.Path().absolute()), args.project_name) apf = pjoin( str(pathlib.Path().absolute()), args.project_name, args.project_name.replace("-", "_"), ) sketch = Sketch(pf, apf, answers, args) make_commom(sketch) sketch.settings["default"]["DEBUG"] = False sketch.settings["development"]["DEBUG"] = True sketch.secrets["default"]["SECRET_KEY"] = random_string(length=64) app_type_handler(sketch) database_handler(sketch) auth_handler(sketch) if sketch.have_api: api_framework_handler(sketch) api_auth_handler(sketch) handle_features(sketch) config_handler(sketch) # if args.e: sketch.blueprints.extend(["examples"]) make_app(sketch) make_requirements(sketch) make_template_args(sketch) cleanup(sketch) if args.v: print("\ncreating virtual environment...") os.system(f"python -m venv {pf}/.venv") print("\n\nAll done!")
def handle_cors(sketch: Sketch): sketch.add_requirements(reqs.FLASK_CORS) sketch.add_extensions("cors") sketch.write_template( "ext_cors_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "cors.py",), )
def handle_migrate(sketch: Sketch): sketch.add_requirements("flask-migrate") sketch.add_extensions("migrate") sketch.write_template( "ext_migrate_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "migrate.py"), )
def handle_debugtoolbar(sketch: Sketch): sketch.add_requirements("flask-debugtoolbar", dev=True) sketch.add_extensions("debugtoolbar", dev=True) sketch.settings["development"]["DEBUG_TB_INTERCEPT_REDIRECTS"] = False if sketch.config_framework != "dynaconf": sketch.write_template( "ext_debugtoolbar_tpl", templates.ext, pjoin( sketch.app_folder, "ext", "debugtoolbar.py", ), )
def dynaconf_handler(sketch: Sketch): if sketch.config_framework == "dynaconf": sketch.add_requirements("dynaconf") settings_toml = sort_settings(sketch.settings) secrets_toml = sort_settings(sketch.secrets) try: sketch.dev_extensions.remove("debugtoolbar") settings_toml["development"]["EXTENSIONS"] = [ "flask_debugtoolbar:DebugToolbarExtension", "dynaconf_merge_unique", ] except ValueError: settings_toml["development"]["EXTENSIONS"] = [ "dynaconf_merge_unique" ] for extension in sketch.extensions: ext = extension.rsplit(".", 1)[-1] aux = "" if len(extension.rsplit(".", 1)) > 1: aux = "." + extension.rsplit(".", 1)[0] settings_toml["default"]["EXTENSIONS"].append( "{}.ext{}.{}:init_app".format(sketch.app_folder_name, aux, ext)) with open(pjoin(sketch.project_folder, "settings.toml"), "w") as f: toml.dump(settings_toml, f, encoder=FlaskSketchTomlEncoder()) with open(pjoin(sketch.project_folder, ".secrets.toml"), "w") as f: toml.dump(secrets_toml, f, encoder=FlaskSketchTomlEncoder()) sketch.write_template( "config_dynaconf_tpl", templates.config, pjoin( sketch.app_folder, "config", "__init__.py", ), ) sketch.write_template( "app_dynaconf_conf_tpl", templates.app, pjoin(sketch.app_folder, "app.py"), ) return True
def create_project(args: Namespace, answers: dict): pf = pjoin(str(pathlib.Path().absolute()), args.project_name) apf = pjoin( str(pathlib.Path().absolute()), args.project_name, args.project_name.replace("-", "_"), ) sketch = Sketch(pf, apf, answers, args) make_commom(sketch) sketch.settings["default"]["DEBUG"] = False sketch.settings["development"]["DEBUG"] = True sketch.secrets["default"]["SECRET_KEY"] = random_string(length=64) # TODO find a better place for this below sketch.template_args[ "ADMIN_USER_ROLE_IMPORT"] = "from {}.models import User, Role".format( sketch.app_folder_name) app_type_handler(sketch) database_handler(sketch) models_handler(sketch) auth_handler(sketch) if sketch.have_api: api_framework_handler(sketch) api_auth_handler(sketch) commands_handler(sketch) handle_features(sketch) config_handler(sketch) # if args.e: sketch.blueprints.extend(["examples"]) make_app(sketch) make_requirements(sketch) make_template_args(sketch) cleanup(sketch) if args.v: print("\nCreating virtual environment...") os.system(f"python3 -m venv {pf}/.venv") print("\n\nAll done!")
def basicauth_web_handler(sketch: Sketch): if sketch.auth_framework == "basicauth": sketch.add_requirements("flask-basicAuth") sketch.secrets["default"]["BASIC_AUTH_PASSWORD"] = "******" sketch.secrets["default"]["BASIC_AUTH_PASSWORD"] = random_string() return True
def smorest_handler(sketch: Sketch): if sketch.api_framework == "smorest": sketch.add_requirements(reqs.FLASK_SMOREST) sketch.settings["default"]["API_TITLE"] = sketch.project_name sketch.settings["default"]["API_VERSION"] = "v1" sketch.settings["default"]["OPENAPI_VERSION"] = "3.0.2" sketch.settings["default"]["OPENAPI_JSON_PATH"] = "api-spec.json" sketch.settings["default"]["OPENAPI_URL_PREFIX"] = "/openapi" sketch.settings["default"]["OPENAPI_REDOC_PATH"] = "/redoc" sketch.settings["default"][ "OPENAPI_REDOC_URL" ] = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js" # noqa sketch.settings["default"]["OPENAPI_SWAGGER_UI_PATH"] = "/swagger-ui" sketch.settings["default"][ "OPENAPI_SWAGGER_UI_URL" ] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist/" sketch.add_extensions("api") os.makedirs(pjoin(sketch.app_folder, "api", "resources", "examples")) open( pjoin( sketch.app_folder, "api", "resources", "examples", "__init__.py", ), "a", ).close() if sketch.api_auth_framework == "jwt_extended": sketch.write_template( "api_init_jwt_extended_tpl", templates.api, pjoin(sketch.app_folder, "api", "__init__.py"), ) sketch.write_template( "ext_api_smorest_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "api.py"), ) if sketch.api_auth_framework == "none": resource_tpl = "api_example_smorest_pet_tpl" else: resource_tpl = "api_example_smorest_pet_auth_tpl" sketch.write_template( resource_tpl, templates.api.resources.examples, pjoin(sketch.app_folder, "api", "resources", "examples", "pet.py"), ) if sketch.database == "mongodb": example_tpl_model = "pet_mongo_tpl" else: example_tpl_model = "pet_sql_tpl" sketch.write_template( example_tpl_model, templates.models.examples, pjoin(sketch.app_folder, "models", "examples", "pet.py"), ) return True
def handle_admin(sketch: Sketch): sketch.add_requirements("flask-admin") sketch.add_extensions("admin") sketch.settings["default"]["ADMIN_TEMPLATE_MODE"] = "bootstrap3" sketch.settings["development"]["ADMIN_NAME"] = "{} (Dev)".format( snake_to_camel(sketch.project_name)) sketch.settings["testing"]["ADMIN_NAME"] = "{} (Testing)".format( snake_to_camel(sketch.project_name)) sketch.settings["production"]["ADMIN_NAME"] = snake_to_camel( sketch.project_name) # TODO refact this part to not use a lot of if statements if sketch.auth_framework == "security": sketch.write_template( "ext_admin_security_tpl", templates.ext.admin, pjoin( sketch.app_folder, "ext", "admin", "__init__.py", ), ) if sketch.auth_framework == "login": sketch.write_template( "ext_admin_login_tpl", templates.ext.admin, pjoin( sketch.app_folder, "ext", "admin", "__init__.py", ), ) if sketch.auth_framework == "none": sketch.add_requirements("flask-basicauth") sketch.add_extensions("admin.basic_auth") sketch.secrets["default"]["BASIC_AUTH_USERNAME"] = "******" sketch.secrets["default"]["BASIC_AUTH_PASSWORD"] = str(uuid4()) sketch.write_template( "ext_basicauth_tpl", templates.ext.admin, pjoin( sketch.app_folder, "ext", "admin", "basic_auth.py", ), ) sketch.write_template( "ext_admin_basicauth_tpl", templates.ext.admin, pjoin( sketch.app_folder, "ext", "admin", "__init__.py", ), )
def login_handler(sketch: Sketch): if sketch.auth_framework == "login": sketch.add_requirements("flask-login", "argon2-cffi", "flask-wtf", "email_validator") sketch.add_extensions("auth") sketch.write_template( "commands_default_tpl", templates.commands, pjoin( sketch.app_folder, "commands", "__init__.py", ), ) sketch.write_template( "ext_login_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "auth.py"), ) sketch.write_template( "models_login_tpl", templates.models, pjoin(sketch.app_folder, "models", "user.py"), ) sketch.write_template( "examples_login_auth_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "auth_examples.py", ), ) sketch.write_template( "examples_init_auth_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "__init__.py", ), ) sketch.write_template( "utils_security_login_rbac_tpl", templates.utils.security, pjoin(sketch.app_folder, "utils", "security", "rbac.py"), ) sketch.write_template( "utils_security_password_hasher_tpl", templates.utils.security, pjoin(sketch.app_folder, "utils", "security", "password_hasher.py"), mode="w", ) sketch.write_template( "site_login_auth_views_tpl", templates.site, pjoin( sketch.app_folder, "site", "views.py", ), ) sketch.write_template( "site_login_auth_forms_tpl", templates.site, pjoin( sketch.app_folder, "site", "forms.py", ), ) sketch.write_template( "site_login_init_tpl", templates.site, pjoin( sketch.app_folder, "site", "__init__.py", ), ) os.makedirs(pjoin(sketch.app_folder, "site", "templates")) sketch.write_template( "login_html_tpl", templates.site.templates, pjoin( sketch.app_folder, "site", "templates", "login.html", ), ) sketch.write_template( "register_html_tpl", templates.site.templates, pjoin( sketch.app_folder, "site", "templates", "register.html", ), ) sketch.write_template( "dashboard_html_tpl", templates.site.templates, pjoin( sketch.app_folder, "site", "templates", "dashboard.html", ), ) return True
def handle_caching(sketch: Sketch): sketch.add_requirements("flask-caching") sketch.settings["development"]["CACHE_TYPE"] = "simple" sketch.settings["testing"]["CACHE_TYPE"] = "simple" sketch.settings["production"]["CACHE_TYPE"] = "simple" sketch.add_extensions("caching") sketch.write_template( "ext_caching_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "caching.py"), ) sketch.write_template( "examples_caching_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "caching_examples.py", ), ) sketch.write_template( "examples_init_caching_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "__init__.py", ), )
def handle_limiter(sketch: Sketch): sketch.add_requirements("flask-limiter") sketch.settings["default"]["RATELIMIT_DEFAULT"] = "200 per day;50 per hour" sketch.settings["default"]["RATELIMIT_ENABLED"] = True sketch.settings["development"]["RATELIMIT_ENABLED"] = False sketch.add_extensions("limiter") sketch.write_template( "ext_limiter_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "limiter.py"), ) sketch.write_template( "examples_limiter_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "limiter_examples.py", ), ) sketch.write_template( "examples_init_limiter_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "__init__.py", ), )