Пример #1
0
    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)
Пример #2
0
    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')
Пример #3
0
    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
Пример #4
0
    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
Пример #5
0
    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']
        }
Пример #6
0
    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)
Пример #7
0
    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
Пример #8
0
    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)
Пример #9
0
    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
Пример #10
0
    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)
Пример #11
0
    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!')
Пример #12
0
    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)
Пример #13
0
    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)
Пример #14
0
    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!')
Пример #15
0
    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)