示例#1
0
    def setup_context(self, reset_config_if_needed=True):
        if isfile(self.conf):
            self._BUNQ_CONF_CUSTOM = self.conf
            pass  # Config is already present
        elif isfile(self.determine_bunq_conf_filename()):
            pass  # Config is already present
        elif self.env == ApiEnvironmentType.SANDBOX:
            sandbox_user = self.generate_new_sandbox_user()
            ApiContext.create(ApiEnvironmentType.SANDBOX, sandbox_user.api_key,
                              socket.gethostname()).save(
                                  self.determine_bunq_conf_filename())
        else:
            raise BunqException(self._ERROR_COULD_NOT_DETIRMINE_CONF)

        try:
            api_context = ApiContext.restore(
                self.determine_bunq_conf_filename())
            api_context.ensure_session_active()
            api_context.save(self.determine_bunq_conf_filename())

            BunqContext.load_api_context(api_context)
        except ForbiddenException as forbidden_exception:
            if reset_config_if_needed:
                self.__handle_forbidden_exception(forbidden_exception)
            else:
                raise forbidden_exception
示例#2
0
    def assert_has_next_page(self) -> None:
        """

        :raise: BunqException
        """

        if self._next_id is None:
            raise BunqException(self._ERROR_NO_NEXT_PAGE)
示例#3
0
    def assert_has_previous_page(self) -> None:
        """

        :raise: BunqException
        """

        if not self.has_previous_page():
            raise BunqException(self._ERROR_NO_PREVIOUS_PAGE)
示例#4
0
def validate_response(public_key_server: RsaKey, status_code: int,
                      body_bytes: bytes, headers: Dict[str, str]) -> None:
    if is_valid_response_header_with_body(public_key_server, status_code,
                                          body_bytes, headers):
        return
    elif is_valid_response_body(public_key_server, body_bytes, headers):
        return
    else:
        raise BunqException(_ERROR_INVALID_SIGNATURE)
示例#5
0
    def determine_auth_uri_format(cls) -> str:
        environment_type = BunqContext.api_context().environment_type

        if ApiEnvironmentType.PRODUCTION == environment_type:
            return cls.TOKEN_URI_FORMAT_PRODUCTION

        if ApiEnvironmentType.SANDBOX == environment_type:
            return cls.TOKEN_URI_FORMAT_SANDBOX

        raise BunqException(cls.ERROR_ENVIRONMENT_TYPE_NOT_SUPPORTED)
示例#6
0
    def alias_first(self) -> Pointer:
        if BunqContext.user_context().is_only_user_company_set():
            return BunqContext.user_context().user_company.alias[
                self._FIRST_INDEX]

        if BunqContext.user_context().is_only_user_person_set():
            return BunqContext.user_context().user_person.alias[
                self._FIRST_INDEX]

        raise BunqException(self.__ERROR_COULD_NOT_DETERMINE_USER)
示例#7
0
    def get_first_pointer_iban(cls, monetary_account_bank):
        """
        :rtype: object_.Pointer
        """

        for alias in monetary_account_bank.alias:
            if alias.type_ == cls._POINTER_TYPE_IBAN:
                return alias

        raise BunqException(cls._ERROR_COULD_NOT_FIND_IBAN_POINTER)
示例#8
0
 def __set_user(self, user: BunqModel):
     if isinstance(user, UserPerson):
         self._user_person = user
     elif isinstance(user, UserCompany):
         self._user_company = user
     elif isinstance(user, UserApiKey):
         self._user_api_key = user
     elif isinstance(user, UserPaymentServiceProvider):
         self._user_payment_service_provider = user
     else:
         raise BunqException(self._ERROR_UNEXPECTED_USER_INSTANCE)
示例#9
0
 def get_user_reference(self) -> BunqModel:
     if self.user_person is not None:
         return self.user_person
     elif self.user_company is not None:
         return self.user_company
     elif self.user_api_key is not None:
         return self.user_api_key
     elif self.user_payment_service_provider is not None:
         return self.user_payment_service_provider
     else:
         raise BunqException(self._ERROR_ALL_FIELD_IS_NULL)
示例#10
0
    def create(cls,
               description: str,
               secret: str,
               permitted_ips: List[str] = None,
               custom_headers: Dict[str, str] = None,
               api_context: ApiContext = None) -> BunqResponseInt:
        """
        Create a new DeviceServer providing the installation token in the header
        and signing the request with the private part of the key you used to
        create the installation. The API Key that you are using will be bound to
        the IP address of the DeviceServer which you have
        created.<br/><br/>Using a Wildcard API Key gives you the freedom to make
        API calls even if the IP address has changed after the POST
        device-server.<br/><br/>Find out more at this link <a
        href="https://bunq.com/en/apikey-dynamic-ip"
        target="_blank">https://bunq.com/en/apikey-dynamic-ip</a>.

        :param description: The description of the DeviceServer. This is only
        for your own reference when reading the DeviceServer again.
        :type description: str
        :param secret: The API key. You can request an API key in the bunq app.
        :type secret: str
        :param permitted_ips: An array of IPs (v4 or v6) this DeviceServer will
        be able to do calls from. These will be linked to the API key.
        :type permitted_ips: list[str]
        :type custom_headers: dict[str, str]|None
        :type api_context: ApiContext

        :rtype: BunqResponseInt
        """

        if api_context is None:
            raise BunqException(cls._ERROR_API_CONTEXT_IS_NULL)

        if custom_headers is None:
            custom_headers = {}

        request_map = {
            cls.FIELD_DESCRIPTION: description,
            cls.FIELD_SECRET: secret,
            cls.FIELD_PERMITTED_IPS: permitted_ips
        }

        api_client = ApiClient(api_context)
        request_bytes = converter.class_to_json(request_map).encode()
        endpoint_url = cls._ENDPOINT_URL_CREATE
        response_raw = api_client.post(endpoint_url, request_bytes,
                                       custom_headers)

        return BunqResponseInt.cast_from_bunq_response(
            cls._process_for_id(response_raw)
        )
