Skip to content
__init__.py 71.4 KiB
Newer Older
    table = corr.get( new_field_name, False )

    if table != False:
        current_app.logger.info( "Add '{}' to the {} database".format( new_field, new_field_name ) )
        
        sql = utils.sql.sql_insert_generate( table, "name", "id" )
        current_app.logger.info( sql )
        field_id = config.db.query_fetchone( sql, ( new_field, ) )[ "id" ]
        config.db.commit()
        
        return jsonify( {
            "error": False,
            "id": field_id
        } )

    else:
        return jsonify( {
            "error": True
        } )
@submission_view.route( "/submission/<submission_id>/mark/<mark_id>/delete" )
@submission_has_access
def submission_mark_delete( submission_id, mark_id ):
    """
        Delete a mark from the database.
    """
    current_app.logger.info( "Delete mark '{}' from submission '{}'".format( mark_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"
        config.db.query( sql, ( session[ "user_id" ], mark_id, ) )
        config.db.commit()
        
        return jsonify( {
            "error": False
        } )
    
    else:
        return jsonify( {
            "error": True
        } )

################################################################################
#    Submission deletion

@submission_view.route( "/submission/<submission_id>/delete" )
@submission_has_access
def submission_delete( submission_id ):
    """
        Delete the empty submission. A submission can not be deleted after the upload
        of the consent form and the creation of the donor user.
    """
    current_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
        } )
    
    else:
        current_app.logger.error( "Can  not delete a submission with consent form" )
        return jsonify( {
            "error": True,
            "message": "Can not delete if a consent form is already uploaded"
        } )

