Example #1
0
 def test_duration_from_string_fails(self):
     """
     This test verifies that the duration_from_string method raises a
     ConfiguationError exception if there was a problem parsing the string
     """
     with pytest.raises(ConfigurationError):
         duration_from_string('12x1y1z')
     with pytest.raises(ConfigurationError):
         duration_from_string('')
Example #2
0
    def test_duration_from_string_success(self):
        """
        This test verifies that the duration_from_string method can be used to
        parse a duration from a string with expected formats
        """
        expected_duration = pendulum.duration(days=12, hours=1, seconds=1)
        computed_duration = duration_from_string('12d1h1s')
        assert computed_duration == expected_duration

        expected_duration = pendulum.duration(months=1, hours=2, minutes=3)
        computed_duration = duration_from_string('1 Month 2 Hours 3 minutes')
        assert computed_duration == expected_duration

        expected_duration = pendulum.duration(days=1, minutes=2, seconds=3)
        computed_duration = duration_from_string('1day,2min,3sec')
        assert computed_duration == expected_duration

        expected_duration = pendulum.duration(months=1, minutes=2)
        computed_duration = duration_from_string('1mo,2m')
        assert computed_duration == expected_duration
Example #3
0
    def init_app(
        self,
        app=None,
        user_class=None,
        token_store_class=None,
        is_blacklisted=None,
        encode_jwt_token_hook=None,
        refresh_jwt_token_hook=None,
    ):
        """
        Initializes the Praetorian extension

        :param: app:                    The flask app to bind this
                                        extension to
        :param: user_class:             The class used to interact with
                                        user data
        :param: token_store_class:      The class used to interact with
                                        token store data
        :param: is_blacklisted:         A method that may optionally be
                                        used to check the token against
                                        a blacklist when access or refresh
                                        is requested should take the jti
                                        for the token to check as a single
                                        argument. Returns True if the jti is
                                        blacklisted, False otherwise. By
                                        default, always returns False.
        :param encode_jwt_token_hook:   A method that may optionally be
                                        called right before an encoded jwt
                                        is generated. Should take
                                        payload_parts which contains the
                                        ingredients for the jwt.
        :param refresh_jwt_token_hook:  A method that may optionally be called
                                        right before an encoded jwt is
                                        refreshed. Should take payload_parts
                                        which contains the ingredients for
                                        the jwt.
        """
        PraetorianError.require_condition(
            app.config.get('SECRET_KEY') is not None,
            "There must be a SECRET_KEY app config setting set",
        )

        self.roles_disabled = app.config.get(
            'PRAETORIAN_ROLES_DISABLED',
            DEFAULT_ROLES_DISABLED,
        )

        self.hash_autoupdate = app.config.get(
            'PRAETORIAN_HASH_AUTOUPDATE',
            DEFAULT_HASH_AUTOUPDATE,
        )

        self.hash_autotest = app.config.get(
            'PRAETORIAN_HASH_AUTOTEST',
            DEFAULT_HASH_AUTOTEST,
        )

        self.pwd_ctx = CryptContext(
            schemes=app.config.get(
                'PRAETORIAN_HASH_ALLOWED_SCHEMES',
                DEFAULT_HASH_ALLOWED_SCHEMES,
            ),
            default=app.config.get(
                'PRAETORIAN_HASH_SCHEME',
                DEFAULT_HASH_SCHEME,
            ),
            deprecated=app.config.get(
                'PRAETORIAN_HASH_DEPRECATED_SCHEMES',
                DEFAULT_HASH_DEPRECATED_SCHEMES,
            ),
        )

        valid_schemes = self.pwd_ctx.schemes()
        PraetorianError.require_condition(
            self.hash_scheme in valid_schemes or self.hash_scheme is None,
            "If {} is set, it must be one of the following schemes: {}".format(
                'PRAETORIAN_HASH_SCHEME',
                valid_schemes,
            ),
        )

        self.user_class = self._validate_user_class(user_class)
        #self.token_class = self._validate_token_class(token_class)
        self.token_store_class = token_store_class
        self.is_blacklisted = is_blacklisted or (lambda t: False)
        self.encode_jwt_token_hook = encode_jwt_token_hook
        self.refresh_jwt_token_hook = refresh_jwt_token_hook

        self.encode_key = app.config['SECRET_KEY']
        self.allowed_algorithms = app.config.get(
            'JWT_ALLOWED_ALGORITHMS',
            DEFAULT_JWT_ALLOWED_ALGORITHMS,
        )
        self.encode_algorithm = app.config.get(
            'JWT_ALGORITHM',
            DEFAULT_JWT_ALGORITHM,
        )
        self.access_lifespan = app.config.get(
            'JWT_ACCESS_LIFESPAN',
            DEFAULT_JWT_ACCESS_LIFESPAN,
        )
        self.refresh_lifespan = app.config.get(
            'JWT_REFRESH_LIFESPAN',
            DEFAULT_JWT_REFRESH_LIFESPAN,
        )
        self.reset_lifespan = app.config.get(
            'JWT_RESET_LIFESPAN',
            DEFAULT_JWT_RESET_LIFESPAN,
        )
        self.jwt_places = app.config.get(
            'JWT_PLACES',
            DEFAULT_JWT_PLACES,
        )
        self.cookie_name = app.config.get(
            'JWT_COOKIE_NAME',
            DEFAULT_JWT_COOKIE_NAME,
        )
        self.header_name = app.config.get(
            'JWT_HEADER_NAME',
            DEFAULT_JWT_HEADER_NAME,
        )
        self.header_type = app.config.get(
            'JWT_HEADER_TYPE',
            DEFAULT_JWT_HEADER_TYPE,
        )
        self.user_class_validation_method = app.config.get(
            'USER_CLASS_VALIDATION_METHOD',
            DEFAULT_USER_CLASS_VALIDATION_METHOD,
        )

        self.confirmation_template = app.config.get(
            'PRAETORIAN_CONFIRMATION_TEMPLATE',
            DEFAULT_CONFIRMATION_TEMPLATE,
        )
        self.confirmation_uri = app.config.get('PRAETORIAN_CONFIRMATION_URI', )
        self.confirmation_sender = app.config.get(
            'PRAETORIAN_CONFIRMATION_SENDER', )
        self.confirmation_subject = app.config.get(
            'PRAETORIAN_CONFIRMATION_SUBJECT',
            DEFAULT_CONFIRMATION_SUBJECT,
        )

        self.reset_template = app.config.get(
            'PRAETORIAN_RESET_TEMPLATE',
            DEFAULT_RESET_TEMPLATE,
        )
        self.reset_uri = app.config.get('PRAETORIAN_RESET_URI', )
        self.reset_sender = app.config.get('PRAETORIAN_RESET_SENDER', )
        self.reset_subject = app.config.get(
            'PRAETORIAN_RESET_SUBJECT',
            DEFAULT_RESET_SUBJECT,
        )

        if isinstance(self.access_lifespan, dict):
            self.access_lifespan = pendulum.duration(**self.access_lifespan)
        elif isinstance(self.access_lifespan, str):
            self.access_lifespan = duration_from_string(self.access_lifespan)
        ConfigurationError.require_condition(
            isinstance(self.access_lifespan, datetime.timedelta),
            "access lifespan was not configured",
        )

        if isinstance(self.refresh_lifespan, dict):
            self.refresh_lifespan = pendulum.duration(**self.refresh_lifespan)
        if isinstance(self.refresh_lifespan, str):
            self.refresh_lifespan = duration_from_string(self.refresh_lifespan)
        ConfigurationError.require_condition(
            isinstance(self.refresh_lifespan, datetime.timedelta),
            "refresh lifespan was not configured",
        )

        if not app.config.get('DISABLE_PRAETORIAN_ERROR_HANDLER'):
            app.register_error_handler(
                PraetorianError,
                PraetorianError.build_error_handler(),
            )

        self.is_testing = app.config.get('TESTING', False)

        if not hasattr(app, 'extensions'):
            app.extensions = {}
        app.extensions['praetorian'] = self

        return app