Beispiel #1
0
def check_existance_and_fetch_image(image_id: str, user_hash: str) -> tuple:
    """checks if the image_id is in the database for the user and returns it.

    :param image_id: image_id to find
    :type image_id: str
    :param user_hash: hash that identifies a user
    :type user_hash: str
    :return: Success, error message, Image
    :rtype: tuple
    """

    # Verify input types
    t_ok, t_err = is_type_ok(image_id, "str")
    if t_ok is False:
        return False, t_err, None

    t_ok, t_err = is_type_ok(user_hash, "str")
    if t_ok is False:
        return False, t_err, None

    if db.image_exists(image_id, user_hash) is False:
        return False, 'No image id: ' + image_id + ' found for the user', None
    else:
        image = db.get_image(image_id, user_hash)
        if image is not None:
            return True, '', image
        else:
            return False, 'Error fetching image' + image_id, None
Beispiel #2
0
def get_single_image(image_id: str, user_hash: str) -> dict:
    """get single image from server

    :param image_id: id of the image to download
    :type image_id: str
    :param user_hash: hash identifying user
    :type user_hash: str
    :return: dictionary with the info. see protocol
    :rtype: dict
    """
    # Validate image_id type
    t_ok, t_err = is_type_ok(image_id, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate user_hash type
    t_ok, t_err = is_type_ok(user_hash, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    d = {
        'image_ids': [image_id],
        'format': 'PNG',
        'user_hash': user_hash
    }
    try:
        r = requests.get(api_host+"/api/download/", json=d)
        return json.loads(r.text)
    except:
        return {
            'success': False,
            'error_msg': 'Could not connect to server',
        }
Beispiel #3
0
def get_download_images(
    image_ids: list,
    im_format: str,
    user_hash: str
) -> dict:
    """run a get request to download images

    :param image_ids: list of ids to download
    :type image_ids: list
    :param im_format: format to download
    :type im_format: str
    :param user_hash: hash identifying user
    :type user_hash: str
    :return: dictionary with info. see protocol
    :rtype: dict
    """
    # Validate image_ids type
    t_ok, t_err = is_type_ok(image_ids, "list[str, ...]")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate im_format type
    t_ok, t_err = is_type_ok(im_format, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate user_hash type
    t_ok, t_err = is_type_ok(user_hash, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    d = {
        'image_ids': image_ids,
        'format': im_format,
        'user_hash': user_hash
    }
    try:
        r = requests.get(api_host+"/api/download/", json=d)
        return json.loads(r.text)
    except:
        return {
            'success': False,
            'error_msg': 'Could not connect to server',
        }
Beispiel #4
0
def upload_image(image_b64s: str, filename: str, user_hash: str) -> dict:
    """upload a single image to the server

    :param image_b64s: image data as a base 64 string
    :type image_b64s: str
    :param filename: filename for the image
    :type filename: str
    :param user_hash: hash identifying the user
    :type user_hash: str
    :return: dictionary with info. see protocol
    :rtype: dict
    """
    # Validate image_b64s type
    t_ok, t_err = is_type_ok(image_b64s, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate filename type
    t_ok, t_err = is_type_ok(filename, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate user_hash type
    t_ok, t_err = is_type_ok(user_hash, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    d = {
        'filename': filename,
        'user_hash': user_hash,
        'description': filename,
        'data': image_b64s,
    }
    try:
        r = requests.post(api_host+"/api/upload/image", json=d)
        return json.loads(r.text)
    except:
        return {
            'success': False,
            'error_msg': 'Could not connect to server',
        }
Beispiel #5
0
def edit_description(image_id: str, new_desc: str, user_hash: str) -> dict:
    """edit description of an image

    :param image_id: id of the image to edit
    :type image_id: str
    :param new_desc: new description for the image
    :type new_desc: str
    :param user_hash: hash identifying a user
    :type user_hash: str
    :return: dictionary with info. see protocol
    :rtype: dict
    """
    # Validate image_id type
    t_ok, t_err = is_type_ok(image_id, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate new_desc type
    t_ok, t_err = is_type_ok(new_desc, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate user_hash type
    t_ok, t_err = is_type_ok(user_hash, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    data = {
        'image_id': image_id,
        'description': new_desc,
        'user_hash': user_hash
    }
    try:
        r = requests.post(api_host + '/api/edit/description', json=data)
        return json.loads(r.text)
    except:
        return {
            'success': False,
            'error_msg': 'Could not connect to server',
        }
Beispiel #6
0
def upload_zip(zip_b64s: str, filename: str, user_hash: str) -> dict:
    """upload multiple images as a zip

    :param zip_b64s: zip file data as a base 64 string
    :type zip_b64s: str
    :param filename: filename of the zip
    :type filename: str
    :param user_hash: hash identifying a user
    :type user_hash: str
    :return: dictionary with info. see protocol
    :rtype: dict
    """
    # Validate zip_b64s type
    t_ok, t_err = is_type_ok(zip_b64s, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate filename type
    t_ok, t_err = is_type_ok(filename, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate user_hash type
    t_ok, t_err = is_type_ok(user_hash, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    d = {
        'filename': filename,
        'user_hash': user_hash,
        'data': zip_b64s,
    }
    try:
        r = requests.post(api_host+"/api/upload/zip", json=d)
        return json.loads(r.text)
    except:
        return {
            'success': False,
            'error_msg': 'Could not connect to server',
        }
Beispiel #7
0
def get_image_info(user_hash: str) -> dict:
    """ get information of all the user images

    Get the following information:
    ['filename', 'img_format', 'timestamp', 'size', 'description']
    from all the images that belong the the user.

    :param user_hash: hash that identifies a user
    :type user_hash: str
    :return: dictionary with success(bool), error_msg(str)
        or the images information
    :rtype: dict
    """

    # Verify input types
    t_ok, t_err = is_type_ok(
        user_hash,
        "str"
    )

    if t_ok is False:
        return {
            'success':	False,
            'error_msg': t_err,
        }

    # Log Action
    logging.info("{} - {} - CALLED: {} INPUT_ARGS: {}".format(
        user_hash,
        datetime.now(),
        'get_image_info',
        ''
    )
    )

    # fetch all images for the user
    images = db.get_all_user_images(user_hash)

    # create a dictionary with all the image info
    out_dict = {}
    if images is not None:
        for img in images:
            out_dict[str(img._id)] = {
                'filename': img.filename,
                'img_format': img.img_format,
                'timestamp': img.timestamp,
                'size': img.size,
                'description': img.description,
            }

    # return the info
    return out_dict
Beispiel #8
0
def get_images_info(user_hash: str) -> dict:
    """get information of all the images that belong to the user

    :param user_hash: hash identifying a user
    :type user_hash: str
    :return: dictionary with all the info. see protocol
    :rtype: dict
    """
    # Validate user_hash type
    t_ok, t_err = is_type_ok(user_hash, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    try:
        r = requests.get(api_host + '/api/image_info/' + user_hash)
        return json.loads(r.text)
    except:
        return {
            'success': False,
            'error_msg': 'Could not connect to server',
        }
Beispiel #9
0
def apply_algorithm(
    image_id: str,
    algorithm: str,
    im_format: str,
    out_filename: str,
    user_hash: str
) -> dict:
    """Apply an image processing algorithm ot an image

    :param image_id: id of the image to process
    :type image_id: str
    :param algorithm: algorithm to apply
    :type algorithm: str
    :param im_format: format of the output image
    :type im_format: str
    :param out_filename: name of the output image
    :type out_filename: str
    :param user_hash: hash identifying a user
    :type user_hash: str
    :return: dictionary with info. see protocol
    :rtype: dict
    """
    # Validate image_id type
    t_ok, t_err = is_type_ok(image_id, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate algorithm type
    t_ok, t_err = is_type_ok(algorithm, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate im_format type
    t_ok, t_err = is_type_ok(im_format, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate out_filename type
    t_ok, t_err = is_type_ok(out_filename, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    # Validate user_hash type
    t_ok, t_err = is_type_ok(user_hash, "str")
    if t_ok is False:
        return {'success':	False, 'error_msg': t_err}

    d = {
        'image_id': image_id,
        'algorithm': algorithm,
        'out_image_format': im_format,
        'out_image_filename': out_filename,
        'user_hash': user_hash,
    }
    try:
        r = requests.post(api_host+"/api/image_process", json=d)
        return json.loads(r.text)
    except:
        return {
            'success': False,
            'error_msg': 'Could not connect to server',
        }
Beispiel #10
0
def image_process(image_process_dict: dict) -> dict:
    """ Apply processing algorithm to an image

    This function validates input data, fetches an image,
    applies a processing algorithm to it, converts it to
    a new format and stores it in the database as a new
    image with a new image filename,


    :param image_process_dict: dictionary with all the
        required information
    :type image_process_dict: dict
    :return: dictionary with
        success(bool), error_msg(str)
    :rtype: dict
    """
    # Verify input types
    t_ok, t_err = is_type_ok(
        image_process_dict,
        """
        dict{
            'image_id': str,
            'algorithm':str,
            'out_image_format': str,
            'out_image_filename':str,
            'user_hash': str,
        }
        """
    )
    if t_ok is False:
        return {
            'success':	False,
            'error_msg': t_err,
        }

    # Log Action
    logging.info("{} - {} - CALLED: {} INPUT_ARGS: {}".format(
        image_process_dict['user_hash'],
        datetime.now(),
        'image_process',
        ";".join(
            [
                'image_id: ' + image_process_dict['image_id'],
                'algorithm: ' + image_process_dict['algorithm'],
                'out_image_format: ' + image_process_dict['out_image_format'],
                'out_image_filename: ' +
                image_process_dict['out_image_filename'],
            ]
        )
    )
    )

    image_id = image_process_dict['image_id']
    algorithm = image_process_dict['algorithm']
    out_image_format = image_process_dict['out_image_format']
    out_image_filename = image_process_dict['out_image_filename']
    user_hash = image_process_dict['user_hash']

    # Check if algorithm is correct
    if img_proc.is_valid_algorithm(algorithm) is False:
        return {
            'success': False,
            'error_msg': 'Unknown algorithm: ' + algorithm,
            'processing_time': 0.0
        }

    # Check if image exists and fetch it
    result, errmsg, in_image = check_existance_and_fetch_image(
        image_id,
        user_hash
    )

    if result is False:
        return {
            'success': False,
            'error_msg': errmsg,
            'processing_time': 0.0
        }

    # Start measuring ellapsed time
    start_time = datetime.now()

    image_fio = b64s_to_fio(in_image.data)

    # Extract size from image data
    im_size = img_proc.get_image_size(image_fio)

    # Transform image using algorithm
    out_image_fio = img_proc.transform_image(image_fio, algorithm)

    # Convert image format
    out_image_fio = img_proc.format_convert(out_image_fio, out_image_format)

    result = db.add_image(
        filename=out_image_filename,
        img_format=out_image_format,
        description='Created using ' + algorithm + ' on ' + in_image.filename,
        size=im_size,
        timestamp=datetime.now(),
        data=fio_to_b64s(out_image_fio),
        user_hash=user_hash
    )

    if result is False:
        return {
            'success': False,
            'error_msg': 'Error adding image' +
            out_image_filename +
            ' to database\n',
            'processing_time': 0.0
        }

    # Stop measuring ellapsed time
    end_time = datetime.now()
    ellapsed_time = end_time-start_time

    return {
        'success': True,
        'error_msg': '',
        'processing_time': ellapsed_time.total_seconds()
    }
Beispiel #11
0
def download(download_images_dict: dict) -> dict:
    """ download single or multiple images

    To download a single or multiple images from the server,
    the user calls this api function through the RESTapi.
    This function validates the input dict and calls:
    download_signle_image or download_multiple_images

    And returns a dicionary with success and error message

    :param download_images_dict: dictionary with all the
        required info (see protocol)
    :type download_images_dict: dict
    :return: dictionary with
        success(bool), error_msg(str)
    :rtype: dict
    """

    # Verify input types
    t_ok, t_err = is_type_ok(
        download_images_dict,
        """
        dict{
            'image_ids': list[str...],
            'format': str,
            'user_hash': str
        }
        """
    )

    if t_ok is False:
        return {
            'success':	False,
            'error_msg': t_err,
        }

    # Log Action
    logging.info("{} - {} - CALLED: {} INPUT_ARGS: {}".format(
        download_images_dict['user_hash'],
        datetime.now(),
        'download',
        ";".join(
            [
                'image_ids: ' + ','.join(download_images_dict['image_ids']),
                'format: ' + download_images_dict['format']
            ]
        )
    )
    )

    # Extract image id, format and user hash from input data
    img_ids = download_images_dict['image_ids']
    img_format = download_images_dict['format']
    user_hash = download_images_dict['user_hash']

    if len(img_ids) == 1:
        return download_signle_image(
            image_id=img_ids[0],
            image_format=img_format,
            user_hash=user_hash
        )
    else:
        return download_multiple_images(
            image_ids=img_ids,
            image_format=img_format,
            user_hash=user_hash
        )
Beispiel #12
0
def edit_image_filename(edit_image_filename_dict: dict) -> dict:
    """ edit the filename of an image

    This function validates the input dict, fetches the image
    and changes its filename.
    And returns a dicionary with success and error message
    TODO: Add this function to the client and protocol

    :param edit_image_filename_dict: dictionary with all the
        required info (see protocol)
    :type edit_image_filename_dict: dict
    :return: dictionary with
        success(bool), error_msg(str)
    :rtype: dict
    """

    # Verify input types
    t_ok, t_err = is_type_ok(
        edit_image_filename_dict,
        """
        dict{
            'image_id': str,
            'filename': str,
            'user_hash': str
        }
        """
    )

    if t_ok is False:
        return {
            'success':	False,
            'error_msg': t_err,
        }

    # Log Action
    logging.info("{} - {} - CALLED: {} INPUT_ARGS: {}".format(
        edit_image_filename_dict['user_hash'],
        datetime.now(),
        'edit_image_filename',
        ";".join(
            [
                'image_id: ' + edit_image_filename_dict['image_id'],
                'filename: ' + edit_image_filename_dict['filename']
            ]
        )
    )
    )

    # Extract image id and user hash from input data
    image_id = edit_image_filename_dict['image_id']
    user_hash = edit_image_filename_dict['user_hash']

    # Check if image id exists (and fetch it)
    result, errmsg, image = check_existance_and_fetch_image(
        image_id,
        user_hash
    )

    if result is False:
        return {
            'success': False,
            'error_msg': errmsg,
        }

    # Edit Description
    image.filename = edit_image_filename_dict['filename']

    # Save image
    try:
        image.save()
    except:
        return {
            'success': False,
            'error_msg': 'Could not save edited image',
        }
    return {
        'success': True,
        'error_msg': '',
    }
Beispiel #13
0
def upload_image(upload_img_dict: dict) -> dict:
    """ upload single image

    this function receives an image file in base64 string
    and adds it to the database.

    :param upload_img_dict: dictionary with all the info
    :type upload_img_dict: dict
    :return: dictionary with success(bool), error_msg(str)
    :rtype: dict
    """

    # Verify input types
    t_ok, t_err = is_type_ok(
        upload_img_dict,
        """
        dict{
            'filename': str,
            'description': str,
            'data': str,
            'user_hash': str
        }
        """
    )

    if t_ok is False:
        return {
            'success':	False,
            'error_msg': t_err,
        }

    # Log Action
    logging.info("{} - {} - CALLED: {} INPUT_ARGS: {}".format(
        upload_img_dict['user_hash'],
        datetime.now(),
        'upload_image',
        ";".join(
            [
                'filename: ' + upload_img_dict['filename'],
                'description: ' + upload_img_dict['description']
            ]
        )
    )
    )

    # Create image file IO
    image_fio = b64s_to_fio(upload_img_dict['data'])

    # Verify that the received data is actually an image
    if img_proc.is_image(image_fio) is False:
        return {
            'success':	False,
            'error_msg':
            'image_data cant be identified as an base64 formatted image file',
        }

    # Extract size and format from image data
    im_size = img_proc.get_image_size(image_fio)
    im_format = img_proc.get_image_format(image_fio)
    im_filename = name_from_path(upload_img_dict['filename'])

    # Store the new image in the database
    result = db.add_image(
        filename=im_filename,
        img_format=im_format,
        description=upload_img_dict['description'],
        size=im_size,
        timestamp=datetime.now(),
        data=upload_img_dict['data'],
        user_hash=upload_img_dict['user_hash'],
    )

    if result is False:
        return {
            'success': False,
            'error_msg': 'Error adding image to database',
        }

    # If everything went well
    return {
        'success':	True,
        'error_msg': '',
    }
Beispiel #14
0
def upload_multiple_images(upload_mult_img_dict: dict) -> dict:
    """ upload multiple images as a zip file

    this function receives a zip file in base64 string and
    extracts all the images from it and adds them to the
    database.

    :param upload_mult_img_dict: dictionary with all the info
    :type upload_mult_img_dict: dict
    :return: dictionary with success(bool), error_msg(str)
    :rtype: dict
    """

    # Verify input types
    t_ok, t_err = is_type_ok(
        upload_mult_img_dict,
        """
        dict{
            'filename': str,
            'user_hash': str,
            'data': str,
        }
        """
    )

    if t_ok is False:
        return {
            'success':	False,
            'error_msg': t_err,
        }

    # Log Action
    logging.info("{} - {} - CALLED: {} INPUT_ARGS: {}".format(
        upload_mult_img_dict['user_hash'],
        datetime.now(),
        'upload_multiple_images',
        ";".join(
            [
                'filename: ' + upload_mult_img_dict['filename']
            ]
        )
    )
    )

    # Extract user hash from input data
    user_hash = upload_mult_img_dict['user_hash']

    # Create zip file IO
    zip_fio = b64s_to_fio(upload_mult_img_dict['data'])

    # Verify that the received data is actually a zip file
    if is_zip(zip_fio) is False:
        return {
            'success':	False,
            'error_msg':
            'data cant be identified as a zip file in base64 string format',
        }

    # Process each file inside the zip
    results = []
    errs = []

    for name, image_fio in files_from_zip(zip_fio):

        # Verify that the current file is actually an image
        if img_proc.is_image(image_fio) is False:
            results.append(False)
            errs.append(
                name +
                'file can not be identified as an image. Ignored \n'
            )
            continue

        # Extract size and format from image data
        im_size = img_proc.get_image_size(image_fio)
        im_format = img_proc.get_image_format(image_fio)
        im_filename = name_from_path(name)

        # Store the new image in the database
        result = db.add_image(
            filename=im_filename,
            img_format=im_format,
            description="extracted from " + upload_mult_img_dict['filename'],
            size=im_size,
            timestamp=datetime.now(),
            data=fio_to_b64s(image_fio),
            user_hash=user_hash,
        )

        if result is False:
            results.append(False)
            errs.append(
                'Error adding image' +
                name +
                ' to database\n'
            )
            continue

    # return all the error messages
    return {
        'success':	all(results),
        'error_msg': '\n'.join(errs),
    }
def test_is_type_ok(str_type, var, expected):
    from core.verification import is_type_ok
    valid, errorstr = is_type_ok(var, str_type)
    assert valid == expected