@submission_view.route( "/submission/<submission_id>/tenprint/list" )
@submission_has_access
def submission_tenprint_list( submission_id ):
    """
        Serve the page with the list of tenprint images, splitted by front, back and NIST format.
    """
    current_app.logger.info( "Get the list of tenprint for the submission '{}'".format( submission_id ) )
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    submission_folder_id, nickname = config.db.query_fetchone( sql, ( submission_id, ) )
    nickname = do_decrypt_user_session( nickname )
    
    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
    """
    
    q = config.db.query_fetchall( sql, ( submission_folder_id, ) )
    
    tenprint_cards = {
        "1": [],
        "2": [],
        "5": []
    }
    nb = 0
    for tenprint in q:
        current_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 )
        } )
    
    current_app.logger.info( "{} tenprint(s) for the submission '{}'".format( nb, submission_id ) )
    
    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,
        nickname = nickname
    )

@submission_view.route( "/submission/<submission_id>/tenprint/<tenprint_id>" )
@submission_has_access
def submission_tenprint( submission_id, tenprint_id ):
    """
        Serve the page to see and edit a tenprint file.
    """
    current_app.logger.info( "Serve tenprint edit page for '{}', submission '{}'".format( tenprint_id, submission_id ) )
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    submission_folder_id, nickname = config.db.query_fetchone( sql, ( submission_id, ) )
    nickname = do_decrypt_user_session( nickname )
    
    sql = """
        SELECT
            files.uuid, files.filename, files.note,
            files.format, files.resolution, files.width, files.height, files.size,
            files.creation_time, files.type,
        FROM files
        WHERE
            folder = %s AND
            files.uuid = %s
    """
    
    tenprint_file = config.db.query_fetchone( sql, ( submission_folder_id, tenprint_id, ) )
    
    current_app.logger.debug( "tenprint type: {}".format( tenprint_file[ "type" ] ) )
    
    if tenprint_file[ "type" ] == 5:
        current_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 ) )
    
    else:
        tenprint_file[ "size" ] = round( 100 * float( tenprint_file[ "size" ] ) / ( 1024 * 1024 ) ) / 100
        tenprint_file[ "filename" ] = do_decrypt_user_session( tenprint_file[ "filename" ] )
        
        if tenprint_file[ "type" ] == 1:
            side = "front"
        elif tenprint_file[ "type" ] == 2:
            side = "back"
        
        ############################################################################
        
        sql = "SELECT id, name FROM quality_type"
        quality_type = config.db.query_fetchall( sql )
        
        ############################################################################
        
        sql = "SELECT width, height, resolution FROM files WHERE uuid = %s LIMIT 1"
        img_info = config.db.query_fetchone( sql, ( tenprint_id, ) )
        svg_hw_factor = float( img_info[ "width" ] ) / float( img_info[ "height" ] )
        
        ############################################################################
        
        sql = "SELECT * FROM segments_locations WHERE tenprint_id = %s ORDER BY fpc ASC"
        zones_raw = config.db.query_fetchall( sql, ( tenprint_id, ) )
        zones = []
        
        for z in zones_raw:
            tmp = {}
            for k in [ "fpc", "orientation" ]:
                tmp[ k ] = z[ k ]
            
            for k in [ "x", "width" ]:
                tmp[ k ] = z[ k ] / img_info[ "width" ]
            for k in [ "y", "height" ]:
                tmp[ k ] = z[ k ] / img_info[ "height" ]
            
            zones.append( tmp )
        
        ############################################################################
        
        if side == "front":
            to_annotate = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ]
        else:
            to_annotate = [ 25, 27, 22, 24 ]
        
        ############################################################################
        
            "shared/tenprint.html",
            segments_position_code = segments_position_code,
            to_annotate = to_annotate,
            submission_id = submission_id,
            file = tenprint_file,
            nickname = nickname,
            img_info = img_info,
            zones = zones,
            svg_hw_factor = svg_hw_factor,
            quality_type = quality_type
        )

@submission_view.route( "/submission/<submission_id>/tenprint/<tenprint_id>/delete" )
@submission_has_access
def submission_tenprint_delete( submission_id, tenprint_id ):
    """
        Endpoint to delete a tenprint image.
    """
    current_app.logger.info( "Delete tenprint '{}' from submission '{}'".format( tenprint_id, submission_id ) )
    
    try:
        sql = "DELETE FROM files WHERE uuid = %s"
        config.db.query( sql, ( tenprint_id, ) )
        
        sql = "DELETE FROM files_segments WHERE tenprint = %s"
        config.db.query( sql, ( tenprint_id, ) )
        
        config.db.commit()
        
        return jsonify( {
            "error": False
        } )
    
    except:
        return jsonify( {
            "error": True
        } )

@submission_view.route( "/submission/<submission_id>/tenprint/<tenprint_id>/set/template", methods = [ "POST" ] )
@submission_has_access
def submission_tenprint_set_template( submission_id, tenprint_id ):
    """
        Set the template id for a tenprint image.
    """
    try:
        template = request.form.get( "template" )
        current_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_fetchone( sql, ( tenprint_id, ) )
        
        if q == None:
            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, ) )
            config.db.commit()
        
        return jsonify( {
            "error": False
        } )
    
    except:
        return jsonify( {
            "error": True
        } )

@submission_view.route( "/submission/<submission_id>/file/<file_uuid>/set/note", methods = [ "POST" ] )
def submission_file_set_note( submission_id, file_uuid ):
    """
        Store the user encrypted notes for a tenprint image.
    """
    try:
        current_app.logger.info( "Add note for file '{}', submission id '{}'".format( file_uuid, submission_id ) )
        note = request.form.get( "note" )
        
        sql = "UPDATE files SET note = %s WHERE uuid = %s RETURNING id"
        config.db.query( sql, ( note, file_uuid, ) )
        config.db.commit()
        
        return jsonify( {
            "error": False
        } )
    
    except:
        return jsonify( {
            "error": True
        } )

@submission_view.route( "/submission/<submission_id>/tenprint/<tenprint_id>/set/quality", methods = [ "POST" ] )
@submission_has_access
def submission_tenprint_set_quality( submission_id, tenprint_id ):
    """
        Store the quality for a tenprint image.
    """
    try:
        quality = request.form.get( "quality" )
        current_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
        } )
    
    except:
        return jsonify( {
            "error": True
        } )

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

@submission_view.route( "/submission/<submission_id>/tenprint/<tenprint_id>/segment/list" )
@submission_has_access
def submission_tenprint_segments_list( submission_id, tenprint_id ):
    """
        Serve the page with the list of segments for a tenprint image.
    """
    current_app.logger.info( "Get the list of segments for tenprint '{}', submission id '{}'".format( tenprint_id, submission_id ) )
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    submission_folder_id, nickname = config.db.query_fetchone( sql, ( submission_id, ) )
    nickname = do_decrypt_user_session( nickname )
    
    sql = "SELECT uuid, filename FROM files WHERE folder = %s AND files.uuid = %s"
    
    tenprint_file = config.db.query_fetchone( sql, ( submission_folder_id, tenprint_id, ) )
    filename = do_decrypt_user_session( tenprint_file[ "filename" ] )
    tenprint_id = tenprint_file[ "uuid" ]
    
    ############################################################################
    
    sql = """
        SELECT files_segments.pc, files_segments.data, pc.name
        FROM files_segments
        LEFT JOIN pc ON pc.id = files_segments.pc
        WHERE tenprint = %s
    """
    segments = config.db.query_fetchall( sql, ( tenprint_id, ) )
    nb_segments = len( segments )
    
    current_app.logger.debug( "{} segments stored in database".format( nb_segments ) )
    
    ############################################################################
    
    return my_render_template( 
        "submission/segment_list.html",
        submission_id = submission_id,
        tenprint_id = tenprint_id,
        nickname = nickname,
        filename = filename,
        segments = segments,
        nb_segments = nb_segments
    )

@submission_view.route( "/submission/<submission_id>/tenprint/<tenprint_id>/segment/<pc>" )
@submission_has_access
def submission_segment( submission_id, tenprint_id, pc ):
    """
        Serve the page to edit the information relative to a segment image.
    """
    current_app.logger.info( "Serve the edit page for segment '{}'".format( pc ) )
    
    pc = int( pc )
    
    if not pc in config.all_fpc:
        current_app.logger.error( "'{}' not in the pc_list".format( pc ) )
        return redirect( url_for( "submission.tenprint_segments_list", submission_id = submission_id, tenprint_id = tenprint_id ) )
    
    else:
        current_app.logger.debug( "Retrieving data for submission '{}', pc '{}'".format( submission_id, pc ) )
        
        sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
        submission_folder_id, nickname = config.db.query_fetchone( sql, ( submission_id, ) )
        nickname = do_decrypt_user_session( nickname )
        
        sql = "SELECT uuid, filename, type FROM files WHERE folder = %s AND files.uuid = %s"
        tp_file = config.db.query_fetchone( sql, ( submission_folder_id, tenprint_id, ) )
        tp_filename = do_decrypt_user_session( tp_file[ "filename" ] )
        
        sql = "SELECT name FROM pc WHERE id = %s"
        pc_name = config.db.query_fetchone( sql, ( pc, ) )[ "name" ]
        
        sql = """
            SELECT gp.div_name
            FROM donor_fingers_gp
            LEFT JOIN submissions ON donor_fingers_gp.donor_id = submissions.donor_id
            LEFT JOIN gp ON donor_fingers_gp.gp = gp.id
            WHERE submissions.uuid = %s AND donor_fingers_gp.fpc = %s
        """
        try:
            current_gp = config.db.query_fetchone( sql, ( submission_id, pc, ) )[ "div_name" ]
        except:
            current_gp = None
        
        if pc in xrange( 1, 10 ):
            next_pc = pc + 1
            tp_type = "finger"
        elif pc == 10:
            next_pc = None
            tp_type = "finger"
        elif pc == 25:
            next_pc = 27
            tp_type = "palm"
        elif pc == 27:
            next_pc = None
            tp_type = "palm"
        else:
            return abort( 404 )
        
        current_app.logger.debug( "pc: {}".format( pc ) )
        current_app.logger.debug( "tp_type: {}".format( tp_type ) )
        current_app.logger.debug( "next pc: {}".format( next_pc ) )
        
        return my_render_template( 
            "submission/segment.html",
            submission_id = submission_id,
            nickname = nickname,
            pc_name = pc_name,
            tp_filename = tp_filename,
            tenprint_id = tenprint_id,
            pc = pc,
            next_pc = next_pc,
            current_gp = current_gp,
            tp_type = tp_type
        )

@submission_view.route( "/submission/<submission_id>/tenprint/segment/<pc>/set/gp", methods = [ "POST" ] )
@submission_has_access
def submission_segment_set_gp( submission_id, pc ):
    """
        Set the general pattern of a fingerprint segment image (FPC 1-10).
    """
    try:
        pc = int( pc )
        
        gp = request.form.get( "gp" )
        
        current_app.logger.info( "Set general pattern for '{}', pc '{}' to '{}'".format( submission_id, pc, gp ) )
        
        sql = "SELECT id FROM gp WHERE name = %s OR div_name = %s"
        r = config.db.query_fetchone( sql, ( gp, gp, ) )
        if r == None:
            current_app.logger.error( "General pattern not recognized" )
            return jsonify( {
                "error": True,
                "message": "General pattern not recognized"
            } )
        
        gp_id = r[ "id" ]
        
        sql = """
            SELECT count( * )
            FROM donor_fingers_gp
            LEFT JOIN submissions ON donor_fingers_gp.donor_id = submissions.donor_id
            WHERE submissions.uuid = %s AND donor_fingers_gp.fpc = %s
            GROUP BY donor_fingers_gp.id
        """
        nb = config.db.query_fetchone( sql, ( submission_id, pc, ) )
        
        sql = "SELECT donor_id FROM submissions WHERE uuid = %s"
        donor_id = config.db.query_fetchone( sql, ( submission_id, ) )[ "donor_id" ]
        
        if nb == 0 or nb == None:
            current_app.logger.debug( "Insert general pattern in database" )
            sql = utils.sql.sql_insert_generate( "donor_fingers_gp", [ "donor_id", "fpc", "gp" ] )
            config.db.query( sql, ( donor_id, pc, gp_id, ) )
        
        else:
            current_app.logger.debug( "Update general patern in database" )
            sql = "UPDATE donor_fingers_gp SET gp = %s WHERE donor_id = %s AND fpc = %s"
            config.db.query( sql, ( gp_id, donor_id, pc, ) )
        
        config.db.commit()
        
        return jsonify( {
            "error": False
        } )
    
    except:
        return jsonify( {
            "error": True
        } )

@submission_view.route( "/submission/<submission_id>/tenprint/<tenprint_id>/segment/set_coordinates", methods = [ "POST" ] )
@submission_has_access
def submission_segment_setcoordinates( submission_id, tenprint_id ):
    """
        Add the segment location data to the database.
    """
    try:
        fpc = request.form.get( "fpc" )
        x = float( request.form.get( "x" ) )
        y = float( request.form.get( "y" ) )
        w = float( request.form.get( "w" ) )
        h = float( request.form.get( "h" ) )
        img_width = float( request.form.get( "img_width" ) )
        img_height = float( request.form.get( "img_height" ) )
        orientation = int( request.form.get( "orientation" ) )
        
        img_data = do_img_info( tenprint_id )
        
        fpc = int( fpc )
        
        x_seg = int( x / img_width * img_data[ "width" ] )
        y_seg = int( y / img_height * img_data[ "height" ] )
        
        width_seg = int( w / img_width * img_data[ "width" ] )
        height_seg = int( h / img_height * img_data[ "height" ] )
        
        count = config.db.query_fetchone( "SELECT count( * ) FROM segments_locations WHERE tenprint_id = %s AND fpc = %s", ( tenprint_id, fpc, ) )[ "count" ]
        
        if count == 0:
            sql = utils.sql.sql_insert_generate( "segments_locations", [ "tenprint_id", "fpc", "x", "y", "width", "height", "orientation" ], "id" )
            seg_data_id = config.db.query_fetchone( sql, ( tenprint_id, fpc, x_seg, y_seg, width_seg, height_seg, orientation, ) )[ "id" ]
            sql = "UPDATE segments_locations SET x = %s, y = %s, width = %s, height = %s, orientation = %s WHERE tenprint_id = %s AND fpc = %s RETURNING id"
            data = ( x_seg, y_seg, width_seg, height_seg, orientation, tenprint_id, fpc, )
            seg_data_id = config.db.query_fetchone( sql, data )[ "id" ]
        
        config.db.commit()
        
        return jsonify( {
            "error": False,
            "id": seg_data_id,
        } )
    
Marco De Donno's avatar
Marco De Donno committed
    except:
@submission_view.route( "/submission/<submission_id>/tenprint/<tenprint_id>/segment/delete_coordinates" )
@submission_view.route( "/submission/<submission_id>/tenprint/<tenprint_id>/segment/delete_coordinates/<fpc>" )
def submission_segment_deletecoordinates( submission_id, tenprint_id, fpc = "all" ):
    try:
        if fpc == "all":
            sql = "DELETE FROM segments_locations WHERE tenprint_id = %s"
            data = ( tenprint_id, )
        
        else:
            fpc = int( fpc )
            if fpc in config.all_fpc:
                sql = sql = "DELETE FROM segments_locations WHERE tenprint_id = %s AND fpc = %s"
                data = ( tenprint_id, int( fpc ), )
            else:
            
        config.db.query( sql, data )
        config.db.commit()
        
        return jsonify( {
            "error": False
        } )
################################################################################
#    Admin review

@submission_view.route( "/admin/<submission_id>" )
@admin_required
def admin_submission_home( submission_id ):
    sql = """
        SELECT submissions.id, submissions.uuid, users.username
        FROM submissions
        LEFT JOIN users ON submissions.donor_id = users.id
        WHERE submissions.uuid = %s
    """
    donor = config.db.query_fetchone( sql, ( submission_id, ) )
    
    return my_render_template( 
        "admin/submission_home.html",
        donor = donor
    )
    
@submission_view.route( "/admin/submission/list" )
@admin_required
def admin_submission_list():
    """
        Get the list of all submissions folder.
    """
    current_app.logger.info( "Get all submissions" )
    
    sql = """
        SELECT submissions.id, submissions.uuid, users.username
        FROM submissions
        LEFT JOIN users ON submissions.donor_id = users.id
        ORDER BY created_time DESC
    """
    donors = config.db.query_fetchall( sql )
    
    current_app.logger.info( "{} submissions found".format( len( donors ) ) )
    
    return my_render_template( 
        "admin/submission_list.html",
@submission_view.route( "/admin/submission/table" )
@admin_required
def admin_submission_table():
    sql = """
        SELECT
            submissions.id,
            submissions.uuid,
            users.username
        FROM submissions
        LEFT JOIN users ON submissions.donor_id = users.id
        ORDER BY created_time DESC
    """
    donors = config.db.query_fetchall( sql )
    
    sql = """
        SELECT
            submissions.uuid,
            files_type.name,
            count( files.uuid ) AS nb
        FROM files
        INNER JOIN submissions ON files.folder = submissions.id
        INNER JOIN files_type ON files.type = files_type.id
        GROUP BY submissions.uuid, files_type.name
    """
    counts = config.db.query_fetchall( sql )
    
    sql = """
        SELECT
            submissions.uuid,
            count( * ) AS nb
        FROM files_segments
        INNER JOIN files ON files_segments.tenprint = files.uuid
        INNER JOIN submissions ON files.folder = submissions.id
        GROUP BY submissions.uuid
    """
    segments = config.db.query_fetchall( sql )

    current_app.logger.info( "{} submissions found".format( len( donors ) ) )
    
    return my_render_template(
        "admin/submission_table.html",
        donors = donors,
        counts = counts,
        segments = segments
    )
@submission_view.route( "/admin/<submission_id>/tenprint/list" )
@admin_required
def admin_tenprint_list( submission_id = "all" ):
    """
        Get the list of all tenprints.
    """
    current_app.logger.info( "Get all tenprints cards" )
    
    sql = """
        SELECT files.id, files.uuid, files.folder, users.username, submissions.uuid as submission_uuid
        FROM files
        LEFT JOIN submissions ON files.folder = submissions.id
        LEFT JOIN users ON submissions.email_hash = users.email
        WHERE ( files.type = 1 OR files.type = 2 OR files.type = 5 )
    """
    data = ()
    
    if submission_id != "all":
        sql += " AND submissions.uuid = %s"
        data = ( submission_id, )
    
    sql += """
        ORDER BY users.id ASC, files.type, files.id ASC
    """
    
    tenprint_cards = config.db.query_fetchall( sql, data )
    
    if submission_id != "all":
        sql = """
            SELECT users.username, submissions.uuid
            FROM submissions
            LEFT JOIN users ON submissions.donor_id = users.id
            WHERE submissions.uuid = %s
        """
        selector, submission_uuid = config.db.query_fetchone( sql, ( submission_id, ) )
        submission_uuid = None
    current_app.logger.info( "{} tenprints cards found".format( len( tenprint_cards ) ) )
    
    return my_render_template( 
        "admin/tenprint_list.html",
        tenprint_cards = tenprint_cards,
        selector = selector,
        submission_uuid = submission_uuid
    )

@submission_view.route( "/admin/<submission_id>/tenprint/<tenprint_id>" )
@admin_required
def admin_tenprint( submission_id, tenprint_id ):
    """
        Serve the page to see and edit a tenprint file.
    """
    current_app.logger.info( "Serve tenprint edit page for '{}', submission '{}'".format( tenprint_id, submission_id ) )
    sql = """
        SELECT
            files.uuid,
            files.format, files.resolution, files.width, files.height, files.size,
            files.creation_time, files.type,
            files.quality,
            users.username
        FROM files
        LEFT JOIN submissions ON files.folder = submissions.id
        LEFT JOIN users ON submissions.donor_id = users.id
        WHERE
            submissions.uuid = %s AND
            files.uuid = %s
    """
    tenprint_file = config.db.query_fetchone( sql, ( submission_id, tenprint_id, ) )
    
    current_app.logger.debug( "tenprint type: {}".format( tenprint_file[ "type" ] ) )
    
    if tenprint_file[ "type" ] == 5:
        current_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 ) )
    
    else:
        tenprint_file[ "size" ] = round( 100 * float( tenprint_file[ "size" ] ) / ( 1024 * 1024 ) ) / 100
        
        if tenprint_file[ "type" ] == 1:
            side = "front"
        elif tenprint_file[ "type" ] == 2:
            side = "back"
        
        ############################################################################
        
        sql = "SELECT id, name FROM quality_type"
        quality_type = config.db.query_fetchall( sql )
        
        ############################################################################
        
        sql = "SELECT width, height, resolution FROM files WHERE uuid = %s LIMIT 1"
        img_info = config.db.query_fetchone( sql, ( tenprint_id, ) )
        svg_hw_factor = float( img_info[ "width" ] ) / float( img_info[ "height" ] )
        
        ############################################################################
        
        sql = "SELECT * FROM segments_locations WHERE tenprint_id = %s ORDER BY fpc ASC"
        zones_raw = config.db.query_fetchall( sql, ( tenprint_id, ) )
        zones = []
        
        for z in zones_raw:
            tmp = {}
            for k in [ "fpc", "orientation" ]:
                tmp[ k ] = z[ k ]
            
            for k in [ "x", "width" ]:
                tmp[ k ] = z[ k ] / img_info[ "width" ]
            for k in [ "y", "height" ]:
                tmp[ k ] = z[ k ] / img_info[ "height" ]
            
            zones.append( tmp )
        
        ############################################################################
        
        sql = "SELECT width, height, resolution FROM files WHERE uuid = %s LIMIT 1"
        img_info = config.db.query_fetchone( sql, ( tenprint_id, ) )
        svg_hw_factor = float( img_info[ "width" ] ) / float( img_info[ "height" ] )
        
        ############################################################################
        
        if side == "front":
            to_annotate = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ]
        else:
            to_annotate = [ 25, 27, 22, 24 ]
        
        ############################################################################
            "shared/tenprint.html",
            segments_position_code = segments_position_code,
            to_annotate = to_annotate,
            submission_id = submission_id,
            file = tenprint_file,
            img_info = img_info,
            svg_hw_factor = svg_hw_factor,
            zones = zones,
            quality_type = quality_type
        )

@submission_view.route( "/admin/submission/<submission_id>/tenprint/<tenprint_id>/segment/list" )
@admin_required
def admin_submission_tenprint_segments_list( submission_id, tenprint_id ):
    """
        Serve the page with the list of segments for a tenprint image.
    """
    current_app.logger.info( "Get the list of segments for tenprint '{}', submission id '{}'".format( tenprint_id, submission_id ) )
    
    sql = """
        SELECT files_segments.pc, files_segments.data, pc.name
        FROM files_segments
        LEFT JOIN pc ON pc.id = files_segments.pc
        WHERE tenprint = %s
    """
    segments = config.db.query_fetchall( sql, ( tenprint_id, ) )
    nb_segments = len( segments )
    
    current_app.logger.debug( "{} segments stored in database".format( nb_segments ) )
    
    sql = "SELECT username FROM users LEFT JOIN submissions ON submissions.donor_id = users.id WHERE submissions.uuid = %s"
    donor_username = config.db.query_fetchone( sql, ( submission_id, ) )[ "username" ]
    
    ############################################################################
    
    return my_render_template( 
        "admin/segment_list.html",
        submission_id = submission_id,
        tenprint_id = tenprint_id,
        donor_username = donor_username,
        segments = segments,
        nb_segments = nb_segments
    )

@submission_view.route( "/admin/<submission_id>/gp" )
@submission_has_access
def admin_submission_gp( submission_id ):
    """
        Serve the page to upload the general pattern for a donor.
    """
    current_app.logger.info( "Serve the page to set the GP for {}".format( submission_id ) )
    
    finger_names = []
    for laterality in [ "Right", "Left" ]:
        for finger in [ "thumb", "index", "middel", "ring", "little" ]:
            finger_names.append( "{} {}".format( laterality, finger ) )
    
    gp_list = [
        {
            "div_name": "ll",
            "name": "left loop"
        },
        {
            "div_name": "rl",
            "name": "right loop"
        },
        {
            "div_name": "whorl",
            "name": "whorl"
        },
        {
            "div_name": "arch",
            "name": "arch"
        },
        {
            "div_name": "cpl",
            "name": "central pocket loop"
        },
        {
            "div_name": "dl",
            "name": "double loop"
        },
        {
            "div_name": "ma",
            "name": "missing/amputated"
        },
        {
            "div_name": "sm",
            "name": "scarred/mutilated"
        },
        {
            "div_name": "unknown",
            "name": "unknown"
        }
    ]
    
    try:
        sql = """
            SELECT donor_fingers_gp.fpc, gp.div_name, gp.name
            FROM donor_fingers_gp
            LEFT JOIN submissions ON donor_fingers_gp.donor_id = submissions.donor_id
            LEFT JOIN gp ON donor_fingers_gp.gp = gp.id
            WHERE submissions.uuid = %s AND donor_fingers_gp.fpc <= 10
            ORDER BY donor_fingers_gp.fpc ASC
        """
        current_gp = config.db.query_fetchall( sql, ( submission_id, ) )
        
        dek_check( submission_id )
        
        sql = """
            SELECT users.username
            FROM submissions
            LEFT JOIN users ON submissions.donor_id = users.id
            WHERE uuid = %s
        """
        donor = config.db.query_fetchone( sql, ( submission_id, ) )
        
        return my_render_template( 
            "admin/set_gp.html",
            submission_id = submission_id,
            finger_names = finger_names,
            gp_list = gp_list,
            current_gp = current_gp,
            donor = donor
        )
    
    except:
        return jsonify( {
            "error": True,
            "message": "Case not found"
        } )

@submission_view.route( "/admin/submission/<submission_id>/mark/list" )
@submission_view.route( "/admin/submission/<submission_id>/mark/list/<mark_type>" )
@submission_has_access
def admin_submission_mark_list( submission_id, mark_type = "all" ):
    current_app.logger.info( "Get the list of mark for the submission '{}'".format( submission_id ) )
    current_app.logger.debug( "mark_type: {}".format( mark_type ) )
    
    if mark_type in [ "target", "incidental", "all" ]:
        sql = "SELECT id FROM submissions WHERE uuid = %s"
        case_id, = config.db.query_fetchone( sql, ( submission_id, ) )
        
        sql = """
            SELECT files.id, 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 mark_type == "target":
            sql += " files_type.name = 'mark_target'"
        elif mark_type == "incidental":
            sql += " files_type.name = 'mark_incidental'"
        elif mark_type == "all":
            sql += " ( files_type.name = 'mark_target' OR files_type.name = 'mark_incidental' )"
        
        sql += " ORDER BY files.id DESC"
        files = config.db.query_fetchall( sql, ( case_id, ) )
        
        for _, v in enumerate( files ):
            v[ "filename" ] = do_decrypt_user_session( v[ "filename" ] )
            v[ "size" ] = round( ( float( v[ "size" ] ) / ( 1024 * 1024 ) ) * 100 ) / 100
        
        current_app.logger.debug( "{} marks for '{}'".format( len( files ), submission_id ) )
        
        return my_render_template( 
            "shared/mark_list.html",
            submission_id = submission_id,
            mark_type = mark_type,
            files = files,
        )
    
    else:
        return abort( 403 )