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)
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)
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()
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
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