def __init__(self, opts=None) -> None: super(CreateSwagger, self).__init__(opts) sys.path = ["", ".."] + sys.path[1:] self.info = {"openapi": "3.0.0"} url_patterns = get_settings_variable("URL_PATTERNS") swagger_info = get_settings_variable("SWAGGER") if not swagger_info: raise CraxImproperlyConfigured( "'SWAGGER' variable should" " be defined in configuration file to use Swagger") elif swagger_info.servers is None or swagger_info.basePath is None: raise CraxImproperlyConfigured( "'SWAGGER_HOST' and 'SWAGGER_BASE_PATH' should" " be defined in configuration file to use Swagger") self.base_path = swagger_info.basePath self.swagger_file = f"{BASE_URL}/crax/swagger/static/swagger.json" info = { k: v for k, v in swagger_info.__dict__.items() if k not in ["host", "basePath", "schemes"] } self.info["info"] = info self.info["host"] = swagger_info.host self.info["basePath"] = swagger_info.basePath self.info["servers"] = swagger_info.servers self.info["tags"] = [] self.url_list = list(unpack_urls(url_patterns))
async def login(request: Request, username: str, password: str) -> typing.Union[User, AnonymousUser]: secret = get_settings_variable("SECRET_KEY") signer = itsdangerous.TimestampSigner(str(secret)) max_age = get_settings_variable("SESSION_EXPIRES", default=1209600) cookie_name = get_settings_variable("SESSION_COOKIE_NAME", default="session_id") if not secret: raise CraxImproperlyConfigured( '"SECRET_KEY" variable should be defined to use Authentication backends' ) if hasattr(request, "cookies"): cookies = request.cookies if cookie_name in cookies: session_cookie = cookies[cookie_name] session_cookie = b64decode(session_cookie) user = signer.unsign(session_cookie, max_age=max_age) user = user.decode("utf-8") await set_user(request, username, password, user_pk=int(user.split(":")[1])) else: await set_user(request, username, password) return request.user
def create_password(password: str) -> str: secret = get_settings_variable("SECRET_KEY") if not secret: raise CraxImproperlyConfigured( '"SECRET_KEY" variable should be defined to use Authentication backends' ) secret = secret.encode() hashed = hashlib.pbkdf2_hmac("sha256", password.encode(), secret, 100000) return hashed.hex()
def check_password(hashed: str, password: str) -> bool: secret = get_settings_variable("SECRET_KEY") if not secret: raise CraxImproperlyConfigured( '"SECRET_KEY" variable should be defined to use Authentication backends' ) secret = secret.encode() return hmac.compare_digest( bytearray.fromhex(hashed), hashlib.pbkdf2_hmac("sha256", password.encode(), secret, 100000), )
def csrf_token(): secret_key = get_settings_variable("SECRET_KEY") if secret_key is None: raise CraxImproperlyConfigured( '"SECRET_KEY" string should be defined in settings to use CSRF Protection' ) signer = itsdangerous.TimestampSigner(str(secret_key)) sign = signer.sign(str(int(time.time()))) encoded = b64encode(sign) csrf_key = encoded.decode("utf-8") return csrf_key
def create_session_signer() -> tuple: secret_key = get_settings_variable("SECRET_KEY") if secret_key is None: raise CraxImproperlyConfigured( '"SECRET_KEY" string should be defined in settings to use Crax Sessions' ) signer = itsdangerous.TimestampSigner( str(secret_key), algorithm=itsdangerous.signer.HMACAlgorithm()) max_age = get_settings_variable("SESSION_EXPIRES", default=1209600) cookie_name = get_settings_variable("SESSION_COOKIE_NAME", default="session_id") same_site = get_settings_variable("SAME_SITE_COOKIE_MODE", default="lax") return signer, max_age, cookie_name, same_site
def get_match(self, request: Request) -> Optional[typing.Callable]: scheme = request.scheme handler = None matched = False params = {} for url in self.urls: if isinstance(url, Url): find_path, path = self.create_path(url, request.path) if url.type_ == "re_path": match = re.match(find_path, path) if match: params = match.groupdict() matched = True else: matched, params = self.check_len(url, path) if matched is True and scheme in url.scheme: handler = self.handler request.params = params if url.masquerade is True: if hasattr(handler, "scope"): masqueraded = [ x for x in handler.scope if x == request.path.split("/")[-1] ] if not masqueraded: handler = DefaultError( request, CraxPathNotFound(request.path)) else: handler.template = masqueraded[0] else: handler = DefaultError( request, CraxPathNotFound(request.path)) else: handler = DefaultError( request, CraxImproperlyConfigured( f'{url} should be instance of "Url"'), ) return handler
def check_allowed(self, handler: typing.Callable): errors = None if self.request.user is not None: if hasattr(handler, "login_required"): login_required = handler.login_required if ( hasattr(self.request.user, "pk") and self.request.user.pk == 0 and login_required is True ): errors = { "error_handler": CraxUnauthorized, "error_message": self.request.path, "status_code": 401, } if hasattr(handler, "staff_only"): staff_only = handler.staff_only if self.request.user.is_staff is False and staff_only is True: errors = { "error_handler": CraxForbidden, "error_message": self.request.path, "status_code": 403, } if hasattr(handler, "superuser_only"): superuser_only = handler.superuser_only if self.request.user.is_superuser is False and superuser_only is True: errors = { "error_handler": CraxForbidden, "error_message": self.request.path, "status_code": 403, } if hasattr(handler, "methods") and self.request.scheme in [ "http", "http.request", ]: if self.enable_csrf is True and self.request.method in ["POST", "PATCH"]: if hasattr(handler, "enable_csrf") and handler.enable_csrf is True: if "csrf_token" not in self.request.post: errors = { "error_handler": CraxForbidden, "error_message": "CSRF token missed", "status_code": 403, } elif not self.request.post["csrf_token"]: errors = { "error_handler": CraxForbidden, "error_message": "CSRF token is empty", "status_code": 403, } else: secret_key = get_settings_variable("SECRET_KEY") if secret_key is None: raise CraxImproperlyConfigured( '"SECRET_KEY" string should be defined in settings to use CSRF Protection' ) try: token = self.request.post["csrf_token"] signer = itsdangerous.TimestampSigner(str(secret_key)) max_age = get_settings_variable( "SESSION_EXPIRES", default=1209600 ) session_cookie = b64decode(token) signer.unsign(session_cookie, max_age=max_age) except ( binascii.Error, BadTimeSignature, BadSignature, SignatureExpired, ): errors = { "error_handler": CraxForbidden, "error_message": "CSRF token is incorrect", "status_code": 403, } if not self.request.method: # pragma: no cover errors = { "error_handler": CraxNoMethodGiven, "error_message": handler, "status_code": 500, } elif not handler.methods: errors = { "error_handler": CraxEmptyMethods, "error_message": handler, "status_code": 500, } else: handler.methods += ["HEAD", "OPTIONS"] if self.request.method not in handler.methods: errors = { "error_handler": CraxMethodNotAllowed, "error_message": handler, "status_code": 405, } return errors
def __init__(self, opts: typing.List[typing.Union[tuple]], **kwargs) -> None: super(DataBaseCommands, self).__init__(opts) self.kwargs = kwargs self.db_map = {} self.db_keys = {} self.db_tables = [] self.sorted_tables = [] settings = os.environ.get("CRAX_SETTINGS", None) self.configuration = get_settings(settings=settings) required_params = ["BASE_URL", "APPLICATIONS", "DATABASES"] for x in required_params: if not hasattr(self.configuration, x): raise CraxImproperlyConfigured( f"Missed required parameter {x}") self.project_applications = self.configuration.APPLICATIONS self.project_url = self.configuration.BASE_URL self.databases = self.configuration.DATABASES if not isinstance(self.databases, dict): raise CraxImproperlyConfigured( "DATABASES parameter should be a dict") elif settings is not None and "default" not in self.databases: raise CraxImproperlyConfigured( 'DATABASES dictionary should contain "default" database') self.default_connection = None self.db_name = None self.config_file = "alembic.ini" self.alembic_dir = "alembic_env" self.migrations_dir = "migrations" db = self.get_option("database") if db is None: self.set_database("default") else: self.set_database(db) if hasattr(self.configuration, "MIDDLEWARE"): middleware = self.configuration.MIDDLEWARE check_auth = [ x for x in middleware if x.split(".")[-1] == "SessionMiddleware" or x.split(".")[-1] == "AuthMiddleware" ] if len(check_auth) == 2 and self.db_name == "default": self.project_applications.append("crax.auth") apps = self.get_option("apps") self.applications = [] if apps: applications = [ x for x in self.project_applications if x in apps or x == "crax.auth" ] else: applications = self.project_applications for app in applications: if app != "crax.auth": if "models.py" in os.listdir(f'{self.project_url}/{app}'): content = open(f'{self.project_url}/{app}/models.py', "r").read() if content: self.applications.append(app) else: self.applications.append(app) if self.db_name != "default" and "crax.auth" in self.applications: self.applications.remove("crax.auth") self.config = self.check_config() if self.config is not None: self.config.set_main_option( "version_locations", " ".join([ self.create_version_dir(app) for app in self.project_applications ]), ) os.environ["CRAX_DB_CONNECTION"] = self.default_connection os.environ["CRAX_FULL_METADATA"] = " ".join(self.project_applications)