def __init__(self, **args):

        # Default message:
        self.msg = 'Insufficient permission'

        # Possible arguments:
        optional_args = ['msg', 'handle', 'operation', 'response', 'username']
        add_missing_optional_args_with_value_none(args, optional_args)
        self.handle = args['handle']
        self.custom_message = args['msg']
        self.operation = args['operation']
        self.response = args['response']
        self.username = args['username']

        if self.operation is not None:
            self.msg += ' for '+self.operation

        if self.custom_message is not None:
            self.msg += ': '+self.custom_message
        self.msg += '.'

        if self.handle is not None:
            self.msg += '\n\tHandle: '+self.handle

        if self.username is not None:
            self.msg += '\n\tUsername: '******'\n\tURL: '+str(self.response.request.url)
            self.msg += '\n\tHTTP Status Code: '+str(self.response.status_code)
            self.msg += '\n\tResponse: '+str(self.response.content)

        super(self.__class__, self).__init__(self.msg)
    def __init__(self,**args):

        # Default message:
        self.msg = 'Error during interaction with Handle Server'

        # Possible arguments:
        optional_args = ['msg', 'handle','response', 'payload', 'operation']
        add_missing_optional_args_with_value_none(args, optional_args)
        self.handle = args['handle']
        self.custom_message = args['msg']
        self.response = args['response']
        self.operation = args['operation']
        self.payload = args['payload']

        if self.operation is not None:
            self.msg += ' ('+self.operation+')'

        if self.custom_message is not None:
            self.msg += ': '+self.custom_message
        self.msg += '.'

        if self.handle is not None:
            self.msg += '\n\tHandle: '+self.handle

        if self.response is not None:
            self.msg += '\n\tURL: '+str(self.response.request.url)
            self.msg += '\n\tHTTP Status Code: '+str(self.response.status_code)
            self.msg += '\n\tResponse: '+str(self.response.content)

        if self.payload is not None:
            self.msg += '\n\tPayload: '+self.payload

        super(self.__class__, self).__init__(self.msg)
    def __init__(self, **args):

        # Default message:
        self.msg = 'Error during Reverse Lookup'

        # Possible arguments:
        optional_args = ['msg', 'query','response']
        add_missing_optional_args_with_value_none(args, optional_args)
        self.query = args['query']
        self.custom_message = args['msg']
        self.response = args['response']

        if self.custom_message is not None:
            self.msg += ': '+self.custom_message
        self.msg += '.'

        if self.query is not None:
            self.msg += '\n\tQuery: '+self.query

        if self.response is not None:
            pat = re.compile('>[\s]+<')
            responsecontent_less_whitespace = pat.sub('><', str(self.response.content))
            self.msg += '\n\tURL: '+str(self.response.request.url)
            self.msg += '\n\tHTTP Status Code: '+str(self.response.status_code)
            self.msg += '\n\tResponse: '+responsecontent_less_whitespace

        super(self.__class__, self).__init__(self.msg)
    def __init__(self, **args):

        # Default message:
        self.msg ='Handle not found on server'

        # Possible arguments:
        optional_args = ['msg', 'handle','response']
        add_missing_optional_args_with_value_none(args, optional_args)
        self.handle = args['handle']
        self.custom_message = args['msg']
        self.response = args['response']

        if self.handle is not None:
            self.msg = self.msg.replace('andle', 'andle '+self.handle)

        if self.custom_message is not None:
            self.msg += ': '+self.custom_message
        self.msg += '.'

        if self.response is not None:
            self.msg += '\n\tURL: '+str(self.response.request.url)
            self.msg += '\n\tHTTP Status Code: '+str(self.response.status_code)
            self.msg += '\n\tResponse: '+str(self.response.content)

        super(self.__class__, self).__init__(self.msg)
