Skip to content
module.py 130 KiB
Newer Older
            app.logger.debug( "Donor uuid: {}".format( donor_uuid ) )
            email_hash = utils.hash.pbkdf2( email, iterations = config.EMAIL_NB_ITERATIONS ).hash()
            
            upload_nickname = request.form.get( "upload_nickname", None )
            upload_nickname = do_encrypt_user_session( upload_nickname )
            submitter_id = session[ "user_id" ]
            
            status = "pending"
            
Marco De Donno's avatar
Marco De Donno committed
            userid = config.db.query_fetchone( "SELECT nextval( 'username_donor_seq' ) as id" )[ "id" ]
            username = "donor_{}".format( userid )
            sql = utils.sql.sql_insert_generate( "users", [ "username", "email", "type" ], "id" )
            donor_user_id = config.db.query_fetchone( sql, data )[ "id" ]
            
            app.logger.debug( "Username: {}".format( username ) )
            
            dek_salt, dek, dek_check = dek_generate( email = email, username = username )
            app.logger.debug( "DEK salt: {}...".format( dek_salt[ 0:10 ] ) )
            app.logger.debug( "DEK:      {}...".format( dek[ 0:10 ] ) )
            
            sql = utils.sql.sql_insert_generate( "donor_dek", [ "donor_name", "salt", "dek", "dek_check", "iterations", "algo", "hash" ], "id" )
            data = ( username, dek_salt, dek, dek_check, config.DEK_NB_ITERATIONS, "pbkdf2", "sha512", )
            config.db.query_fetchone( sql, data )
            
            sql = utils.sql.sql_insert_generate( "submissions", [ "uuid", "email_aes", "email_hash", "nickname", "donor_id", "status", "submitter_id" ] )
            data = ( donor_uuid, email_aes, email_hash, upload_nickname, donor_user_id, status, submitter_id, )
            config.db.query( sql, data )
            config.db.commit()
            
            return jsonify( {
                "error": False,
        app.logger.error( "No email provided for the submission folder" )
        return jsonify( {
            "error": True,
            "msg": "Email not provided"
@app.route( baseurl + "/submission/<submission_id>/add_files" )
def submission_upload_tplp( submission_id ):
    """
        Serve the page to upload tenprint and latent images files.
        This page is not accessible if a consent form is not available in the
        database for this particular donor.
    """
    app.logger.info( "Upload a new file in the submission {}".format( submission_id ) )
        sql = """
            SELECT email_aes as email, nickname, created_time, consent_form
            FROM submissions
            WHERE submitter_id = %s AND uuid = %s
        """
        r = config.db.query( sql, ( session[ "user_id" ], submission_id ) )
        user = r.fetchone()
        
        if user[ "consent_form" ]:
            app.logger.debug( "The donor has a consent form" )
            app.logger.info( "Serving the add new file page" )
            
            for key in [ "email", "nickname" ]:
                user[ key ] = do_decrypt_user_session( user[ key ] )
Marco De Donno's avatar
Marco De Donno committed
            return my_render_template( 
                submission_id = submission_id,
            app.logger.debug( "The donor dont have a consent form in the database" )
            app.logger.info( "Serving the consent form upload page" )
            
            return redirect( url_for( "submission_consent_form", submission_id = submission_id ) )
        
    except:
        return jsonify( {
            "error": True,
            "msg": "Case not found"
@app.route( baseurl + "/submission/<submission_id>/consent_form" )
def submission_consent_form( submission_id ):
    """
        Serve the page to upload the consent form for the user.
    """
    app.logger.info( "Serve the consent form upload page" )
    
Marco De Donno's avatar
Marco De Donno committed
    sql = """
        SELECT email_aes as email, nickname, created_time
        FROM submissions
        WHERE submitter_id = %s AND uuid = %s
    """
    r = config.db.query( sql, ( session[ "user_id" ], submission_id ) )
        for key in [ "email", "nickname" ]:
            user[ key ] = do_decrypt_user_session( user[ key ] )
Marco De Donno's avatar
Marco De Donno committed
        return my_render_template( 
            "submission/consent_form.html",
            submission_id = submission_id,
        app.logger.error( "Submission not found" )
@app.route( baseurl + "/submission/<submission_id>/set/nickname", methods = [ "POST" ] )
def submission_update_nickname( submission_id ):
    """
        Change the nickname of the donor in the database.

        THIS INFORMATION SHALL BE ENCRYPTED ON THE CLIENT SIDE FIRST WITH A UNIQUE
        ENCRYPTION KEY NOT TRANSMETTED TO THE SERVER!
    """
    app.logger.info( "Save the donor nickname to the database" )
    
    nickname = request.form.get( "nickname", None )
    
    if nickname != None and len( nickname ) != 0:
        try:
            
            sql = "UPDATE submissions SET nickname = %s WHERE uuid = %s"
            config.db.query( sql, ( nickname, submission_id, ) )
                "error": False
            app.logger.error( "Database error" )
                "error": True,
                "message": "DB error"
        app.logger.error( "No nickname in the post request" )
            "error": True,
            "message": "No new nickname in the POST request"
@app.route( baseurl + "/submission/list" )
def submission_list():
    """
        Get the list of all submissions folder for the currently logged submitter.
    """
    app.logger.info( "Get all submissions for '{}'".format( session[ "username" ] ) )
    
    sql = "SELECT * FROM submissions WHERE submitter_id = %s ORDER BY created_time DESC"
    r = config.db.query( sql, ( session[ "user_id" ], ) )
Marco De Donno's avatar
Marco De Donno committed
    donors = []
    for donor in q:
        donors.append( {
            "id": donor.get( "id", None ),
            "email": do_decrypt_user_session( donor.get( "email_aes", None ) ),
            "nickname": do_decrypt_user_session( donor.get( "nickname", None ) ),
            "uuid": donor.get( "uuid", None )
        app.logger.debug( "uuid: {}".format( donor[ "uuid" ] ) )
    
    app.logger.info( "{} submissions found".format( len( donors ) ) )
Marco De Donno's avatar
Marco De Donno committed
    return my_render_template( 
        "submission/list.html",
@app.route( baseurl + "/submission/<submission_id>/latent/list" )
@app.route( baseurl + "/submission/<submission_id>/latent/list/<latent_type>" )
def submission_latent_list( submission_id, latent_type = "all" ):
    """
        Get the list of latent for a particular submission folder.
    """
    app.logger.info( "Get the list of latent for the submission '{}'".format( submission_id ) )
    app.logger.debug( "latent_type: {}".format( latent_type ) )
    
    if latent_type in [ "target", "incidental", "all" ]:
        sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
        r = config.db.query( sql, ( submission_id, ) )
        case_id, nickname = r.fetchone()
        
        sql = """
            SELECT files.uuid, files.filename, files.size, files.creation_time
            FROM files
            LEFT JOIN files_type ON files.type = files_type.id
            WHERE folder = %s AND
        """
        if latent_type == "target":
            sql += " files_type.name = 'latent_target'"
        elif latent_type == "incidental":
            sql += " files_type.name = 'latent_incidental'"
        elif latent_type == "all":
            sql += " ( files_type.name = 'latent_target' OR files_type.name = 'latent_incidental' )"
        
        sql += " ORDER BY files.id DESC"
        r = config.db.query( sql, ( case_id, ) )
        files = r.fetchall()
        
        for _, v in enumerate( files ):
            v[ "filename" ] = do_decrypt_user_session( v[ "filename" ] )
            v[ "size" ] = round( ( float( v[ "size" ] ) / ( 1024 * 1024 ) ) * 100 ) / 100
        app.logger.debug( "{} latents for '{}'".format( len( files ), submission_id ) )
        
Marco De Donno's avatar
Marco De Donno committed
        return my_render_template( 
            "submission/latent_list.html",
            submission_id = submission_id,
            latent_type = latent_type,
Marco De Donno's avatar
Marco De Donno committed
@app.route( baseurl + "/submission/<submission_id>/latent/<latent_id>" )
Marco De Donno's avatar
Marco De Donno committed
def submission_latent( submission_id, latent_id ):
    """
        Serve the page to edit a particular latent image.
    """
    app.logger.info( "Serve the latent page edit" )
    app.logger.debug( "submission {}".format( submission_id ) )
    app.logger.debug( "latent {}".format( latent_id ) )
    
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    r = config.db.query( sql, ( submission_id, ) )
    submission_folder_id, nickname = r.fetchone()
            files.uuid, files.filename, files.note,
            files.format, files.resolution, files.width, files.height, files.size,
            files.creation_time, files.type,
            files_type.name as file_type
        LEFT JOIN files_type ON files.type = files_type.id
Marco De Donno's avatar
Marco De Donno committed
    r = config.db.query( sql, ( submission_folder_id, latent_id, ) )
    latent = r.fetchone()
    latent[ "size" ] = round( 100 * float( latent[ "size" ] ) / ( 1024 * 1024 ) ) / 100
    latent[ "filename" ] = do_decrypt_user_session( latent[ "filename" ] )
    latent[ "note" ] = do_decrypt_user_session( latent[ "note" ] )
    latent[ "file_type" ] = latent[ "file_type" ].replace( "latent_", "" )
Marco De Donno's avatar
Marco De Donno committed
    return my_render_template( 
        submission_id = submission_id,
        nickname = nickname,
Marco De Donno's avatar
Marco De Donno committed
@app.route( baseurl + "/submission/<submission_id>/latent/<latent_id>/pfsp" )
Marco De Donno's avatar
Marco De Donno committed
def submission_latent_pfsp( submission_id, latent_id ):
    """
        Serve the page to set the PFSP information (location on the finger
        or the palm print) for the latent.
    """
    app.logger.info( "Serve the PFSP edit page" )
    app.logger.debug( "submission {}".format( submission_id ) )
    app.logger.debug( "latent {}".format( latent_id ) )
    
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    r = config.db.query( sql, ( submission_id, ) )
    submission_folder_id, nickname = r.fetchone()
    
    sql = """
        SELECT
            files.uuid, files.filename, files.note,
            files.format, files.resolution, files.width, files.height, files.size,
            files.creation_time, files.type,
            files_type.name as file_type
        
        FROM files
        LEFT JOIN files_type ON files.type = files_type.id
        WHERE
            folder = %s AND
            files.uuid = %s
    """
    
Marco De Donno's avatar
Marco De Donno committed
    r = config.db.query( sql, ( submission_folder_id, latent_id, ) )
    latent = r.fetchone()
    latent[ "size" ] = round( 100 * float( latent[ "size" ] ) / ( 1024 * 1024 ) ) / 100
    latent[ "filename" ] = do_decrypt_user_session( latent[ "filename" ] )
    latent[ "note" ] = do_decrypt_user_session( latent[ "note" ] )
    latent[ "file_type" ] = latent[ "file_type" ].replace( "latent_", "" )
    app.logger.debug( "file size: {}Mo".format( latent[ "size" ] ) )
    
    sql = "SELECT pfsp FROM latent_info WHERE uuid = %s"
    try:
Marco De Donno's avatar
Marco De Donno committed
        current_pfsp = config.db.query( sql, ( latent_id, ) ).fetchone()[ 0 ]
    app.logger.debug( "Current PFSP: {}".format( current_pfsp ) )
    
        if z[ "desc" ] == current_pfsp:
            current_pfsp = ",".join( z[ "sel" ] )
Marco De Donno's avatar
Marco De Donno committed
    return my_render_template( 
        "submission/latent_pfsp.html",
        submission_id = submission_id,
        nickname = nickname,
        pfsp_zones = pfsp.zones,
Marco De Donno's avatar
Marco De Donno committed
@app.route( baseurl + "/submission/<submission_id>/latent/<latent_id>/set/pfsp", methods = [ "POST" ] )
Marco De Donno's avatar
Marco De Donno committed
def submission_latent_pfsp_set( submission_id, latent_id ):
    """
        Save the PFSP information relative to a latent.
    """
    app.logger.info( "Save the PFSP for submission '{}' latent '{}'".format( submission_id, latent_id ) )
    
    pfsp = request.form.get( "pfsp" )
    
    sql = "SELECT id FROM latent_info WHERE uuid = %s"
Marco De Donno's avatar
Marco De Donno committed
    q = config.db.query( sql, ( latent_id, ) ).fetchone()
        sql = utils.sql.sql_insert_generate( "latent_info", [ "uuid", "pfsp" ] )
Marco De Donno's avatar
Marco De Donno committed
        config.db.query( sql, ( latent_id, pfsp, ) )
    
    else:
        sql = "UPDATE latent_info SET pfsp = %s WHERE uuid = %s"
Marco De Donno's avatar
Marco De Donno committed
        config.db.query( sql, ( pfsp, latent_id, ) )
        "error": False
Marco De Donno's avatar
Marco De Donno committed
@app.route( baseurl + "/submission/<submission_id>/latent/<latent_id>/delete" )
Marco De Donno's avatar
Marco De Donno committed
def submission_latent_delete( submission_id, latent_id ):
    """
        Delete a latent from the database.
    """
    app.logger.info( "Delete latent '{}' from submission '{}'".format( latent_id, submission_id ) )
    
    sql = "SELECT id FROM submissions WHERE submitter_id = %s AND uuid = %s"
    q = config.db.query( sql, ( session[ "user_id" ], submission_id, ) )
    
    if q != None:
        sql = "DELETE FROM files WHERE creator = %s AND uuid = %s"
Marco De Donno's avatar
Marco De Donno committed
        config.db.query( sql, ( session[ "user_id" ], latent_id, ) )
            "error": False
            "error": True
################################################################################
#    Submission deletion

@app.route( baseurl + "/submission/<submission_id>/delete" )
    app.logger.info( "Delete the submission '{}' for user '{}'".format( submission_id, session[ "username" ] ) )
    
    sql = "SELECT consent_form FROM submissions WHERE submitter_id = %s AND uuid = %s"
    cf = config.db.query_fetchone( sql, ( session[ "user_id" ], submission_id, ) )[ "consent_form" ]
    if not cf:
        sql = "DELETE FROM submissions WHERE submitter_id = %s AND uuid = %s"
        config.db.query( sql, ( session[ "user_id" ], submission_id, ) )
        config.db.commit()
        return jsonify( {
            "error": False
        } )
        app.logger.error( "Can  not delete a submission with consent form" )
            "error": True,
            "message": "Can not delete if a consent form is already uploaded"
################################################################################
#    Image processing

def get_submission_uuid_for_file( file_uuid ):
    sql = """
        SELECT submissions.uuid
        FROM submissions
        LEFT JOIN files ON submissions.id = files.folder
        WHERE files.uuid = %s
    """
    return config.db.query_fetchone( sql, ( file_uuid, ) )[ "uuid" ]

@app.route( baseurl + "/image/file/<file_id>/preview" )
def image_file_serve( file_id ):
    """
        Function to get an image from the database and return it as PNG preview image.
    """
    app.logger.info( "Serve a preview for the file '{}'".format( file_id ) )
    
        submission_id = get_submission_uuid_for_file( file_id )
        app.logger.debug( "submission id: '{}'".format( submission_id ) )
        
        img, _ = image_serve( "thumbnails", file_id, submission_id )
            app.logger.debug( "No image in the 'thumnnails' database. Recreating the thumbnail" )
            
            img, _ = image_serve( "files", file_id, submission_id )
            app.logger.debug( "Image from the 'files' table: {}".format( img ) )
            img = create_thumbnail( file_id, img, submission_id )
            app.logger.debug( "Thumbnail image: {}".format( img ) )
        buff = utils.images.pil2buffer( img, "PNG" )
        return send_file( buff, mimetype = "image/png" )
        app.logger.error( "Error while creating the thumbnail. Serving a 'no preview' image" )
        
        img = Image.new( "L", ( 210, 297 ), 255 )
        draw = ImageDraw.Draw( img )
        font = ImageFont.truetype( "arial.ttf", 18 )
        draw.text( ( 0, 0 ), "No preview", 0, font = font )
Marco De Donno's avatar
Marco De Donno committed
         
        buff = utils.images.pil2buffer( img, "PNG" )
        return send_file( buff, mimetype = "image/png" )
@app.route( baseurl + "/image/segment/<tenprint_id>/<pc>" )
def image_segment_serve( tenprint_id, pc ):
    """
        Serve a preview for a segment image.
    """
    app.logger.info( "Serving a segment image for the tenprint '{}', pc '{}'".format( tenprint_id, pc ) )
    
    try:
        submission_id = get_submission_uuid_for_file( tenprint_id )
        
        app.logger.debug( "submission id: {}".format( submission_id ) )
        
        img, file_segment_id = image_serve( "files_segments", ( tenprint_id, pc ), submission_id )
        img = create_thumbnail( file_segment_id, img, submission_id )
        
        app.logger.debug( "image: {}".format( img ) )
        
        buff = utils.images.pil2buffer( img, "PNG" )
        return send_file( buff, mimetype = "image/png" )
        app.logger.error( "Error while creating the thumbnail. Serving a 'no preview' image" )
        
        img = Image.new( "L", ( 210, 297 ), 255 )
        draw = ImageDraw.Draw( img )
        font = ImageFont.truetype( "arial.ttf", 18 )
        draw.text( ( 0, 0 ), "No preview", 0, font = font )
         
        buff = utils.images.pil2buffer( img, "PNG" )
        return send_file( buff, mimetype = "image/png" )
@app.route( baseurl + "/image/template/<tenprint_id>/<side>" )
@app.route( baseurl + "/image/template/<tenprint_id>/<side>/<action>" )
@login_required
def image_tp_template( tenprint_id, side, action = "full" ):
    """
        Serve a template image, full-resolution or preview.
    """
    app.logger.info( "Serve the tenprint template image for {}, {}".format( tenprint_id, side ) )
    
    if side in [ "front", "back" ]:
        img, _ = image_serve( "tenprint_cards", ( tenprint_id, side ), None )
        if action == "preview":
            img.thumbnail( ( 500, 500 ) )
        
        app.logger.debug( "image: {}".format( img ) )
        
        buff = utils.images.pil2buffer( img, "PNG" )
        return send_file( buff, mimetype = "image/png" )
    
    else:
        return abort( 403 )

def image_serve( db, image_id, submission_id ):
    """
        Backend function to get the image from the database.
    """
    app.logger.info( "Serve the image '{}' for submission '{}' from table '{}'".format( image_id, submission_id, db ) )
    
    if db == "files_segments":
        if isinstance( image_id, tuple ):
            tp, pc = image_id
Marco De Donno's avatar
Marco De Donno committed
            sql = "SELECT data, uuid FROM {} WHERE tenprint = %s AND pc = %s".format( db )
Marco De Donno's avatar
Marco De Donno committed
            sql = "SELECT data, uuid FROM {} WHERE uuid = %s".format( db )
    
    elif db in [ "files", "thumbnails" ]:
Marco De Donno's avatar
Marco De Donno committed
        sql = "SELECT data, uuid FROM {} WHERE uuid = %s".format( db )
    
    elif db == "tenprint_cards":
Marco De Donno's avatar
Marco De Donno committed
        sql = "SELECT image_{}, id FROM {} WHERE id = %s".format( t, db )
        app.logger.error( "table '{}' not authorized".format( db ) )
        raise Exception( "table not authorized" )
    
    app.logger.debug( "sql:    {}".format( sql ) )
    app.logger.debug( "params: {}".format( p ) )
    
    data = config.db.query( sql, p ).fetchone()
    if data == None:
        return None, None
    
        img, rid = data
        
        app.logger.debug( "image: {}...".format( img[ 0:20 ] ) )
        app.logger.debug( "need_to_debug: {}".format( need_to_decrypt ) )
        
        if need_to_decrypt:
            img = do_decrypt_dek( img, submission_id )
        
        img = str2img( img )
        app.logger.debug( "image: {}".format( img ) )
        
        return img, rid
    """
        Convert a base64 string image to a PIL image.
    """
    app.logger.info( "Convert string image to PIL format" )
    
    if data == None:
        return None
    
    else:
        img = base64.b64decode( data )
        buff = StringIO()
        buff.write( img )
        buff.seek( 0 )
        img = Image.open( buff )
        
        app.logger.debug( "string: {}".format( data[ 0:20 ] ) )
        app.logger.debug( "image: {}".format( img ) )
        
@app.route( baseurl + "/image/file/<image_id>/info" )
    """
        Get and return the metadata for a particular image.
        See do_img_info() for more informations.
    """
    app.logger.info( "Serve image informations for image '{}'".format( image_id ) )
    
    
    if d != None:
        return jsonify( d )
    else:
        return abort( 404 )

    """
        Retrieve the metadata for a particular image from the database.
    """
    app.logger.debug( "Get image information from database for '{}'".format( image_id ) )
    
    sql = "SELECT size, width, height, resolution, format FROM files WHERE uuid = %s"
    r = config.db.query( sql, ( image_id, ) )
    for key, value in d.iteritems():
        app.logger.debug( "{}: {}".format( key, value ) )
    
    if d != None:
        return dict( d )
    else:
        return None

def create_thumbnail( file_uuid, img, submission_id ):
    """
        Generate a thumbnail image for a PIL image passed in argument.
    """
    app.logger.info( "Creating a thumbnail for the file '{}', submission '{}'".format( file_uuid, submission_id ) )
    app.logger.debug( "Input image: {}".format( img ) )
    
    img.thumbnail( ( 1000, 1000 ) )
    width, height = img.size
    
    app.logger.debug( "Thumbnail: {}".format( img ) )
    
    buff = StringIO()
    img.save( buff, format = img.format )
    img_size = buff.tell()
    buff.seek( 0 )
    
    app.logger.debug( "Encrypt the thumnbnail with DEK" )
    img_data = buff.getvalue()
    img_data = base64.b64encode( img_data )
    img_data = do_encrypt_dek( img_data, submission_id )
    app.logger.debug( "Saving thumnbail to database" )
    sql = utils.sql.sql_insert_generate( "thumbnails", [ "uuid", "width", "height", "size", "format", "data" ] )
    data = ( file_uuid, width, height, img_size, img.format, img_data, )
    config.db.query( sql, data )
    config.db.commit()
    
@app.route( baseurl + "/image/segment/<tenprint_id>/start" )
def image_tenprint_segmentation( tenprint_id ):
    """
        Route to start the segmentation of a tenprint image into segments (fingers or palm images).
    """
    app.logger.info( "Start segmentations for '{}'".format( tenprint_id ) )
    
    ret = do_image_tenprint_segmentation( tenprint_id )
        "error": False,
        "data": ret
def do_image_tenprint_segmentation( tenprint_id ):
    """
        Backend function to create all the segments images for a tenprint souce image.
    """
    sql = "SELECT size, resolution, type, format, data FROM files WHERE uuid = %s"
    r = config.db.query( sql, ( tenprint_id, ) )
    for key, value in img.iteritems():
        if isinstance( value, str ) and len( value ) > 20:
            value = "{}...".format( value[ 0:20 ] )
        app.logger.debug( "{}: {}".format( key, value ) )
    
    res = img[ "resolution" ]
    img_format = img[ "format" ]
        1: "front",
        2: "back"
    }[ img[ "type" ] ]
    app.logger.debug( "side: {}".format( t ) )
    
    submission_id = get_submission_uuid_for_file( tenprint_id )
    
    app.logger.debug( "Decrypt data with DEK" )
    img = do_decrypt_dek( img[ "data" ], submission_id )
    img = base64.b64decode( img )
    
    buff = StringIO()
    buff.write( img )
    buff.seek( 0 )
    img = Image.open( buff )
    
    app.logger.debug( "image: {}".format( img ) )
    
    sql = "SELECT template FROM file_template WHERE file = %s"
    r = config.db.query( sql, ( tenprint_id, ) )
    template_id = r.fetchone()[ "template" ]
    
    zones = get_tenprint_template_zones( template_id, t )
    
    app.logger.debug( "Use '{}' as tenprint template".format( template_id ) )
    
        app.logger.debug( "Segmenting fpc '{}' ({})".format( z[ "pc" ], z[ "pc_name" ] ) )
        
        tl_x, tl_y, br_x, br_y = map( lambda v: v * res / 2.54 , [ z[ "tl_x" ], z[ "tl_y" ], z[ "br_x" ], z[ "br_y" ] ] )
        tmp = img.crop( ( tl_x, tl_y, br_x, br_y ) )
        buff = StringIO()
        tmp.save( buff, format = img_format )
        buff.seek( 0 )
        
        app.logger.debug( "Encrypting segment image with DEK" )
        file_data = buff.getvalue()
        file_data = base64.b64encode( file_data )
        file_data = do_encrypt_dek( file_data, submission_id )
        sql = "SELECT id FROM files_segments WHERE tenprint = %s AND pc = %s"
        q = config.db.query( sql, ( tenprint_id, z[ "pc" ], ) ).fetchone()
            app.logger.debug( "Inserting to the database" )
            sql = utils.sql.sql_insert_generate( "files_segments", [ "tenprint", "uuid", "pc", "data" ] )
            data = ( tenprint_id, str( uuid4() ), z[ "pc" ], file_data )
            app.logger.debug( "Updating the database" )
            sql = "UPDATE files_segments SET data = %s WHERE tenprint = %s AND pc = %s"
            data = ( file_data, tenprint_id, z[ "pc" ] )
################################################################################
Marco De Donno's avatar
Marco De Donno committed
#    Donor tenprints
@app.route( baseurl + "/submission/<submission_id>/tenprint/list" )
def submission_tenprint_list( submission_id ):
    """
        Serve the page with the list of tenprint images, splitted by front, back and NIST format.
    """
    app.logger.info( "Get the list of tenprint for the submission '{}'".format( submission_id ) )
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    r = config.db.query( sql, ( submission_id, ) )
    submission_folder_id, nickname = r.fetchone()
    sql = """
        SELECT
            id, filename, uuid, type, creation_time
        FROM files
        WHERE folder = %s AND ( type = 1 OR type = 2 OR type = 5 )
        ORDER BY creation_time DESC
    """
    
    r = config.db.query( sql, ( submission_folder_id, ) )
        "1": [],
        "2": [],
        "5": []
        app.logger.debug( "tenprint: '{}'".format( tenprint[ "id" ] ) )
        nb += 1
        tenprint_cards[ str( tenprint[ "type" ] ) ].append( {
            "id": tenprint.get( "id", None ),
            "filename": do_decrypt_user_session( tenprint.get( "filename", None ) ),
            "uuid": tenprint.get( "uuid", None ),
            "type": tenprint.get( "type", None )
    app.logger.info( "{} tenprint(s) for the submission '{}'".format( nb, submission_id ) )
    
Marco De Donno's avatar
Marco De Donno committed
    return my_render_template( 
        "submission/tenprint_list.html",
        tenprint_cards_front = tenprint_cards[ "1" ],
        tenprint_cards_back = tenprint_cards[ "2" ],
        tenprint_cards_nist = tenprint_cards[ "5" ],
        submission_id = submission_id,
@app.route( baseurl + "/submission/<submission_id>/tenprint/<tenprint_id>" )
def submission_tenprint( submission_id, tenprint_id ):
    """
        Serve the page to see and edit a tenprint file.
    """
    app.logger.info( "Serve tenprint edit page for '{}', submission '{}'".format( tenprint_id, submission_id ) )
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    r = config.db.query( sql, ( submission_id, ) )
    submission_folder_id, nickname = r.fetchone()
            files.uuid, files.filename, files.note,
            files.format, files.resolution, files.width, files.height, files.size,
            files.creation_time, files.type,
            file_template.template, files.quality
        LEFT JOIN file_template ON files.uuid = file_template.file
    r = config.db.query( sql, ( submission_folder_id, tenprint_id, ) )
    app.logger.debug( "tenprint type: {}".format( tenprint_file[ "type" ] ) )
    
    if tenprint_file[ "type" ] == 5:
        app.logger.debug( "Redirect to the segments list page" )
        return redirect( url_for( "submission_tenprint_segments_list", submission_id = submission_id, tenprint_id = tenprint_id ) )
        tenprint_file[ "size" ] = round( 100 * float( tenprint_file[ "size" ] ) / ( 1024 * 1024 ) ) / 100
        tenprint_file[ "filename" ] = do_decrypt_user_session( tenprint_file[ "filename" ] )
        tenprint_file[ "note" ] = do_decrypt_user_session( tenprint_file[ "note" ] )
        if tenprint_file[ "type" ] == 1:
            t = "front"
        elif tenprint_file[ "type" ] == 2:
            t = "back"
        
        ############################################################################
        
        try:
            sql = "SELECT width, height, image_resolution FROM tenprint_cards WHERE id = %s LIMIT 1"
            r = config.db.query( sql, ( tenprint_file[ "template" ], ) )
                "width": int( round( float( tmp[ "width" ] ) / 2.54 * tmp[ "image_resolution" ] ) ),
                "height": int( round( float( tmp[ "height" ] ) / 2.54 * tmp[ "image_resolution" ] ) ),
                "width_cm": tmp[ "width" ],
                "height_cm": tmp[ "height" ]
                "width": 0,
                "height": 0,
                "width_cm": 0,
                "height_cm": 0
            }
        
        ############################################################################
        
        sql = "SELECT id, country_code, name, width, height, size_display FROM tenprint_cards ORDER BY name"
        tenprint_templates = config.db.query( sql ).fetchall()
        
        ############################################################################
        
        sql = "SELECT id, name FROM quality_type"
        quality_type = config.db.query_fetchall( sql )
        
        ############################################################################
        
        zones = get_tenprint_template_zones( tenprint_file[ "template" ], t )
        datacolumns = [ "tl_x", "tl_y", "br_x", "br_y", "angle" ]
        
        ############################################################################
        
        sql = "SELECT width, height, resolution FROM files WHERE uuid = %s LIMIT 1"
        r = config.db.query( sql, ( tenprint_id, ) )
        img_info = r.fetchone()
        svg_hw_factor = float( img_info[ "width" ] ) / float( img_info[ "height" ] )
Marco De Donno's avatar
Marco De Donno committed
        return my_render_template( 
            "submission/tenprint.html",
            submission_id = submission_id,
            tenprint_id = tenprint_id,
            card_id = tenprint_file[ "uuid" ],
            card_info = card_info,
            img_info = img_info,
            svg_hw_factor = svg_hw_factor,
            zones = zones,
            datacolumns = datacolumns,
            tenprint_templates = tenprint_templates,
            quality_type = quality_type
@app.route( baseurl + "/submission/<submission_id>/tenprint/<tenprint_id>/delete" )
def submission_tenprint_delete( submission_id, tenprint_id ):
    """
        Endpoint to delete a tenprint image.
    """
    app.logger.info( "Delete tenprint '{}' from submission '{}'".format( tenprint_id, submission_id ) )
    
    sql = "DELETE FROM files WHERE creator = %s AND uuid = %s"
    config.db.query( sql, ( session[ "user_id" ], tenprint_id, ) )
    sql = "DELETE FROM files_segments WHERE tenprint = %s"
    config.db.query( sql, ( tenprint_id, ) )
    config.db.commit()
    
    return jsonify( {
        "error": False
    } )
@app.route( baseurl + "/submission/<submission_id>/tenprint/<tenprint_id>/set/template", methods = [ "POST" ] )
def submission_tenprint_set_template( submission_id, tenprint_id ):
    """
        Set the template id for a tenprint image.
    """
    template = request.form.get( "template" )
    app.logger.info( "Set tenprint template id to '{}' for '{}', submission id '{}'".format( template, tenprint_id, submission_id ) )
    
    sql = "SELECT id FROM file_template WHERE file = %s"
    q = config.db.query( sql, ( tenprint_id, ) ).fetchone()
        sql = utils.sql.sql_insert_generate( "file_template", [ "file", "template" ] )
        config.db.query( sql, ( tenprint_id, template, ) )
        config.db.commit()
    
    else:
        sql = "UPDATE file_template SET template = %s WHERE file = %s"
        config.db.query( sql, ( template, tenprint_id, ) )
        "error": False
@app.route( baseurl + "/submission/<submission_id>/<file_type>/<tenprint_id>/set/note", methods = [ "POST" ] )
def submission_file_set_note( submission_id, file_type, tenprint_id ):
    """
        Store the user encrypted notes for a tenprint image.
    """
    app.logger.info( "Add note for tenprint '{}', '{}', submission id '{}'".format( tenprint_id, file_type, submission_id ) )
    note = request.form.get( "note" )
    
    sql = "UPDATE files SET note = %s WHERE uuid = %s RETURNING id"
    config.db.query( sql, ( note, tenprint_id, ) )
    config.db.commit()
    
    return jsonify( {
        "error": False
@app.route( baseurl + "/submission/<submission_id>/tenprint/<tenprint_id>/set/quality", methods = [ "POST" ] )
def submission_tenprint_set_quality( submission_id, tenprint_id ):
    """
        Store the quality for a tenprint image.
    """
    quality = request.form.get( "quality" )
    app.logger.info( "Set the quality to '{}' for tenprint '{}', submission id '{}'".format( quality, tenprint_id, submission_id ) )
    
    sql = "UPDATE files SET quality = %s WHERE uuid = %s RETURNING id"
    config.db.query( sql, ( quality, tenprint_id, ) )
    config.db.commit()
    
    return jsonify( {
        "error": False
    } )

################################################################################
#    Tenprint segments

@app.route( baseurl + "/submission/<submission_id>/tenprint/<tenprint_id>/segment/list" )