예제 #1
0
    def test_detokenize_with_expired_token_fails(self):
        """Test token decoding with no token"""

        with pytest.raises(CustomError) as e_info:
            token = Encryption.tokenize(USER_DATA,
                                        subject='Testing',
                                        minutes=-10)
            Encryption.detokenize(token)
예제 #2
0
    def test_password_verify_succeeds(self):
        """Test that the password verify works"""

        hashed_password = Encryption.hash('password123')

        is_verify = Encryption.verify(hashed_password, 'password123')

        assert type(hashed_password) == str
        assert is_verify
예제 #3
0
    def test_password_verify_fails(self):
        """Test that the password verify fails when a wrong
        password is provided"""

        hashed_password = Encryption.hash('password123')

        is_verify = Encryption.verify(hashed_password, 'password1234')

        assert type(hashed_password) == str
        assert not is_verify
예제 #4
0
    def test_detokenize_succeeds(self):
        """Test token decoding"""

        token = Encryption.tokenize(USER_DATA, subject='Testing', minutes=10)

        decoded_token = Encryption.detokenize(token)

        assert decoded_token['data'] == DECODED_TOKEN['data']
        assert decoded_token['aud'] == DECODED_TOKEN['aud']
        assert decoded_token['iss'] == DECODED_TOKEN['iss']
        assert decoded_token['sub'] == DECODED_TOKEN['sub']
예제 #5
0
def generate_link(request, data, type='email_verification'):
    """Generate the link based on the type provided.

    Args:
        request (object): Request object
        data (dict): User data
        type (str): The type of token to be generated
            Examples:
                1. email_verification
                2. password_reset

    Returns:
        Tuple: A link and the token.

    """

    # gets the root url
    url_root = request.url_root

    token_payload = {
        'email': data['email'],
    }

    # generates a token
    token = Encryption.tokenize(token_payload, subject=type, minutes=10)

    # maps the methods with link type
    mapper = {
        'password_reset': password_reset_link(url_root, token),
        'email_verification': email_verification_link(url_root, token)
    }

    return mapper[type]
예제 #6
0
    def post(self):
        """Post request for user login"""

        # initialize the schema
        schema = UserSchema()

        # get the request details as json
        request_json = request.get_json()

        # serialize and find the user data in the database
        user_details = schema.load_into_schema(request_json, partial=True)
        found_user = User.query_(email=user_details['email'], deleted=False)\
            .first()

        # throw an error if not found
        if not found_user:
            return {'status': 'error', 'message': MESSAGES['NOT_FOUND']}, 404

        # deserialize the user data if found, and verify the password
        user = schema.dump(found_user).data
        is_match = Encryption.verify(user['password'],
                                     user_details['password'])

        # if password did not match throw an error
        if not is_match:
            return {
                'status': 'error',
                'message': MESSAGES['UNAUTHORIZED']
            }, 401

        else:

            # format the data and generate a JWT token.
            formatted_data = format_user(user)
            token = Encryption.tokenize(
                formatted_data, subject='User_Login', days=14)

            return {
                'status': 'success',
                'message': MESSAGES['LOGIN'],
                'data': {
                    'token': token,
                }
            }, 200
예제 #7
0
    def patch(self):
        """patch request to reset the user's password"""

        # instantiate the user schema
        user_schema = UserSchema()

        # get the verification_token from the request params
        reset_token = request.args.get('token')

        # get the request data in json format
        request_json = request.get_json()

        # check if the token is valid
        # serialize the request data and
        # look for the token in the database
        Encryption.detokenize(reset_token)
        user_details = user_schema.load_into_schema(request_json, partial=True)
        found_token = User.query_(password_reset=reset_token).first()

        # throw an error if not found
        if not found_token:
            return {
                'status': 'error',
                'message': MESSAGES['RESET_LINK_RESEND']
            }, 404

        else:
            # set the password reset column to none
            user_details['password_reset'] = None

            # hash the new password and update the password
            user_details['password'] = Encryption.hash(
                user_details['password'])
            found_token.update_(**user_details)

            return {
                'status':
                'success',
                'message':
                MESSAGES['PROCEED_TO_LOGIN'].format(
                    'Your password has been changed')
            }, 200
예제 #8
0
    def test_generate_link_for_password_reset_succeeds(self):
        """Test the generate link method"""

        data = {'email': USER_DATA['email']}

        actual_behaviour = generate_link(Request, data, type='password_reset')
        decoded_token = Encryption.detokenize(actual_behaviour[1])

        assert isinstance(actual_behaviour, tuple)
        assert len(actual_behaviour) == 2
        assert decoded_token['sub'] == 'password_reset'
