class ProfileResource(Resource): def __init__(self): self.logger = Logger(__name__) def get(self, username): try: # get token from header token = self._get_token_from_header() # identify with token callee_user = Token.identify(token) # get profile info from user username profile = User.get_profile(username, callee_user) # generate response self.logger.info('User profile found for: {}'.format(username)) output = profile # return response return ResponseBuilder.build_response(output) except UserNotFoundException as e: err_msg = "No user found with that name" self.logger.info(err_msg) return ResponseBuilder.build_error_response(err_msg, e.error_code) except (ExpiredTokenException, MissingFieldException, InvalidTokenException) as e: return ResponseBuilder.build_error_response( e.message, e.error_code) def _get_token_from_header(self): return RequestBuilder.get_field_from_header('token')
class LoginResource(Resource): def __init__(self): self.logger = Logger(__name__) self.shared_server_service = SharedServerService() def post(self): try: # get data from request user_data = {} user_data['username'] = self._get_username_from_request() user_data['password'] = self._get_password_from_request() self.logger.info('User data generated. ({})'.format(user_data)) # validate data # ask shared server for authentication service output_dict = self.shared_server_service.get_new_token(user_data) # save token in application server for future use Token.save_new(username=user_data['username'], token=output_dict['token'], expiration_epochs=output_dict['expiresAt']) assert (Token.identify( output_dict['token']) == user_data['username'] ) # confirm it's all good # generate response response = { 'username': user_data['username'], 'token': output_dict } self.logger.info( 'Token received from service. ({})'.format(response)) # return response return ResponseBuilder.build_response(response) except MissingFieldException as mfe: return ResponseBuilder.build_error_response(str(mfe), 400) except InvalidDataException as ide: return ResponseBuilder.build_error_response(str(ide), 400) except NoServerException as nse: return ResponseBuilder.build_error_response(str(nse), 500) except UnexpectedErrorException as uee: return ResponseBuilder.build_error_response(str(uee), 500) except ConnectionFailException as cfe: return ResponseBuilder.build_error_response(str(cfe), 500) def _get_username_from_request(self): return RequestBuilder.get_field_from_request('username') def _get_password_from_request(self): return RequestBuilder.get_field_from_request('password')
class SharedServerService(object): def __init__(self): self.connector = SharedServerConnector() self.logger = Logger(__name__) def create_user(self, user_info): """Receives an UserInfo dict, posts it to sharedserverURL/user and returns the new user's information""" try: new_user = self.connector.create_user(user_info) self.logger.info('User successfully retrieved from connector.') except BadRequestException as bre: # Bad parameters self.logger.error(str(bre)) raise InvalidDataException(bre.message) except UnauthorizedException as ue: # Incorrect server token self.logger.error(str(ue)) raise InvalidDataException(ue.message) except InternalServerErrorException as isee: # External error self.logger.error(str(isee)) raise UnexpectedErrorException(isee.message) except ConnectionError as ce: self.logger.error(str(ce)) raise ConnectionFailException() # Return new user return new_user def get_new_token(self, user_info): """ Processes the request to the shared server to get a new token for a given user.""" try: token = self.connector.get_new_token(user_info) self.logger.info('Token successfully retrieved from connector.') except (BadRequestException, NotFoundException) as e: # Request fail self.logger.error(str(e)) raise InvalidDataException(e.message) except InternalServerErrorException as isee: # External error self.logger.error(str(isee)) raise UnexpectedErrorException(isee.message) except ConnectionError as ce: self.logger.error(str(ce)) raise ConnectionFailException() # Return new token return token def delete_user(self, username): """Asks the shared server for deletion of a user related to user_info.""" try: result = self.connector.delete_user(username) self.logger.info( 'User {} successfully deleted from Shared Server'.format( result)) return result except (BadRequestException, NotFoundException) as e: # Request fail self.logger.error(str(e)) raise InvalidDataException(e.message) except InternalServerErrorException as isee: # External error self.logger.error(str(isee)) raise UnexpectedErrorException(isee.message) except ConnectionError as ce: self.logger.error(str(ce)) raise ConnectionFailException()
class SignUpResource(Resource): def __init__(self): self.logger = Logger(__name__) self.shared_server_service = SharedServerService() def post(self): try: # get data from request user_data = {} user_data['username'] = self._get_username_from_request() user_data['password'] = self._get_password_from_request() self.logger.info('User data generated. ({})'.format(user_data)) # validate data received # fill in accessory fields shared_server_request = dict(user_data) shared_server_request['id'] = int( hashlib.sha256( user_data['username'].encode('utf-8')).hexdigest(), 16) % 10**8 shared_server_request['_rev'] = 0 shared_server_request['applicationOwner'] = "steelsoft" # ask shared server for register service output_dict = self.shared_server_service.create_user( shared_server_request) self.logger.info( "User {} successfully registered in shared server".format( output_dict['username'])) # register at application server pw = user_data.pop('password') # don't save the password new_user_id = User.save_new(user_data) self.logger.info('User ({}) added to DB with id {}'.format( user_data, new_user_id)) # generate response response = {'username': output_dict['username'], 'password': pw} # return response return ResponseBuilder.build_response(response) except MissingFieldException as mfe: return ResponseBuilder.build_error_response( str(mfe), 400) # check status_code except InvalidDataException as ide: return ResponseBuilder.build_error_response( str(ide), 400) # check status_code except NoServerException as nse: return ResponseBuilder.build_error_response( str(nse), 500) # check status_code except UnexpectedErrorException as uee: return ResponseBuilder.build_error_response( str(uee), 500) # check status_code except ConnectionFailException as cfe: return ResponseBuilder.build_error_response( str(cfe), 500) # check status_code def _get_username_from_request(self): return RequestBuilder.get_field_from_request('username') def _get_password_from_request(self): return RequestBuilder.get_field_from_request('password')
class SharedServerConnector(object): def __init__(self): self.success_codes = [200, 201, 204] self.logger = Logger(__name__) my_file = Path('config.cfg') if my_file.is_file(): parser = ConfigParser() file = open('config.cfg') parser.read_file(file) file.close() self.host = parser.get('shared_server', 'host') else: self.host = 'https://picappss.herokuapp.com' def create_user(self, user_info): """Posts a user to the server""" # Generate uri uri = self.host + BASE_PATH + NEW_USER_PATH params = {'ApplicationToken': SERVER_TOKEN} self.logger.info('HTTP Post to URI {} with body {} and params {}'.format(uri, user_info, params)) # Get response response = requests.post(uri, data=json.dumps(user_info), params=params, headers={'Content-Type': 'Application/json'}) self.logger.info('Response received with code {}. ({})'.format(response.status_code, response.text)) # Handle error codes if response.status_code not in self.success_codes: handle_error(response) # Get data user = response.json()['user'] # Check response if user['username'] != user_info['username']: raise InvalidResponseException('Returned username value is different from the posted one.') # Return user object return user def get_new_token(self, user_info): """Gets a token for a given user""" # Generate uri uri = self.host + BASE_PATH + NEW_TOKEN_PATH self.logger.info('HTTP Post to URI {} with body {}'.format(uri, user_info)) # Get response response = requests.post(uri, data=json.dumps(user_info), headers={'Content-Type': 'Application/json'}) self.logger.info('Response received with code {}. ({})'.format(response.status_code, response.text)) # Handle error codes if response.status_code not in self.success_codes: handle_error(response) # Get data token = response.json()['token'] # Check data # if token['expiresAt'] < time.time(): # raise InvalidResponseException('Expiration time is previous to current time!') # Return object return token def delete_user(self, username): """Deletes given user at shared server""" # Generate uri uri = self.host + BASE_PATH + DELETE_USER_BASE_PATH + str(username) self.logger.info('HTTP Delete to URI {}'.format(uri)) # Get response response = requests.delete(uri) self.logger.info('Response received with code {}. ({})'.format(response.status_code, response.text)) # Handle error codes if response.status_code not in self.success_codes: handle_error(response) return username