Esempio n. 5
0
def make_request_log_message(**args):
    '''
    Creates a string containing all relevant information
    about a request made to the Handle System, for
    logging purposes.

    :handle: The handle that the request is about.
    :url: The url the request is sent to.
    :headers: The headers sent along with the request.
    :verify: Boolean parameter passed to the requests
        module (https verification).
    :resp: The request's response.
    :op: The library operation during which the request
        was sent.
    :payload: Optional. The payload sent with the request.
    :return: A formatted string.

    '''

    mandatory_args = ['op', 'handle', 'url', 'headers', 'verify', 'resp']
    optional_args = ['payload']
    util.check_presence_of_mandatory_args(args, mandatory_args)
    util.add_missing_optional_args_with_value_none(args, optional_args)

    space = '\n   '
    message = ''
    message += '\n'+args['op']+' '+args['handle']
    message += space+'URL:          '+args['url']
    message += space+'HEADERS:      '+str(args['headers'])
    message += space+'VERIFY:       '+str(args['verify'])
    if 'payload' in args.keys():
        message += space+'PAYLOAD:'+space+str(args['payload'])
    message += space+'RESPONSECODE: '+str(args['resp'].status_code)
    message += space+'RESPONSE:'+space+str(args['resp'].content)
    return message
    def __init__(self, **args):

        util.log_instantiation(LOGGER, 'HandleSystemConnector', args, ['password','reverselookup_password'])

        # Possible arguments:
        optional_args = [
            'handle_server_url',
            'REST_API_url_extension',
            'HTTPS_verify',
            'username',
            'password',
            'private_key',
            'certificate_only',
            'certificate_and_key'
        ]
        util.add_missing_optional_args_with_value_none(args, optional_args)

        # Defaults for args:
        defaults = {
            'handle_server_url': 'https://hdl.handle.net',
            'REST_API_url_extension': '/api/handles/',
            'HTTPS_verify': True,
        }

        # Args that the constructor understands:
        self.__handle_server_url = None
        self.__REST_API_url_extension = None
        self.__HTTPS_verify = None
        self.__username = None
        self.__password = None
        self.__private_key = None
        self.__certificate_only = None
        self.__certificate_and_key = None
        self.__handle_connector = None

        # Other attributes:
        self.__basic_authentication_string = None
        self.__cert_object = None
        self.__has_write_access = False
        self.__auth_methods = dict(user_pw='user_pw', cert='client_cert')
        self.__authentication_method = None
        self.__session = requests.Session()
        self.__no_auth_message = 'No credentials passed. Read access only.'
        self.__first_request = True

        # Needed for read and write access:
        self.__store_args_or_set_to_defaults(args, defaults)

        # If write access, do some additional setup:
        if self.__check_if_write_access(args):
            self.__setup_for_writeaccess(args)

        LOGGER.debug('End of instantiation of the handle system connector.')
    def __init__(self, **args):

        # Default message:
        self.msg = 'Ill-formatted credentials'

        # Possible arguments:
        optional_args = ['msg']
        add_missing_optional_args_with_value_none(args, optional_args)
        self.custom_message = args['msg']

        if self.custom_message is not None:
            self.msg += ': '+self.custom_message
        self.msg += '.'

        super(self.__class__, self).__init__(self.msg)