예제 #9
0
    def get(self):
        """Get request to verify the user's emails"""

        # get the verification_token from the request params
        verification_token = request.args.get('token')

        # check if the token is valid and look for the token in the database
        Encryption.detokenize(verification_token)
        found_token = User.query_(token=verification_token).first()

        # throw an error if not found else update and return a success message
        if not found_token:
            return {'status': 'error', 'message': MESSAGES['VERIFIED']}, 409

        else:
            found_token.update_(token=None, verified=True)

            return {
                'status':
                'success',
                'message':
                MESSAGES['PROCEED_TO_LOGIN'].format(
                    'Your account has been successfully verified'),
            }, 200
예제 #10
0
    def post(self):
        """Post request for user registration"""

        # instantiate the user schema
        user_schema = UserSchema()

        # get the request data in json format
        request_json = request.get_json()

        # serialize and validate the request
        user_details = user_schema.load_into_schema(request_json, partial=True)
        user_details['first_name'] = user_details['first_name'].strip()
        user_details['last_name'] = user_details['last_name'].strip()

        # check if the user already exist
        found_user = User.query_(email=user_details['email']).first()
        if found_user:
            return {
                'status': 'error',
                'message': MESSAGES['DUPLICATES'].format(found_user.email)
            }, 409

        # hash password
        user_details['password'] = Encryption.hash(user_details['password'])

        # generate a random unique username
        user_details['username'] = push_id.next_id()[8:]

        link, user_details['token'] = generate_link(request, user_details)

        # save to database and serialize the returned user data
        saved_user = User(**user_details).save()

        # if the save was successful, send out the verification email and
        # return a success message.
        if saved_user:
            MailGun.with_api(
                saved_user.email,
                email_verification.format(style, link, 'Verification Link'),
                'Email verification')

            return {
                'status': 'success',
                'message': MESSAGES['REGISTER'],
            }, 201
예제 #11
0
from api.utilities.encryption import Encryption
from api.utilities.push_id import PushID

USER_DATA = {
    'firstname': 'Test',
    'lastname': 'User',
    'email': '*****@*****.**',
    'password': '******',
}

FIXTURE_NEW_USER = {
    'first_name': 'Test',
    'last_name': 'User',
    'username': PushID().next_id()[8:],
    'email': '*****@*****.**',
    'password': Encryption.hash('Password@1234'),
    'verified': True,
    'token': None,
    'password_reset': None
}

FIXTURE_NEW_USER_TWO = {
    'first_name':
    'Test',
    'last_name':
    'User',
    'username':
    PushID().next_id()[8:],
    'email':
    '*****@*****.**',
    'password':
예제 #12
0
 def _encrypt(payload, subject, **kwargs):
     return Encryption.tokenize(payload, subject=subject, **kwargs)
예제 #13
0
    def test_detokenize_with_no_token_fails(self):
        """Test token decoding with no token"""

        with pytest.raises(CustomError) as e_info:
            Encryption.detokenize(None)
예제 #14
0
    def test_tokenize_succeeds(self):
        """Test token generation"""

        token = Encryption.tokenize(USER_DATA, subject='Testing', minutes=10)

        assert type(token) == str
예제 #15
0
class TestEncryptionClass:
    """Tests encryption class"""
    def test_password_hash_succeeds(self):
        """Test that passwords are hashed"""

    hashed_password = Encryption.hash('password123')

    assert type(hashed_password) == str
    assert len(hashed_password) == 192

    def test_password_verify_succeeds(self):
        """Test that the password verify works"""

        hashed_password = Encryption.hash('password123')

        is_verify = Encryption.verify(hashed_password, 'password123')

        assert type(hashed_password) == str
        assert is_verify

    def test_password_verify_fails(self):
        """Test that the password verify fails when a wrong
        password is provided"""

        hashed_password = Encryption.hash('password123')

        is_verify = Encryption.verify(hashed_password, 'password1234')

        assert type(hashed_password) == str
        assert not is_verify

    def test_tokenize_succeeds(self):
        """Test token generation"""

        token = Encryption.tokenize(USER_DATA, subject='Testing', minutes=10)

        assert type(token) == str

    def test_detokenize_succeeds(self):
        """Test token decoding"""

        token = Encryption.tokenize(USER_DATA, subject='Testing', minutes=10)

        decoded_token = Encryption.detokenize(token)

        assert decoded_token['data'] == DECODED_TOKEN['data']
        assert decoded_token['aud'] == DECODED_TOKEN['aud']
        assert decoded_token['iss'] == DECODED_TOKEN['iss']
        assert decoded_token['sub'] == DECODED_TOKEN['sub']

    def test_detokenize_with_no_token_fails(self):
        """Test token decoding with no token"""

        with pytest.raises(CustomError) as e_info:
            Encryption.detokenize(None)

    def test_detokenize_with_expired_token_fails(self):
        """Test token decoding with no token"""

        with pytest.raises(CustomError) as e_info:
            token = Encryption.tokenize(USER_DATA,
                                        subject='Testing',
                                        minutes=-10)
            Encryption.detokenize(token)