예제 #1
0
    def post(self):
        reset_password_data = request.get_json()

        # attempt validation
        validate_request(instance=reset_password_data,
                         schema=reset_password_json_schema)
        new_password = reset_password_data.get("new_password", None)
        password_reset_token = reset_password_data.get("password_reset_token",
                                                       None)

        if new_password and len(new_password) < 8:
            response = {
                "error": {
                    "message": "Password must be at least 8 characters long.",
                    "status": "Fail",
                }
            }
            return response, 422

        decoded_token_response = User.decode_single_use_jws(
            token=password_reset_token, required_token_type="reset_password")

        is_valid_token = decoded_token_response["status"] == "Success"
        if not is_valid_token:
            response = {
                "error": {
                    "message": decoded_token_response["message"],
                    "status": "Fail",
                }
            }
            return make_response(jsonify(response), 401)

        user: User = decoded_token_response.get("user", None)

        is_used_token = user.check_is_used_password_reset_token(
            password_reset_token=password_reset_token)
        if is_used_token:
            response = {
                "error": {
                    "message": "This token has already been used.",
                    "status": "Fail",
                }
            }
            return make_response(jsonify(response), 401)

        user.hash_password(new_password)
        user.remove_all_password_reset_tokens()
        db.session.commit()

        response = {
            "message": "Password successfully changed. Please log in.",
            "status": "Success",
        }
        return make_response(jsonify(response), 200)
예제 #2
0
    def post(self):
        activate_user_data = request.get_json()

        activation_token = activate_user_data.get("activation_token", None)

        if not activation_token:
            response = {
                "error": {
                    "message": "Activation token is required.",
                    "status": "Fail"
                }
            }
            return make_response(jsonify(response), 401)

        decoded_token_response = User.decode_single_use_jws(
            token=activation_token, required_token_type="user_activation")

        is_valid_token = decoded_token_response.get("status") == "Success"
        if not is_valid_token:
            response = {
                "error": {
                    "message": decoded_token_response.get("message"),
                    "status": "Fail",
                }
            }
            return make_response(jsonify(response), 401)

        user: User = decoded_token_response.get("user", None)
        is_already_activated = user.is_activated

        if is_already_activated:
            response = {
                "error": {
                    "message": "User is already activated. Please login.",
                    "status": "Fail",
                }
            }
            return make_response(jsonify(response), 403)

        user.is_activated = True
        authentication_token = user.encode_auth_token()
        db.session.commit()

        response = {
            "authentication_token": authentication_token.decode(),
            "data": {
                "user": user_schema.dump(user).data
            },
            "message": "User successfully activated.",
            "status": "Success",
        }
        return make_response(jsonify(response), 200)
예제 #3
0
def get_user_role_from_auth_token(token: str):
    decoded_user_data = User.decode_auth_token(token)
    if not isinstance(decoded_user_data, str):
        user = (
            User.query.filter_by(id=decoded_user_data.get("id"))
            .execution_options(show_all=True)
            .first()
        )
        if not user:
            raise Exception("No user found.")
        else:
            return user.role.name
    else:
        raise Exception(decoded_user_data)
예제 #4
0
def create_client_user(test_client, initialize_database, seed_system_data,
                       create_master_organization):
    organization = create_master_organization
    user = User(
        given_names="Jon Snow",
        surname="Stark",
        phone="+254712345678",
        signup_method=SignupMethod.MOBILE_SIGNUP,
        role_id=2,
    )
    user.set_identification_details(id_type="NATIONAL_ID", id_value="12345678")
    user.hash_password("password-123")
    db.session.add(user)
    user.bind_user_to_organization(organization)
    db.session.commit()
    return user
예제 #5
0
def create_admin_user(test_client, initialize_database, seed_system_data,
                      create_master_organization):
    organization = create_master_organization
    user = User(
        given_names="John Doe",
        surname="Jane",
        email="*****@*****.**",
        signup_method=SignupMethod.WEB_SIGNUP,
        role_id=1,
    )
    user.hash_password("password-123")
    user.bind_user_to_organization(organization)
    db.session.add(user)
    db.session.commit()
    return user