Esempio n. 8
0
    def __init__(self, **args):

        util.log_instantiation(LOGGER, 'Searcher', args, ['password','reverselookup_password'])

        optional_args = [
            'reverselookup_baseuri',
            'reverselookup_url_extension',
            'handle_server_url',
            'reverselookup_username',
            'username',
            'reverselookup_password',
            'password',
            'allowed_search_keys',
            'HTTPS_verify'
        ]
        util.add_missing_optional_args_with_value_none(args, optional_args)

        # Args that the constructor understands:
        self.__reverselookup_baseuri = None
        self.__reverselookup_url_extension = None
        self.__allowed_search_keys = None
        self.__HTTPS_verify = None
        self.__user = None
        self.__password = None

        # Other attributes:
        self.__has_search_access = False
        self.__handle_system_username_used = False
        self.__handle_system_password_used = False
        self.__revlookup_auth_string = None
        self.__header = None
        self.__session = None

        # Defaults:
        defaults = {
            'allowed_search_keys': ['URL', 'CHECKSUM'],
            'HTTPS_verify': True,
            'reverselookup_url_extension': '/hrls/handles/',
        }

        # Set them:
        self.__store_args_or_set_to_defaults(args, defaults)
        if self.__has_search_access:
            self.__setup_search_access()

        LOGGER.debug('End of instantiation of the search module.')
    def __init__(self, **args):

        # Default message:
        self.msg = 'Handle already exists'

        # Possible arguments:
        optional_args = ['msg', 'handle']
        add_missing_optional_args_with_value_none(args, optional_args)
        self.handle = args['handle']
        self.custom_message = args['msg']

        if self.handle is not None:
            self.msg = self.msg.replace('andle', 'andle '+self.handle)

        if self.custom_message is not None:
            self.msg += ': '+self.custom_message
        self.msg += '.'

        super(self.__class__, self).__init__(self.msg)
    def __init__(self, **args):

        # Default message:
        self.msg = 'Ill-formatted handle record'

        # Possible arguments:
        optional_args = ['msg', 'handle']
        add_missing_optional_args_with_value_none(args, optional_args)
        self.handle = args['handle']
        self.custom_message = args['msg']

        if self.custom_message is not None:
            self.msg += ': '+self.custom_message
        self.msg += '.'

        if self.handle is not None:
            self.msg += '\n\tHandle: '+self.handle

        super(self.__class__, self).__init__(self.msg)
    def __init__(self, **args):

        # Default message:
        self.msg = "Illegal Operation"

        # Possible arguments:
        optional_args = ['msg', 'handle', 'operation']
        add_missing_optional_args_with_value_none(args, optional_args)
        self.handle = args['handle']
        self.custom_message = args['msg']
        self.operation = args['operation']

        if self.operation is not None:
            self.msg += ' ('+self.operation+')'
        if self.handle is not None:
            self.msg += ' on handle '+self.handle
        if self.custom_message is not None:
            self.msg += ': ' + self.custom_message
        self.msg += '.'

        super(self.__class__, self).__init__(self.msg)
    def __init__(self, **args):

        # Default message:
        self.msg = 'Handle does not have expected syntax'

        # Possible arguments:
        optional_args = ['msg', 'handle','expected_syntax']
        add_missing_optional_args_with_value_none(args, optional_args)
        self.handle = args['handle']
        self.custom_message = args['msg']
        self.expected_syntax = args['expected_syntax']

        if self.handle is not None:
            self.msg = self.msg.replace('andle', 'andle '+self.handle)

        if self.custom_message is not None:
            self.msg += ': '+self.custom_message
        self.msg += '.'

        if self.expected_syntax is not None:
            self.msg += '\n\tExpected: '+self.expected_syntax

        super(self.__class__, self).__init__(self.msg)
    def __init__(self, **args):
        '''
        Initialize client credentials instance.

        The constructor checks if enough arguments are passed to
        authenticate at a handle server or search servlet. For this,
        the following parameters are checked. Depending on the
        chosen authentication method, only a subset of them are
        required.

        All other parameters passed are stored and can be retrieved
        using 'get_config()'. If a credentials objects is used to
        initialize the client, these key-value pairs are passed on
        to the client constructor.

        :param handle_server_url: Optional. The URL of the Handle System
            server to read from. Defaults to 'https://hdl.handle.net'
        :param username: Optional. This must be a handle value reference in
            the format "index:prefix/suffix". The method will throw an exception
            upon bad syntax or non-existing Handle. The existence or validity
            of the password in the handle is not checked at this moment.
        :param password: Optional. This is the password stored as secret key
            in the actual Handle value the username points to.
        :param handleowner: Optional. The username that will be given admin
            permissions over every newly created handle. By default, it is
            '200:0.NA/xyz' (where xyz is the prefix of the handle being created.
        :param private_key: Optional. The path to a file containing the private
            key that will be used for authentication in write mode. If this is
            specified, a certificate needs to be specified too.
        :param certificate_only: Optional. The path to a file containing the
            client certificate that will be used for authentication in write
            mode. If this is specified, a private key needs to be specified too.
        :param certificate_and_key: Optional. The path to a file containing both
            certificate and private key, used for authentication in write mode.
        :param prefix: Prefix. This is not used by the library, but may be
            retrieved by the user.
        :param \**args: Any other key-value pairs are stored and can be accessed
            using 'get_config()'.
        :raises: :exc:`~b2handle.handleexceptions.HandleSyntaxError`
        '''

        util.log_instantiation(LOGGER, 'PIDClientCredentials', args, ['password','reverselookup_password'])

        # Possible arguments:
        useful_args = [
            'handle_server_url',
            'username',
            'password',
            'private_key',
            'certificate_only',
            'certificate_and_key',
            'prefix',
            'handleowner',
            'reverselookup_password',
            'reverselookup_username',
            'reverselookup_baseuri'
        ]
        util.add_missing_optional_args_with_value_none(args, useful_args)

        # Args that the constructor understands:
        self.__handle_server_url = args['handle_server_url']
        self.__username = args['username']
        self.__password = args['password']
        self.__prefix = args['prefix']
        self.__handleowner = args['handleowner']
        self.__private_key = args['private_key']
        self.__certificate_only = args['certificate_only']
        self.__certificate_and_key = args['certificate_and_key']

        # Other attributes:
        self.__additional_config = None

        # All the other args collected as "additional config":
        self.__additional_config = self.__collect_additional_arguments(args, useful_args)

        # Some checks:
        self.__check_handle_syntax()
        self.__check_file_existence()
        self.__check_if_enough_args_for_revlookup_auth(args)
        self.__check_if_enough_args_for_hs_auth()
