def process_resource(self, request, response, resource, params): """ This method validate that the user is authenticated if required by the entry point. """ # meta_resource = MetaResource.get_meta_resource(resource) meta_resource = MetaResource._meta_resource_content['data'][ resource.__class__.__name__] if meta_resource is not None: if request.method in meta_resource: method_meta_info = meta_resource[request.method] # Check authentication if 'auth_token_required' in method_meta_info: user_types = method_meta_info['auth_token_required'] # auth_token = ContextInfo.get_context_data('auth_token') auth_token = request.context['auth_token'] # Authenticated? if auth_token is None: raise ServiceException( 'UNAUTHORIZED_NOT_AUTHENTICATED', module=find_module_associated_to_uri(request.path)) # Still valid? if auth_token.is_expired(): raise ServiceException( 'UNAUTHORIZED_SESSION_EXPIRED', module=find_module_associated_to_uri(request.path)) # Has access? if auth_token['type'] not in user_types: raise ServiceException( 'FORBIDDEN', "User doesn't have access to this resource.", module=find_module_associated_to_uri(request.path))
def delete_content_item(content_item_id): """ Delete content item with id :param content_item_id: content item id to be deleted :return: A List of Dictionary with all the deleted item information """ try: # Make sure the content exist content_item_exist = FacadeContent.get_content_by_id( content_item_id) except Exception as e: raise ServiceException('ADMIN_USER_DATABASE_QUERY_FAIL', "Unable to delete content.", str(e)) print(content_item_exist) if not content_item_exist: raise ServiceException('INVALID_CONTENT_ID', 'Content id not found. Invalid content id') try: # Make sure the content exist FacadeContent.delete(content_item_id) except Exception as e: raise ServiceException('ADMIN_USER_DATABASE_QUERY_FAIL', "Unable to delete content.", str(e))
def on_delete(self, req, resp, content_item_id=None): """ :description: Delete a Content :title: Admin - Delete's a Item :auth_token_required: admin :code: 204 DELETED - 0 - The item deleted :code: 400 CONTENT_ITEM_DELETE_FAIL - Item delete fail """ if content_item_id is None: raise ServiceException('CONTENT_ITEM_DELETE_FAIL', 'A content item id needs to be specified') Content.delete_content_item(content_item_id) try: content_item = Content.get_content_from_id(content_item_id) except Exception as e: raise ServiceException('CONTENT_ITEM_DELETE_VALIDATION_FAIL', 'An error occured while validating the content deletion', str(e)) if content_item is not None: raise ServiceException('CONTENT_ITEM_DELETE_FAIL', 'Unable to delete the content') resp.status = HTTP_204
def generate_token_from_credential(login, password): """ Verify the authentication information of a user :param login: The login associated to this user [String, Required] :param password: The password associated to this user [String, Required] :return: An authentication token if credential are valid """ # Identify guest login is_guest = False if not login and not password: is_guest = True # Try to retrieve the user information user = None if not is_guest: try: user = FacadeUser.get_by_login(login) except Exception as e: raise ServiceException( 'USER_DATABASE_QUERY_FAIL', "Fail to load the user current information.", str(e)) if user is None: raise ServiceException('USER_UNKNOWN_INVALID_CREDENTIALS', "Invalid credentials", "Unknown user") # If the password is valid, generate the authentication token if not is_guest and not pbkdf2_sha256.verify(password, user['password']): raise ServiceException('USER_INVALID_PASSWORD_CREDENTIALS', "Invalid credentials", "Invalid password") try: # Build the json payload payload = dict() if is_guest: payload['uuid'] = str(uuid_generator.uuid1()) payload['type'] = UserAuthTokenType.AUTH_TYPE_GUEST else: payload['uuid'] = user['uuid'] payload['type'] = UserAuthTokenType.AUTH_TYPE_USER # Generate the token return Token.generate_token('Auth-Token', payload, auth_token_expiration), payload except Exception as e: raise ServiceException('USER_INVALID_CREDENTIALS', "Invalid credentials", str(e))
def process_request(self, request, response): """ This method extracts and decodes the API-Key and Auth-Token headers. It's called before a request is routed to the proper resource. :param request: HTTP request structure :param response: HTTP response structure :return: """ # ContextInfo.clear_auth_token() auth_token = request.get_header('Auth-Token') if auth_token is None: return # Decode the token try: decoded_token = Token(auth_token) except: raise ServiceException('INVALID_REQUEST', "Failed to decode 'Auth-Token'.", "Check SSL certificate.", module=find_module_associated_to_uri( request.path)) # Make sure it's a Auth-Token if not decoded_token.is_type('Auth-Token'): raise ServiceException('INVALID_FORMAT', "'Auth-Token' is not valid.", "Not a 'Auth-Token'.", module=find_module_associated_to_uri( request.path)) # Validate the format if not decoded_token.contains('uuid'): raise ServiceException('INVALID_FORMAT', "'Auth-Token' is malformed.", "'uuid' is missing.", module=find_module_associated_to_uri( request.path)) if not decoded_token.contains('type'): raise ServiceException('INVALID_FORMAT', "'Auth-Token' is malformed.", "'type' is missing.", module=find_module_associated_to_uri( request.path)) request.context['auth_token'] = decoded_token
def update_content_item(content_item_id, entity): """ Update content item with id :param content_item_id: content item id to be updated :param entity: content to be updated :return: A List of Dictionary with all the updated item information """ try: # Make sure the content exist content_item = FacadeContent.get_content_by_id(content_item_id) except Exception as e: raise ServiceException('CONTENT_DATABASE_QUERY_FAIL', "Unable to update content.", str(e)) if not content_item: raise ServiceException('INVALID_CONTENT_ID', 'Content id not found. Invalid content id') # Retrieve the user current information try: content = FacadeContent.get_content_info_by_id(content_item_id) except Exception as e: raise ServiceException( 'CONTENT_DATABASE_LOAD_QUERY_FAIL', "Fail to load the Content current information.", str(e)) # Update the content new information over the current information if entity.member_exist('title'): content['title'] = entity['title'] if entity.member_exist('popularity'): content['popularity'] = entity['popularity'] if entity.member_exist('director'): content['director'] = entity['director'] if entity.member_exist('genre'): content['genre'] = entity['genre'] if entity.member_exist('imdb_score'): content['imdb_score'] = entity['imdb_score'] try: # Make sure the content exist FacadeContent.update(content_item_id, content) except Exception as e: raise ServiceException('ADMIN_CONTENT_DATABASE_QUERY_FAIL', "Unable to update content.", str(e))
def add_content(entity): """ Add content to content list data :param entity: content to be added :return: A List of Dictionary with all the added item information """ try: FacadeContent.add(entity) print("ADDING CONTENT LIST") except Exception as e: raise ServiceException('CONTENT_DATABASE_QUERY_FAIL', "Unable to add content.", str(e))
def get_content_from_id(content_item_id): """ Get content item with id :param content_item_id: content item id to be fetched :return: A Entity of Dictionary with all the item information """ try: # Make sure the content exist content = FacadeContent.get_content_info_by_id(content_item_id) return content except Exception as e: raise ServiceException('ADMIN_USER_DATABASE_QUERY_FAIL', "Unable to fetch content item.", str(e))
def get_content_list(search): """ Get a content list data :param search: search parameter :return: A List of Dictionary with all the item information """ try: # Make sure the user exist content_list = FacadeContent.get_list(search) print("RETURNING CONTENT LIST") return json.dumps(content_list) except Exception as e: raise ServiceException('USER_DATABASE_QUERY_FAIL', "Unable to fetch content.", str(e))
def create_user(entity): """ Create a new user :param entity: A Entity object with required values email: The email associated to this user [String, Required] password: The password associated to this user [String, Required] email: The email associated to this user [String, Required] firstname: The first name of the user [String, Required] lastname: The last name of the user [String, Required] :return: """ print("In bl | User | create User method") # Make sure the user does not already exist try: is_user_exists = FacadeUser.is_exist_by_login(entity['login']) except Exception as e: raise ServiceException( 'USER_DATABASE_QUERY_FAIL', "Fail to verify if the user already exist.", str(e)) if is_user_exists: raise ServiceException('USER_ALREADY_EXIST_FAIL', "User already exists in the database.") # Validate email address if not validate_email(entity['login']): raise ServiceException('USER_CREATION_EMAIL_FAIL', "Email doesn't meet requirements.") # Validate the password if not check_password(entity['password']): raise ServiceException('USER_CREATION_PASSWORD_FAIL', "Password doesn't meet requirements.") entity['uuid'] = str(uuid_generator.uuid1()) # Hash the user password try: entity['password'] = pbkdf2_sha256.encrypt(entity['password'], rounds=2000, salt_size=16) except: raise ServiceException( 'USER_CREATION_ENCRYPTION_FAIL', "The encryption of the password has failed.") # Create a new user using the dal try: FacadeUser.add(entity) except Exception as e: raise ServiceException('USER_DATABASE_CREATION_QUERY_FAIL', "The creation of the user has failed.", str(e))
def get_user_from_login(login): """ Get the user information :param login: The login of the user [String, Required] :return: If not user found, return None :return: If user found, return a Entity with the user information user_id: The uuid associated to this user [String] email: The email associated to this user [String] password: The password associated to this user [String] email: The email associated to this user [String] firstname: The first name of the user [String] lastname: The last name of the user [String] """ try: # Make sure the user exist if not FacadeUser.is_exist_by_login(login): return None return FacadeUser.get_by_login(login) except Exception as e: raise ServiceException('USER_DATABASE_QUERY_FAIL', "Unable to load the user information.", str(e))
def on_put(self, req, resp, content_item_id=None): """ :description: Update a Content :title: Admin - Update a Item :auth_token_required: admin :input_body:: { "type": "object", "properties": { "title": { "type": "string", "description": "title of the content" }, "genre": { "type": "array", "description": "The genre of the content" }, "director": { "type": "string", "description": "The director of the media" }, "idbm_score": { "type": "integer", "description": "The imdb score of the content" }, "popularity": { "type": "integer", "description": "The popularity of the content" } }, } """ if content_item_id is None: raise ServiceException('CONTENT_ITEM_UPDATE_FAIL', 'A content item id needs to be specified') # Extract the 'body' from the request entity = Entity(req.context['body']) if not req.context['body']: raise ServiceException('CONTENT_EMPTY_BODY', "No data provided for update.") Content.update_content_item(content_item_id, entity) # Retrieve the updated content information try: content_item = Content.get_content_from_id(content_item_id) except Exception as e: raise ServiceException('CONTENT_UPDATE_FAIL', "Unable to load the content information that has just been updated.", str(e)) if not content_item: raise ServiceException('CONTENT_UPDATE_FAIL', "Unable to load the content information that has just been updated.") resp.status = HTTP_200 resp.body = json.dumps(content_item)
def on_post(self, req, resp): """ :description: Create user account :title: Create user account :input_body:: { "type": "object", "properties": { "firstname": { "type": "string", "description": "The user’s first name" }, "lastname": { "type": "string", "description": "he user’s last name" }, "email": { "type": "string", "description": "he user’s account email address" }, "password": { "type": "string", "description": "The user’s password" } }, "required": ["email", "password"] } :output_body:: { "type": "object", "properties": { "firstname": { "type": "string", "description": "The user’s first name" }, "lastname": { "type": "string", "description": "he user’s last name" }, "email": { "type": "string", "description": "he user’s account email address" } }, "required": ["firstname", "lastname", "email"] } """ # Extract the 'body' from the request entity = Entity(req.context['body']) # Make sure the entity has all required fields entity.add_member('login', entity['email']) # Process the request User.create_user(entity) # Retrieve the new user information user_info = User.get_user_from_login(entity.get('login')) if not user_info: raise ServiceException( 'USER_CREATION_FAIL', "Unable to load the user information that has just been created." ) # Remove the unnecessary fields from the entity user_info.remove_member('uuid') user_info.remove_member('email') user_info.remove_member('password') # Fill the response resp.status = HTTP_201 resp.body = json.dumps(user_info)
def on_post(self, req, resp): """ :description: Login to admin session :title: Login :input_body:: { "type": "object", "properties": { "email": { "type": "string", "description": "The user’s registered account email address" }, "password": { "type": "string", "description": "The user’s password" } }, "required": ["email", "password"] } :output_body:: { "type": "object", "properties": { "auth_token": { "type": "string", "description": "The user authentication token" } }, "required": ["auth_token"] } """ # Extract the 'body' from the request entity = Entity(req.context['body']) # Make sure the entity has all required fields entity.add_member('login', entity['email']) if not entity['login']: raise ServiceException('ADMIN_CREATION_EMAIL_FAIL', "Login/Email required.") if not entity['password']: raise ServiceException('ADMIN_CREATION_PASSWORD_FAIL', "Password Required") # Process the request auth_token, self._token_payload = Admin.generate_token_from_credential( entity['login'], entity['password']) if not auth_token: raise ServiceException('ADMIN_USER_INVALID_CREDENTIALS_TOKEN', "Invalid credentials", "Token generation failed") # Fill the response resp.status = HTTP_200 resp.body = json.dumps({'auth_token': auth_token})