示例#11
0
    def init_main_monetary_account(self) -> None:
        if self._user_payment_service_provider is not None:
            return

        all_monetary_account = endpoint.MonetaryAccountBank.list().value

        for account in all_monetary_account:
            if account.status == self._STATUS_ACTIVE:
                self._primary_monetary_account = account

                return

        raise BunqException(self._ERROR_NO_ACTIVE_MONETARY_ACCOUNT_FOUND)
示例#12
0
    def __get_user_id(self, user: BunqModel) -> int:
        if isinstance(user, UserPerson):
            return user.id_

        if isinstance(user, UserCompany):
            return user.id_

        if isinstance(user, UserApiKey):
            return user.id_

        if isinstance(user, UserPaymentServiceProvider):
            return user.id_

        raise BunqException(self._ERROR_UNEXPECTED_USER_INSTANCE)
示例#13
0
    def setup_context(self):
        if isfile(self.determine_bunq_conf_filename()):
            pass  # Config is already present
        elif self.env == ApiEnvironmentType.SANDBOX:
            sandbox_user = self.generate_new_sandbox_user()
            ApiContext.create(ApiEnvironmentType.SANDBOX, sandbox_user.api_key, socket.gethostname()).save(
                self.determine_bunq_conf_filename())
        else:
            raise BunqException(self._ERROR_COULD_NOT_DETIRMINE_CONF)

        api_context = ApiContext.restore(self.determine_bunq_conf_filename())
        api_context.ensure_session_active()
        api_context.save(self.determine_bunq_conf_filename())

        BunqContext.load_api_context(api_context)
示例#14
0
 def _get_session_timeout_seconds(cls, session_server: SessionServer) -> int:
     if session_server.user_company is not None:
         return session_server.user_company.session_timeout
     elif session_server.user_person is not None:
         return session_server.user_person.session_timeout
     elif session_server.user_payment_service_provider is not None:
         return session_server.user_payment_service_provider.session_timeout
     elif session_server.user_api_key is not None:
         return session_server \
             .user_api_key \
             .requested_by_user \
             .get_referenced_object() \
             .session_timeout
     else:
         raise BunqException()
示例#15
0
    def _set_user(self, user: BunqModel) -> None:
        if isinstance(user, endpoint.UserPerson):
            self._user_person = user

        elif isinstance(user, endpoint.UserCompany):
            self._user_company = user

        elif isinstance(user, endpoint.UserApiKey):
            self._user_api_key = user

        elif isinstance(user, endpoint.UserPaymentServiceProvider):
            self._user_payment_service_provider = user

        else:
            raise BunqException(
                self._ERROR_UNEXPECTED_USER_INSTANCE.format(user.__class__))
示例#16
0
    def deserialize(cls, target_class: Type[SessionServer],
                    array: List) -> SessionServer:
        session_server = target_class.__new__(target_class)
        session_server.__dict__ = {
            cls._ATTRIBUTE_ID:
            converter.deserialize(Id, array[cls._INDEX_ID][cls._FIELD_ID]),
            cls._ATTRIBUTE_TOKEN:
            converter.deserialize(SessionToken,
                                  array[cls._INDEX_TOKEN][cls._FIELD_TOKEN]),
            cls._ATTRIBUTE_USER_COMPANY:
            None,
            cls._ATTRIBUTE_USER_PERSON:
            None,
            cls._ATTRIBUTE_USER_PAYMENT_SERVER_PROVIDER:
            None,
        }

        user_dict_wrapped = array[cls._INDEX_USER]

        if cls._FIELD_USER_COMPANY in user_dict_wrapped:
            session_server.__dict__[cls._ATTRIBUTE_USER_COMPANY] = \
                converter.deserialize(
                    endpoint.UserCompany,
                    user_dict_wrapped[cls._FIELD_USER_COMPANY]
                )
        elif cls._FIELD_USER_PERSON in user_dict_wrapped:
            session_server.__dict__[cls._ATTRIBUTE_USER_PERSON] = \
                converter.deserialize(
                    endpoint.UserPerson,
                    user_dict_wrapped[cls._FIELD_USER_PERSON]
                )
        elif cls._FIELD_USER_API_KEY in user_dict_wrapped:
            session_server.__dict__[cls._ATTRIBUTE_USER_API_KEY] = \
                converter.deserialize(
                    endpoint.UserApiKey,
                    user_dict_wrapped[cls._FIELD_USER_API_KEY]
                )
        elif cls._FIELD_USER_PAYMENT_SERVER_PROVIDER in user_dict_wrapped:
            session_server.__dict__[cls._ATTRIBUTE_USER_PAYMENT_SERVER_PROVIDER] = \
                converter.deserialize(
                    endpoint.UserPaymentServiceProvider,
                    user_dict_wrapped[cls._FIELD_USER_PAYMENT_SERVER_PROVIDER]
                )
        else:
            raise BunqException(cls._ERROR_COULD_NOT_DETERMINE_USER)

        return session_server
