def __init__(self, customer, username, password, host='api.dynect.net', port=443, ssl=True, api_version='current', auto_auth=True, key=None, history=False, proxy_host=None, proxy_port=None, proxy_user=None, proxy_pass=None): """Initialize a Dynect Rest Session object and store the provided credentials :param host: DynECT API server address :param port: Port to connect to DynECT API server :param ssl: Enable SSL :param api_version: version of the api to use :param customer: DynECT customer name :param username: DynECT Customer's username :param password: User's password :param auto_auth: declare whether or not to automatically log in :param key: A valid AES-256 password encryption key to be used when encrypting your password :param history: A boolean flag determining whether or not you would like to store a record of all API calls made to review later :param proxy_host: A proxy host to utilize :param proxy_port: The port that the proxy is served on :param proxy_user: A username to connect to the proxy with if required :param proxy_pass: A password to connect to the proxy with if required """ super(DynectSession, self).__init__(host, port, ssl, history, proxy_host, proxy_port, proxy_user, proxy_pass) self.__cipher = AESCipher(key) self.extra_headers = {'API-Version': api_version} self.customer = customer self.username = username self.password = self.__cipher.encrypt(password) self.connect() if auto_auth: self.authenticate()
class DynectSession(SessionEngine): """Base object representing a DynectSession Session""" __metakey__ = 'bf7886ea-c61d-40df-8c7b-4241ebed0544' _valid_methods = ('DELETE', 'GET', 'POST', 'PUT') uri_root = '/REST' def __init__(self, customer, username, password, host='api.dynect.net', port=443, ssl=True, api_version='current', auto_auth=True, key=None, history=False, proxy_host=None, proxy_port=None, proxy_user=None, proxy_pass=None): """Initialize a Dynect Rest Session object and store the provided credentials :param host: DynECT API server address :param port: Port to connect to DynECT API server :param ssl: Enable SSL :param api_version: version of the api to use :param customer: DynECT customer name :param username: DynECT Customer's username :param password: User's password :param auto_auth: declare whether or not to automatically log in :param key: A valid AES-256 password encryption key to be used when encrypting your password :param history: A boolean flag determining whether or not you would like to store a record of all API calls made to review later :param proxy_host: A proxy host to utilize :param proxy_port: The port that the proxy is served on :param proxy_user: A username to connect to the proxy with if required :param proxy_pass: A password to connect to the proxy with if required """ super(DynectSession, self).__init__(host, port, ssl, history, proxy_host, proxy_port, proxy_user, proxy_pass) self.__cipher = AESCipher(key) self.extra_headers = {'API-Version': api_version} self.customer = customer self.username = username self.password = self.__cipher.encrypt(password) self.connect() if auto_auth: self.authenticate() def __enter__(self): """Yield this instance as a reference for use within the context block """ yield self def __exit__(self, exc_type, exc_val, exc_tb): """We don't particularly care about any exceptions that occured within the context block, so ignore them and force a log out, which handles closing the current session. """ self.log_out() def _encrypt(self, data): """Accessible method for subclass to encrypt with existing AESCipher""" return self.__cipher.encrypt(data) def _handle_error(self, uri, method, raw_args): """Handle the processing of a connection error with the api""" # Our token is no longer valid because our session was killed self._token = None # Need to force a re-connect on next execute self._conn.close() self._conn.connect() # Need to get a new Session token self.execute('/REST/Session/', 'POST', self.__auth_data) # Then try the current call again and Specify final as true so # if we fail again we can raise the actual error return self.execute(uri, method, raw_args, final=True) def _process_response(self, response, method, final=False): """Process an API response for failure, incomplete, or success and throw any appropriate errors :param response: the JSON response from the request being processed :param method: the HTTP method :param final: boolean flag representing whether or not to continue polling """ status = response['status'] self.logger.debug(status) if status == 'success': return response elif status == 'failure': msgs = response['msgs'] if method == 'POST' and 'login' in msgs[0]['INFO']: raise DynectAuthError(response['msgs']) if method == 'POST': raise DynectCreateError(response['msgs']) elif method == 'GET': raise DynectGetError(response['msgs']) elif method == 'PUT': raise DynectUpdateError(response['msgs']) else: raise DynectDeleteError(response['msgs']) else: # Status was incomplete job_id = response['job_id'] if not final: response = self.wait_for_job_to_complete(job_id) return self._process_response(response, method, True) else: raise DynectQueryTimeout({}) def update_password(self, new_password): """Update the current users password :param new_password: The new password to use """ uri = '/Password/' api_args = {'password': new_password} self.execute(uri, 'PUT', api_args) self.password = self.__cipher.encrypt(new_password) def user_permissions_report(self, user_name=None): """Returns information regarding the requested user's permission access :param user_name: The user whose permissions will be returned. Defaults to the current user """ api_args = dict() api_args['user_name'] = user_name or self.username uri = '/UserPermissionReport/' response = self.execute(uri, 'POST', api_args) permissions = [] for key, val in response['data'].items(): if key == 'allowed': for permission in val: permissions.append(permission['name']) return permissions @property def permissions(self): """Permissions of the currently logged in user""" if self._permissions is None: self._permissions = self.user_permissions_report() return self._permissions @permissions.setter def permissions(self, value): pass def authenticate(self): """Authenticate to the DynectSession service with the provided credentials """ api_args = {'customer_name': self.customer, 'user_name': self.username, 'password': self.__cipher.decrypt(self.password)} try: response = self.execute('/Session/', 'POST', api_args) except IOError: raise DynectAuthError('Unable to access the API host') if response['status'] != 'success': self.logger.error('An error was encountered authenticating to Dyn') raise DynectAuthError(response['msgs']) else: self.logger.info('DynectSession Authentication Successful') def log_out(self): """Log the current session out from the DynECT API system""" self.execute('/Session/', 'DELETE', {}) self.close_session() @property def __auth_data(self): """A dict of the authdata required to authenticate as this user""" return {'customer_name': self.customer, 'user_name': self.username, 'password': self.__cipher.decrypt(self.password)} def __str__(self): """str override""" header = super(DynectSession, self).__str__() return header + force_unicode(': {}, {}').format(self.customer, self.username)