def get(self): """ Sends an e-mail to the user to make him create a new password. Request Parameters ---------- email : string User's e-mail Example: [email protected] Returns ------- None Sends an e-mail with a link to create a new password. """ logging.info('AuthForgotPassword.get()') email = request.args.get('email') logging.info('AuthForgotPassword.get() - email: %s', email) # validate request body data, status = validate({'email': email}, 'forgot_password') if status is False: logging.error('AuthForgotPassword.get() - errors: %s', data) raise BadRequest('Invalid e-mail format!') token = auth_forgot_password_business.send_an_email_to(email) if FLASK_ENV == 'development': return {'token': token} return Response(status=200)
def select_item(self, item_id=None, collection=None): logging.info( f'MySQLConnection.select_item - item_id: {item_id}; collection: {collection}' ) where = [] params = {} if item_id is not None: where.append('id=:item_id') params['item_id'] = item_id if collection is not None: where.append('collection=:collection') params['collection'] = collection where = ' AND '.join(where) if where != '': where = f'WHERE {where}' query = f'SELECT * FROM stac_item {where};' logging.info(f'MySQLConnection.select_item - query: {query}') # execute the query and return the result return self.execute(query, params).to_dict('records')
def send_an_email_to(self, email): """Sends an e-mail to a user.""" user = self.db_ps_register.select_from_user(email=email) # if an empty list (i.e. user == []), then raise an exception if not user: logging.error( 'AuthForgotPasswordBusiness.send_an_email_to() - e-mail was not found.' ) raise NotFound('E-mail was not found.') token = token_urlsafe(32) # save the token in the database self.db_ps_register.insert_into_security(user[0]['username'], token) link = URL_CATALOG_RESET_PASSWORD + '?token={}'.format(token) logging.info( 'AuthForgotPasswordBusiness.send_an_email_to() - link: %s', link) send_email_forgot_password(email, link) return token
def __thread_send_email(email_subject, email_from, email_from_password, email_to, email_content, email_smtp_host, email_smtp_port): msg = Message() msg['Subject'] = email_subject msg['From'] = email_from msg['To'] = email_to msg.add_header('Content-Type', 'text/html') msg.set_payload(email_content) logging.info('send_email() - sending an e-mail to `%s`...', email_to) try: s = SMTP(host=email_smtp_host, port=email_smtp_port) s.starttls() s.login(msg['From'], email_from_password) s.sendmail(msg['From'], [msg['To']], msg.as_string()) s.quit() logging.info( 'send_email() - e-mail to `%s` has been sent successfully!', email_to) except SMTPException as error: logging.error('send_email() - unable to send an e-mail to `%s`.', email_to) logging.error('send_email() - error: `%s`.', error) raise error
def post(self): """ Logs a user into the system Request Parameters ---------- request.data : bytes JSON in bytes format that contains email and password information of a user Example: b'{"email": "*****@*****.**", "password": "******"}' Returns ------- string Token related to the logged user """ logging.info('AuthLogin.post()\n') body = request.data if body == b'': raise BadRequest('Request data is empty.') # get request data (bytes) and convert it to dict body = loads(body.decode('utf-8')) # validate request body data, status = validate(body, 'login') if status is False: logging.error('AuthLogin.get() - errors: %s', data) raise BadRequest(data) logging.info('AuthLogin.post() - data[\'email\']: %s', data['email']) # validate user login token, user_info = auth_login_business.login(data['email'], data['password']) # logging.info('AuthLogin.post() - user_info[username]: %s', user_info['username']) # logging.info('AuthLogin.post() - user_info[email]: %s', user_info['email']) # if there is not a token (i.e. empty string), then raise an error if not token or not user_info: raise InternalServerError('Error during login.') return { "access_token": token, "username": user_info['username'], "name": user_info['name'], "email": user_info['email'], "password": data['password'] }
def get(self, path): """ Returns ------- image/tif """ logging.info('get - path: %s', path) logging.info('get - request.remote_addr: %s', request.remote_addr) ips_string = request.headers.environ.get('HTTP_X_FORWARDED_FOR', request.remote_addr) logging.info('get - ips_string: %s', ips_string) ips_list = [ip.strip() for ip in ips_string.split(',')] # logging.debug('get - request.authorization: %s', request.authorization) # logging.debug('get - request.args: %s', request.args) # Nginx credentials # if request.authorization: # credentials = request.authorization # username = credentials.username # password = credentials.password # Url credentials if not request.args.get('email'): logging.warning('get - `email` parameter is required!') raise BadRequest('`email` parameter is required!') logging.info(f'get - BASE_PATH: {BASE_PATH}') # get the path to the file # e.g: url = '/data/TIFF/.../CBERS_4_MUX_20191022_154_126_L2.tif' urn = f"{BASE_PATH}/{path}" parameters = { 'email': request.args.get('email'), 'urn': urn, 'ips_list': ips_list } logging.info(f'get - parameters: {parameters}') self.download_business.insert_statistics(**parameters) uri = URL_DOWNLOAD + urn logging.debug(f'get - uri: {uri}') return redirect(uri)
def insert_into_address(self, user): """Inserts address into the database.""" query = ''' INSERT INTO address ( cep, street, number, city, district, state, country, complement ) VALUES ( :cep, :street, :number, :city, :district, :state, :country, :complement ) RETURNING id; ''' address_id = self.execute(query, user['address'], is_transaction=True) logging.info(f'insert_into_address - address_id: {address_id}') return address_id
def insert_into_location(self, location): """Inserts location into the database.""" logging.info(f'insert_into_location - location: {location}') # just insert the new location if the IP has not already been added in the database query = ''' INSERT INTO location ( ip, longitude, latitude, city, district, region, region_code, country, country_code, continent, continent_code, zip_code, time_zone ) SELECT :ip, :longitude, :latitude, :city, :district, :region, :region_code, :country, :country_code, :continent, :continent_code, :zip_code, :time_zone WHERE (SELECT COUNT(ip) FROM location WHERE ip = :ip) = 0; ''' self.execute(query, location, is_transaction=True)
def login(self, email, password): """Checks if there is a user in the database and return his token.""" logging.info(f'login - email: {email}') # logging.info(f'login - password: {password}') result = self.db_ps_register.select_from_user(email=email, password=password) # logging.info(f'login - result: {result}') if not result: raise NotFound('E-mail or Password was not found.') # get the only one available result result = result[0] # logging.info(f"login - result: {result}") logging.info(f"login - E-mail `{result['email']}` has been found.") return jwt_encode(result), result
def insert_user(self, user_data): """Inserts a user into database and it returns his e-mail.""" # just remove `password` field to log the parameter password = user_data.pop('password') logging.info(f"insert_user - user_data: {user_data}") user_data['password'] = password # check if user exists by his e-mail user = self.db_ps_register.select_from_user(email=user_data['email']) if user: logging.info( f"insert_user - E-mail has already been registered! E-mail: `{user_data['email']}`" ) raise Conflict( f"E-mail has already been registered! E-mail: `{user_data['email']}`" ) # check if user exists by his username user = self.db_ps_register.select_from_user( username=user_data['username']) if user: logging.info( f"insert_user - Username has already been registered! Username: `{user_data['username']}`" ) raise Conflict( f"Username has already been registered! Username: `{user_data['username']}`" ) # default value to `address_id`, if there is not an `address_id`, then insert NULL user_data['address_id'] = None # if there is 'address' field, then try to insert address # information in the database if 'address' in user_data: # if there are properties inside 'address' field, # then insert the address in the database if user_data['address']: logging.info(f"insert_user - address: {user_data['address']}") address_id = self.db_ps_register.insert_into_address(user_data) user_data['address_id'] = address_id # remove 'address' field from dict del user_data['address'] return self.db_ps_register.insert_into_user(user_data)
def reset_password(self, email, password, token, **kwargs): """Resets a user password.""" logging.info('reset_password - email: %s', email) # logging.debug('reset_password - password: %s', password) logging.info('reset_password - token: %s', token) user = self.db_ps_register.select_from_user(email=email) # if an empty list (i.e. user == []), then raise an exception if not user: logging.error('reset_password - e-mail was not found.') raise NotFound('E-mail was not found.') username = user[0]['username'] security = self.db_ps_register.select_from_security(username=username, token=token) logging.info('reset_password - security: %s', security) # if an empty list (i.e. user == []), then raise an exception if not security: logging.error('reset_password - token was not found.') raise NotFound('Token was not found.') # update the user password self.db_ps_register.update_user(username=username, password=password) logging.info( 'reset_password - user password has been reset successfully!') # delete the token from the database self.db_ps_register.delete_from_security(username=username, token=token) logging.info( 'reset_password - user token has been removed successfully!')
def post(self): """ Resets the user password. Request Parameters ---------- request.data : bytes JSON in bytes format that contains email, password and token information of a user Example: b'{"email": "*****@*****.**", "password": "******", "token": "123456"}' Returns ------- None """ logging.info('AuthResetPassword.get()') body = request.data if body == b'' or body == b'{}': logging.error('AuthResetPassword.get() - request data is empty.') raise BadRequest('Request data is empty.') # get request data (bytes) and convert it to dict body = loads(body.decode('utf-8')) logging.info('AuthResetPassword.get() - body: %s', body) # validate request body data, status = validate(body, 'reset_password') if status is False: logging.error('AuthResetPassword.get() - errors: %s', data) raise BadRequest('Invalid data information.') auth_reset_password_business.reset_password(**body) return Response(status=200)
def delete(self, username=None): """ Deletes a user into the database based on his username passed as argument. Request Arguments ---------- username : string Username Returns ------- None Nothing """ if username is None: raise BadRequest('Username can not be empty.') logging.info(f'User.delete - username: {username}`') # get Authorization header and extract just the token authorization = request.headers.get('Authorization')[7:] logging.info(f'User.delete - authorization header: {authorization}`') # decode the token decoded_auth = jwt_decode(authorization) logging.info(f'User.delete - decoded_auth: {decoded_auth}`') # if the logged user is trying to delete another user, then raise an error, # because a user can delete just himself if decoded_auth['username'] != username: logging.info(f"User.delete - user `{decoded_auth['username']}` is trying to delete `{username}`.") raise BadRequest('Logged user is not allowed to delete another one.') # delete user user_business.delete_user(username)
def insert_statistics(self, email=None, urn=None, ips_list=None): """Inserts statistics in the database""" logging.info(f'insert_statistics - email: {email}') logging.info(f'insert_statistics - urn: {urn}') logging.info(f'insert_statistics - ips_list: {ips_list}') # check if user exists in the database user = self.db_ps_register.select_from_user(email=email) # logging.info(f'insert_statistics - user: \n{user}\n') if not user: raise Forbidden(f'Invalid e-mail: `{email}`') metadata = decode_path(urn) logging.info(f'insert_statistics - metadata: {metadata}') item_name = build_item(metadata) logging.info(f'insert_statistics - item_name: {item_name}') collection = build_collection(metadata) logging.info(f'insert_statistics - collection: {collection}') # check if item exists in the postgres database. item = self.db_ps_catalog.select_from_items( # it checks using `item_name` and `collection` to be faster. # a search just by `asset` is slow. # the unique key is `item name` + `collection`, # because one item can be part of N collections item_name=item_name, collection=collection, asset=urn) logging.info(f'insert_statistics - item: {item}') if not item: # original behavior # raise NotFound(f'Not found an item by asset: `{urn}`') logging.info( f'insert_statistics - {item_name} item has not been found inside new db, ' f'then now I am going to look for it inside old db...') ################################################################################ # if an item has not been found inside new db, # then I look for it inside the old db # build old item name old_item_name = self.old_db.build_old_item(metadata, urn) logging.info(f'insert_statistics - old_item_name: {old_item_name}') # look for the item inside old db old_item = self.old_db.select_item(item_id=old_item_name, collection=collection) if not old_item: logging.info( f'insert_statistics - {old_item_name} item has not been found ' 'inside old db as well... ') raise NotFound(f'Not found an item by asset: `{urn}`') # add `name` property with the item name using the new format old_item[0]['name'] = item_name logging.info(f'insert_statistics - old_item: {old_item}') # replace old item as new item item = old_item ################################################################################ item = item[0] location_raw = self.get_location(ips_list) logging.info(f'insert_statistics - location_raw: {location_raw}') # I search if the chose location has already been added in the database location = self.db_ps_register.select_from_location(location_raw['ip']) logging.info(f'insert_statistics - location: {location}') # if the location has not been added in the database, then I insert it once if not location: # save the new location self.db_ps_register.insert_into_location(location_raw) logging.info( 'insert_statistics - location has been inserted successfully!') # save the statistics self.db_ps_register.insert_into_download(item_id=item['name'], collection=item['collection'], path=urn, user=user[0], location=location_raw) logging.info( 'insert_statistics - statistics have been inserted successfully!')
def get_location(self, ips_list): """ Method to get the client's location return: location (dict): location information """ logging.info('get_location') logging.info('get_location - ips_list: %s', ips_list) for ip in ips_list: logging.info(f'get_location - ip: {ip}') # check if the IP exists inside the database in order to save requests location = self.db_ps_register.select_from_location(ip) logging.info(f'get_location - location: {location}') # if the location has already been added to the database, then I return it, [...] if location: return location[0] # [...] else I search the location by IP once try: # try to get the location based with a public IP location = CDSRIP.get_location(ip) logging.info('get_location - public IP was found: %s', ip) return location except (CDSRIPException, KeyError): # if an exception occurs, a public IP was not found, then try again with another IP continue logging.info('get_location - public IP was not found, then ' f'private IP was chose: {request.remote_addr}') # if there is not one public IP, return a location object based on public IP, # in other words, there is not any location information return CDSRIP.get_location_structure(request.remote_addr)