예제 #6
0
def create_user(
    given_names=None,
    surname=None,
    email=None,
    phone=None,
    address=None,
    date_of_birth=None,
    id_type=None,
    id_value=None,
    password=None,
    role=None,
    signup_method=None,
    organization: Organization = None,
):
    """
    :param role: The user's role
    :param organization: The organization the user belongs to
    :param signup_method: The channel through which teh user was signed up
    :param given_names: The collective first names the user identifies with
    :param surname: The user's surname
    :param email: The user's email address
    :param phone: The user's phone number
    :param address: The user's physical postal address
    :param date_of_birth: The user's date of birth
    :param id_type: The form of identification used by the user
    :param id_value: The value tied to that ID type
    :param password: Value of user's password
    :return:
    """

    # create user
    user = User(
        given_names=given_names,
        surname=surname,
        email=email,
        phone=phone,
        date_of_birth=date_of_birth,
        address=address,
        signup_method=signup_method,
    )

    user.is_activated = False

    # set identification information
    if id_value:
        user.set_identification_details(id_type=id_type, id_value=id_value)

    # hash password
    if password:
        user.hash_password(password=password)

    # unless special organization defined, default to master organization
    if not organization:
        organization = Organization.master_organisation()

    # bind user to organization
    user.bind_user_to_organization(organization)

    # set user role
    if role:
        user.set_role(role)
    # default to client role
    else:
        user.set_role("CLIENT")

    db.session.add(user)

    return user
예제 #7
0
    def wrapper(*args, **kwargs):
        """
        :param args:
        :param kwargs:
        :return:
        """
        auth_header = request.headers.get("Authorization")

        if auth_header:
            auth_token = auth_header.split(" ")[1]
        else:
            auth_token = ""

        if auth_token:
            # decode authentication token
            decoded_user_data = User.decode_auth_token(auth_token)

            if not isinstance(decoded_user_data, str):

                user = (
                    User.query.filter_by(id=decoded_user_data.get("id"))
                    .execution_options(show_all=True)
                    .first()
                )

                if not user:
                    response = {
                        "error": {"message": "User not found.", "status": "Fail"}
                    }
                    return make_response(jsonify(response), 401)

                if not user.is_activated:
                    response = {
                        "error": {"message": "User not activated.", "status": "Fail"}
                    }
                    return make_response(jsonify(response), 401)

                # get user role
                user_role = decoded_user_data.get("role", None)

                if len(authenticated_roles) > 0:
                    # check if user's role matches any of the required roles
                    if user_role not in authenticated_roles:
                        response = {
                            "error": {
                                "message": "User's is not authorized to access this role.",
                                "status": "Fail",
                            }
                        }
                        return make_response(jsonify(response), 401)

                return function(*args, **kwargs)

            # if returned decoded data is a message.
            response = {"error": {"message": decoded_user_data, "status": "Fail"}}
            return make_response(jsonify(response), 401)

        # if no valid authentication is provided.
        response = {
            "error": {
                "message": "Provide a valid authentication token.",
                "status": "Fail",
            }
        }
        return make_response(jsonify(response), 401)
예제 #8
0
def send_one_time_pin(user: User):
    otp = user.set_otp_secret()
    message = f"Hello {user.given_names}, your activation code is: {otp}"
    send_sms(message=message, phone_number=user.phone)
예제 #9
0
    def post(self):

        logout_instruction = request.get_json()

        action = logout_instruction.get("action", None)

        if not action or action != "logout":
            response = {
                "error": {
                    "message": "Invalid action provided for logout.",
                    "status": "Fail",
                }
            }
            return make_response(jsonify(response), 400)

        # get auth token
        auth_header = request.headers.get("Authorization")

        # get auth token
        if auth_header:
            auth_token = auth_header.split(" ")[1]
        else:
            auth_token = ""

        if auth_token:
            decoded_auth_token = User.decode_auth_token(auth_token)
            if not isinstance(decoded_auth_token, str):

                # mark the token as blacklisted
                blacklist_token = BlacklistedToken(token=auth_token)
                try:
                    # insert the token
                    db.session.add(blacklist_token)
                    db.session.commit()

                    response = {
                        "message": "Successfully logged out.",
                        "status": "Success",
                    }
                    return make_response(jsonify(response)), 200

                except Exception as exception:
                    response = {
                        "error": {
                            "message": f"System error: {exception}.",
                            "status": "Fail",
                        }
                    }
                    return make_response(jsonify(response)), 500
            else:
                response = {
                    "error": {
                        "message": decoded_auth_token,
                        "status": "Fail"
                    }
                }
                return make_response(jsonify(response)), 401

        else:
            response = {
                "error": {
                    "message": "Provide a valid auth token.",
                    "status": "Fail"
                }
            }
            return make_response(jsonify(response)), 403