Esempio n. 14
0
    def send_handle_delete_request(self, **args):
        '''
        Send a HTTP DELETE request to the handle server to delete either an
            entire handle or to some specified values from a handle record,
            using the requests module.

        :param handle: The handle.
        :param indices: Optional. A list of indices to delete. Defaults to
            None (i.e. the entire handle is deleted.). The list can contain
            integers or strings.
        :return: The server's response.
        '''

        # Check if we have write access at all:
        if not self.__has_write_access:
            raise HandleAuthenticationError(msg=self.__no_auth_message)

        # Check args:
        mandatory_args = ['handle']
        optional_args = ['indices', 'op']
        util.add_missing_optional_args_with_value_none(args, optional_args)
        util.check_presence_of_mandatory_args(args, mandatory_args)
        handle = args['handle']
        indices = args['indices']
        op = args['op']

        # Make necessary values:
        url = self.make_handle_URL(handle, indices)
        if indices is not None and len(indices) > 0:
            LOGGER.debug('__send_handle_delete_request: Deleting values '+str(indices)+' from handle '+handle+'.')
        else:
            LOGGER.debug('__send_handle_delete_request: Deleting handle '+handle+'.')
        LOGGER.debug('DELETE Request to '+url)
        head = self.__get_headers('DELETE')
        veri = self.__HTTPS_verify

        # Make request:
        resp = None
        if self.__authentication_method == self.__auth_methods['user_pw']:
            resp = self.__session.delete(url, headers=head, verify=veri)
        elif self.__authentication_method == self.__auth_methods['cert']:
            resp = self.__session.delete(url, headers=head, verify=veri, cert=self.__cert_object)
        self.__log_request_response_to_file(
            logger=REQUESTLOGGER,
            op='DELETE',
            handle=handle,
            url=url,
            headers=head,
            verify=veri,
            resp=resp
        )

        # Check response for authentication issues:
        if hsresponses.not_authenticated(resp):
            raise HandleAuthenticationError(
                operation=op,
                handle=handle,
                response=resp,
                username=self.__username
            )

        return resp
Esempio n. 15
0
    def send_handle_put_request(self, **args):
        '''
        Send a HTTP PUT request to the handle server to write either an entire
            handle or to some specified values to an handle record, using the
            requests module.

        :param handle: The handle.
        :param list_of_entries: A list of handle record entries to be written,
         in the format [{"index":xyz, "type":"xyz", "data":"xyz"}] or similar.
        :param indices: Optional. A list of indices to delete. Defaults
         to None (i.e. the entire handle is deleted.). The list can
         contain integers or strings.
        :param overwrite: Optional. Whether the handle should be overwritten
         if it exists already.
        :return: The server's response.
        '''

        # Check if we have write access at all:
        if not self.__has_write_access:
            raise HandleAuthenticationError(msg=self.__no_auth_message)

        # Check args:
        mandatory_args = ['handle', 'list_of_entries']
        optional_args = ['indices', 'op', 'overwrite']
        util.add_missing_optional_args_with_value_none(args, optional_args)
        util.check_presence_of_mandatory_args(args, mandatory_args)
        handle = args['handle']
        list_of_entries = args['list_of_entries']
        indices = args['indices']
        op = args['op']
        overwrite = args['overwrite'] or False

        # Overwrite by index:
        if indices is not None:
            message = 'Writing handle values by index is not implemented'+\
                ' yet because the way the indices are interpreted by the'+\
                ' Handle Server may be modified soon. The entire handle'+\
                ' record has to be overwritten.'
            raise NotImplementedError(message)
            # TODO FIXME: As soon as the Handle System uses the correct indices
            # for overwriting, this may be implemented.
            # In HSv8 beta, the HS uses ?index=3 for overwriting index:4. If the
            # library used this and then the behaviour is changed, it would lead
            # to corrupt handle records, so we wait until the issue is fixed by
            # the Handle System.

        # Make necessary values:
        url = self.make_handle_URL(handle, overwrite=overwrite)
        LOGGER.debug('PUT Request to '+url)
        payload = json.dumps({'values':list_of_entries})
        LOGGER.debug('PUT Request payload: '+payload)
        head = self.__get_headers('PUT')
        veri = self.__HTTPS_verify

        # Make request:
        resp = None
        if self.__authentication_method == self.__auth_methods['user_pw']:
            resp = self.__session.put(url, data=payload, headers=head, verify=veri)
        elif self.__authentication_method == self.__auth_methods['cert']:
            resp = self.__session.put(url, data=payload, headers=head, verify=veri, cert=self.__cert_object)
        self.__log_request_response_to_file(
            logger=REQUESTLOGGER,
            op='PUT',
            handle=handle,
            url=url,
            headers=head,
            verify=veri,
            resp=resp,
            payload=payload)

        # Check response for authentication issues:
        if hsresponses.not_authenticated(resp):
            raise HandleAuthenticationError(
                operation=op,
                handle=handle,
                response=resp,
                username=self.__username
            )

        return resp, payload