Skip to content
Snippets Groups Projects
flask_backend.py 17.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • from flask import Flask, request, abort, jsonify, make_response
    
    from flask_cors import CORS
    
    from database_api import CrisisEventsDatabase
    
    #from database_implementation import sqlite_api
    
    from runtime_import import runtime_import
    
    from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity,create_refresh_token
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    import os 
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    import zipfile
    import glob
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    #summarizers
    import summarizer_implementations.t5 as t5
    
    import summarizer_implementations.nltk_summarizer as nltk
    
    import summarizer_implementations.bert as bert
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    app = Flask(__name__)
    
    app.config['JWT_SECRET_KEY'] = 'PI'
    jwt = JWTManager(app)
    
    #pip install flask-cors
    
    database:CrisisEventsDatabase = None
    
    #this function is terrible, oh well!
    def database_debug_view():
        db_html = ""
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        user_db_html = ""
    
        for collection in database.get_sample_of_collections():
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
            db_html += f"<br/><code>{collection}</code>"
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
        for collection in database.get_sample_of_users():
            user_db_html += f"<br/><code>{collection}</code>"
    
    
        return f"""
        <html>
        <head></head>
        <body>
            <p>This service uses {database.get_info()} as its database</p>
            <p>Warning: if there are any '<'  or '>' or '/' or '\\' in the database: this will break! </p>
    
            <code>CollectionID, UserID, CollectionData, CollectionSummary, CollectionName</code>
    
            {db_html}
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
            <br/><br/><br/>
            <code>UserID, UserName, Hash</code>
            {user_db_html}
    
        </body>
        </html>
        """
    
    @app.route('/login', methods = ['POST'])
    def login():
         
        data = request.json  # Retrieve JSON data from the request
        print(f'The login data: {data}')
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        if "authenticate" not in data:
            abort(400)
    
        data = data["authenticate"]
    
        if 'username' not in data or 'password' not in data:
            abort(400)
    
        username = data['username']
        password = data ['password']
    
        user_hash = hashlib.md5(password.encode()).digest().hex()
    
        user_data = database.get_user_by_username(username)
    
        if user_data is None:
            #abort(401)  # Unauthorized if user does not exist
            print(f'Username or password is incorrect: {data}')
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
            return {"status":"User does not exist"}, 401
    
            
        stored_hash = user_data[2]
    
        if user_hash != stored_hash:
            print(f'Password is incorrect: {data}')
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
            return {"status":"Incorrect Password"}, 401
    
      
        access_token = create_access_token(username)
        refresh_token = create_refresh_token(username)
        print(f'Login Successful!\n')
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        return jsonify({"status":"success", "access_token": access_token, "refresh_token": refresh_token}), 200  # Return a response to indicate success
    
    
    @app.route('/refresh', methods = ['POST'])
    @jwt_required(refresh = True)
    def refresh():
        current_user = get_jwt_identity()
        new_access_token = create_access_token(identity = current_user)
        return make_response(jsonify({"access_token": new_access_token}), 200)
    
    
    @app.route('/database_service', methods=['POST','GET'])
    def database_service():
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        """
        POST Commands:
            create_collection
                - creates a collection under the logged in user
    
            get_collections
                - gets the title and id of every collection under the logged user
        """
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        if request.method == 'POST':
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
            # print("request body: ",request.json)
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
            result = ''
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
                command = request.json["command"]
                if command == "create_collection":
    
                    database.create_collection(0,request.json["data"]["collection_name"])
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
                elif command == "get_collection":
                    result = str(database.get_collection(0,0))
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
                elif command == "get_collections":
                    result = str(database.get_collection(0,0))
    
                else:
                    print("Invalid command")
                    abort(400)
            except KeyError:
                print("Got poorly formatted request")
                abort(400)
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
            return result, 200
    
        elif request.method == 'GET':
            return database_debug_view(), 200
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        else:
            abort(400)
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    @app.route('/api/v1/get_collections', methods=['GET'])
    def get_collections():
        "http://127.0.0.1:5000//api/v1/get_collections?user=0"
        user_id = request.args.get("user")
    
        if not user_id:
            abort(400)
    
        collections = database.get_collections(user_id)
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        # print(collections)
        return {
            "status":"success",
            "collections": collections
        }, 200
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
    @app.route('/api/v1/get_collection', methods=['GET'])
    def get_collection():
        "http://127.0.0.1:5000//api/v1/get_collection?collection=0"
        collection_id = request.args.get("collection")
    
        if not collection_id:
            abort(400)
    
        collection = database.get_collection(collection_id)
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        # print("get_collection:",collection)
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
        if collection:
            return {"status":"success","collection":collection}, 200
        else:
            return {"status":"failure"}, 200
        
    @app.route('/api/v1/create_collection', methods=['POST'])
    def v1_create_collection():
    
        data = request.json
    
        if "collection_info" not in data:
            abort(400)
    
        collection_info = data["collection_info"]
    
        if "collection_name" not in collection_info:
            abort(400)
    
        id = database.create_collection(0,collection_info["collection_name"])
    
        return {
            "status":"success",
            "collection_id":id
            }, 200
    
    
    @app.route('/api/v1/update_collection_glob', methods=['POST'])
    def v1_update_collection_glob():
    
        data = request.json
    
        if "collection_info" not in data:
            abort(400)
    
        collection_info = data["collection_info"]
    
        if "collection_id" not in collection_info:
            print("Missing ID")
            abort(400)
        
        if "glob" not in collection_info:
            print("Missing Glob")
            abort(400)
    
        database.update_collection_glob(collection_info["collection_id"],collection_info["glob"])
        return {
            "status":"success",
            }, 200
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    @app.route('/api/v1/summarize/t5', methods=['POST'])
    def v1_summarize_t5():
        data = request.json
    
        if "collection_info" not in data:
            abort(400)
    
        collection_info = data["collection_info"]
    
        if "collection_id" not in collection_info:
            print("Missing ID")
            abort(400)
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        # collection = database.get_collection(collection_info["collection_id"])
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        files = database.get_raw_text_files(collection_info["collection_id"])
        
        glob = ""
        for file_data in files:
            with open(file_data["path"], "r") as f:
                glob += f.read()
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        # summary = t5.summarize(collection["collection_data"]["glob"])
        summary = t5.summarize(glob)
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        
        if summary:
            database.update_collection_summary(collection_info["collection_id"],summary)
    
            return {
                "status":"success",
                }, 200
        else:
            return {
                "status":"failure",
                }, 500
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        
    
    Tarek Shah's avatar
    Tarek Shah committed
    @app.route('/api/v1/summarize/nltk', methods=['POST'])
    def v1_summarize_nltk():
        data = request.json
    
        if "collection_info" not in data:
            abort(400)
    
        collection_info = data["collection_info"]
    
        if "collection_id" not in collection_info:
            print("Missing ID")
            abort(400)
    
        # collection = database.get_collection(collection_info["collection_id"])
    
        files = database.get_raw_text_files(collection_info["collection_id"])
        
        glob = ""
        for file_data in files:
            with open(file_data["path"], "r") as f:
                glob += f.read()
    
        # summary = t5.summarize(collection["collection_data"]["glob"])
        summary = nltk.summarize(glob)
        
        if summary:
            database.update_collection_summary(collection_info["collection_id"],summary)
    
            return {
                "status":"success",
                }, 200
        else:
            return {
                "status":"failure",
                }, 500
        
    @app.route('/api/v1/summarize/bert', methods=['POST'])
    def v1_summarize_bert():
        data = request.json
    
        if "collection_info" not in data:
            abort(400)
    
        collection_info = data["collection_info"]
    
        if "collection_id" not in collection_info:
            print("Missing ID")
            abort(400)
    
        # collection = database.get_collection(collection_info["collection_id"])
    
        files = database.get_raw_text_files(collection_info["collection_id"])
        
        glob = ""
        for file_data in files:
            with open(file_data["path"], "r") as f:
                glob += f.read()
    
        # summary = t5.summarize(collection["collection_data"]["glob"])
    
        summary = bert.summarize(glob)
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        if summary:
            database.update_collection_summary(collection_info["collection_id"],summary)
    
            return {
                "status":"success",
                }, 200
        else:
            return {
                "status":"failure",
                }, 500
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        
    
    @app.route('/api/v1/upload_raw_text', methods=['POST'])
    def v1_upload_raw_text():
        "http://127.0.0.1:5000//api/v1/upload_raw_text?collection=0"
        collection_id = request.args.get("collection")
    
        if not collection_id:
            abort(400)
    
        # collection = database.get_collection(collection_id)
    
        os.makedirs(f"./backend/storage/{collection_id}",exist_ok=True)
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        for zip_file in request.files.keys():
            path = f"./backend/storage/{collection_id}/{zip_file}"
            request.files[zip_file].save(path)
    
            with zipfile.ZipFile(path, 'r') as zip_ref:
                zip_ref.extractall(f"./backend/storage/{collection_id}")
    
            glob_path = r'./backend/storage/' + collection_id + r'/*.txt'
    
            for file_path in glob.glob(glob_path):
                database.create_raw_text_file(collection_id, file_path)
            
    
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
        # for file_name in request.files.keys():
        #     collection["collection_data"]["raw_text"].append(file_name)
    
        # database.set_collection(collection)
        # print("get_collection:",collection)
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        return {"status":"success"}, 200
      
    @app.route('/api/v1/get_items', methods=['GET'])
    def v1_get_items():
        "http://127.0.0.1:5000//api/v1/get_items?collection=0&type=raw"
        collection_id = request.args.get("collection")
        file_type = request.args.get("type")
    
        if not collection_id:
            abort(400)
    
        if not file_type:
            abort(400)
    
    
        files = database.get_raw_text_files(collection_id)
        print(files)
    
    
    
        return {"status":"success","files":files}, 200
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    @app.route('/testing', methods=['POST','GET'])
    def testing():
        if request.method == 'POST':
            return ["Success Post request"], 200
    
        elif request.method == 'GET':
            print("get request: ",request.args)
            return [{"test":"hello"}], 200
    
        abort(400)
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
    
    if __name__ == '__main__':
    
        database = runtime_import("database_implementation/")[0].IMPLEMENTATION()
        database.initialize()
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        database.create_user("test_user","12345")
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        database.create_user("test_user2","12345")
    
        database.create_collection(0,"The Sea Wing disaster")
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        # database.create_raw_text_file(0,"some path")
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        database.create_collection(1,"User2's favorite food")
    
    
        database.update_collection_glob(0,"""
    The Sea Wing disaster occurred on July 13, 1890, when a strong squall line overturned the excursion vessel Sea Wing on Lake Pepin near Lake City, Minnesota. Approximately 215 people were aboard the vessel when it overturned and as a result of the accident 98 passengers drowned. An excursion barge that was being towed by the Sea Wing was either cut loose or broke loose and survived the disaster with its passengers unharmed. It is the worst Minnesota maritime disaster ever, and one of the worst maritime disasters that occurred on the upper Mississippi River.[1]
    
    While tornadoes had occurred earlier in the evening farther north in the Twin Cities area, it is believed that downburst winds from a thunderstorm were the cause of the accident.[2][1]
    
    Construction
    Built in 1888 at Diamond Bluff, Wisconsin, as a sternwheel rafter, the Sea Wing was 135 feet (41 m) long and 16 feet (4.9 m) beam amidship.[3] She had a displacement of 110 long tons (110 t) and a height of 22 feet (6.7 m) to her pilot house.[4] The Sea Wing was powered by a six piston steam engine.[5] The Sea Wing was rated for a maximum of 350 passengers when the ship towed two passenger barges on its trips.[6] The safety equipment carried consisted of 175 wood floats, 175 cork and tube life preservers, six axes and seven lifeboats with 28 oars.[6]
    
    History
    Based in Diamond Bluff, Wisconsin, the Sea Wing was jointly owned by Captain David Niles Wethern and Melvin Sparks, operating as the Diamond Jo Line.[6][7] Normally used for moving lumber and commodities along the Mississippi River, the ship was also used for excursions as an extra source of income.[8]
    
    Tragedy
    During July 1890, a Sunday excursion was planned from Red Wing, Minnesota to Lake City, Minnesota. The First Regiment of the Minnesota National Guard's summertime encampment, named Camp Lake View, was scheduled to be held at that time.[9][10]
    
    On the morning of the excursion, 13 July 1890, the Sea Wing left Diamond Bluff, Wisconsin at 7:30 am for its trip to the encampment south of Lake City towing a covered barge named the Jim Grant, which would carry a number of the day's passengers. The Sea Wing first stopped at Trenton, Wisconsin, at 8:30 am and then arrived at Red Wing at 9:30 am, where approximately 150 waiting passengers at Red Wing got on board. Captain Wethern's family was already on board as well as a string orchestra that played for the passengers while the vessel was en route.[9] After leaving Red Wing, the vessel stopped at Frontenac, Minnesota, and then proceeded on to her destination arriving around 11:30 am that morning.[11] The passengers disembarked and spent their time picnicking, visiting the troops and listening to a band concert later in the day.[12]
    
    The return trip was scheduled to leave between 5 - 6 pm that evening, but the national guard had scheduled a dress parade for the visitors.[12] Captain Wethern agreed to delay the departure, after being asked by a number of passengers, until after the parade at 7 pm.[13] Shortly after the parade began, the weather conditions changed and began to look ominous. Captain Wethern began sounding the ship's whistle to recall the passengers and by 8 pm the passengers were on board and the ship was made ready to leave. The captain had been advised to delay his departure by other river men, because they felt that a storm was heading their way, but Captain Wethern believed that the weather looked like it was clearing.[12] The Sea Wing left port and headed on to its first stop at Lake City. A half hour into the voyage Captain Wethern noticed a gale heading toward them from the Minnesota shore. He turned the Sea Wing to meet the storm but a large wave struck the ship tilting it at a forty-five degree angle. While still tilted the ship was struck by strong winds that capsized the ship.
    
    Aftermath
    Following the tragedy, there were conflicting reports that Captain Wethern had been arrested for his own protection.[14] Accusations of drunkenness, overloading of the ship and heading out over objections that the weather conditions were unsafe were leveled against Captain Wethern, as well.[14][15] Further claims that the captain ordered the women and children from the barge and into a cabin which he then locked were made as only seven of the 57 women on board had survived the sinking. It was reported that many of the women had left the barge voluntarily for the ship due to objectionable conduct by fellow passengers.[16]
    
    Inquiry
    An inquiry was begun to ascertain the cause of the disaster with the investigation headed by John D. Sloane, who held the office of Inspector of Steam Vessels. He was assisted by Captains George B. Knapp and Charles F. Yeager, who were two local inspectors from Galena, Illinois, board along with Captains John Monaghan and Michael F. Chalk from the Duluth, Minnesota board who would also take affidavits from the survivors of the accident as part of the investigation.[17][18]
    
    During the inquiry, it was found that while the previous captain of the Sea Wing, Captain H.C. Fuller, was licensed for excursion trips of up to 175 passengers, this license wasn't transferred to Captain Wethern and, by regulation, he was only allowed to carry 12 passengers at that time.[19][20] It was also noted that the captain had no authority to take barges in tow at the time of the accident.[21] Under questioning, Captain Wethern stated that he did not know that under the ship's excursion permit he was required to have an additional pilot on board or the number of required crew needed for handling and manning lifeboats.[22] Captain Wethern also stated under questioning that the life preservers on board were in a "miserably deficient" condition.[23]
    
    Following the inquiry, it was reported on August 11, 1890, that Captain Wethern's license as master and pilot was suspended for "Unskillfullness" in his operation of the vessel.[24][17] It was noted in the report that on the day of the accident, the ship's passenger capacity was exceeded by 30 persons; the passenger list was not correct; starting the voyage in the face of an impending storm and not staying near shore but heading into the center of the lake were factors that lead to the suspension. A recommendation for criminal charges against Captain Wethern by United States District Attorney was also included in the report.[17] Charges were never filed against Captain Wethern following the release of the report.[4]
    
    Salvage operations
    It was reported in August 1890 that the wreckage of the Sea Wing was raised by the crew of the steamer Edward S. Durant Jr. The hull, engines and barge were recovered and purchased by the former owner of the Sea Wing, but the boilers were not recovered at that time.[25] The Sea Wing was rebuilt and placed back in service until it was scrapped a number of years later.[4][26]
    """)
    
    
    fcrisafulli-dev's avatar
    fcrisafulli-dev committed
        app.run()