示例#17
0
    def _get_object_class(cls, class_name: str) -> BunqModel:
        class_name = class_name.lstrip(cls.__STRING_FORMAT_UNDERSCORE)

        if class_name in cls._override_field_map:
            class_name = cls._override_field_map[class_name]

        try:
            return getattr(endpoint, class_name)
        except AttributeError:
            pass

        try:
            return getattr(object_, class_name)
        except AttributeError:
            pass

        raise BunqException(cls.__ERROR_MODEL_NOT_FOUND.format(class_name))
示例#18
0
    def _str_to_type_from_member_module(cls, module_: ModuleType,
                                        string: str) -> Type[T]:
        """

        :raise: BunqException when could not find the class for the string.
        """

        module_name_short, class_name = string.split(cls._DELIMITER_MODULE)
        members = inspect.getmembers(module_, inspect.ismodule)

        for name, module_member in members:
            if module_name_short == name:
                return getattr(module_member, class_name)

        error_message = cls._ERROR_COULD_NOT_FIND_CLASS.format(string)

        raise BunqException(error_message)
示例#19
0
    def _fetch_attribute_specs_from_doc(
            cls, cls_in: Type[T], attribute_name: str) -> Optional[ValueSpecs]:
        pattern = cls._TEMPLATE_PATTERN_PARAM_TYPES.format(attribute_name)
        doc_type = cls_in.__doc__

        if doc_type is None:
            raise BunqException(
                cls._ERROR_MISSING_DOC_COMMENT.format(attribute_name, cls_in))

        match = re.search(pattern, doc_type)

        if match is not None:
            return ValueSpecs(
                cls._fetch_name(match),
                ValueTypes(cls._fetch_type_main(cls_in, match),
                           cls._fetch_type_sub(cls_in, match)))
        else:
            return None
示例#20
0
def __generate_new_sandbox_user() -> SandboxUser:
    url = ApiEnvironmentType.SANDBOX.uri_base + __ENDPOINT_SANDBOX_USER

    headers = {
        ApiClient.HEADER_REQUEST_ID: __UNIQUE_REQUEST_ID,
        ApiClient.HEADER_CACHE_CONTROL: ApiClient.CACHE_CONTROL_NONE,
        ApiClient.HEADER_GEOLOCATION: ApiClient.GEOLOCATION_ZERO,
        ApiClient.HEADER_LANGUAGE: ApiClient.LANGUAGE_EN_US,
        ApiClient.HEADER_REGION: ApiClient.REGION_NL_NL,
    }

    response = requests.request(ApiClient.METHOD_POST, url, headers=headers)

    if response.status_code is ApiClient.STATUS_CODE_OK:
        response_json = json.loads(response.text)
        return endpoint.SandboxUser.from_json(
            json.dumps(response_json[__FIELD_RESPONSE][__INDEX_FIRST]
                       [__FIELD_API_KEY]))

    raise BunqException(_ERROR_COULD_NOT_CREATE_NEW_SANDBOX_USER)
示例#21
0
    def generate_new_sandbox_user(self):
        """
        :rtype: SandboxUser
        """

        url = "https://public-api.sandbox.bunq.com/v1/sandbox-user"

        headers = {
            'x-bunq-client-request-id': "uniqueness-is-required",
            'cache-control': "no-cache",
            'x-bunq-geolocation': "0 0 0 0 NL",
            'x-bunq-language': "en_US",
            'x-bunq-region': "en_US",
        }

        response = requests.request("POST", url, headers=headers)

        if response.status_code == 200:
            response_json = json.loads(response.text)
            return endpoint.SandboxUser.from_json(
                json.dumps(response_json["Response"][0]["ApiKey"]))

        raise BunqException(self._ERROR_COULD_NOT_CREATE_NEW_SANDBOX_USER)
示例#22
0
    def user_context(cls) -> UserContext:
        if cls._user_context is not None:
            return cls._user_context

        raise BunqException(cls._ERROR_USER_CONTEXT_HAS_NOT_BEEN_LOADED)
示例#23
0
    def api_context(cls) -> ApiContext:
        if cls._api_context is not None:
            return cls._api_context

        raise BunqException(cls._ERROR_API_CONTEXT_HAS_NOT_BEEN_LOADED)