From bce756b9aa51dfdfa2c2e6cdef4f88f660b80148 Mon Sep 17 00:00:00 2001 From: Parker Date: Mon, 26 Feb 2024 20:55:05 -0600 Subject: Overhaul: Flask -> FastAPI --- app/func/del_link_records.py | 20 -------------------- app/func/delete_link.py | 20 -------------------- app/func/generate_api_key.py | 23 +++++++++++++++++++++++ app/func/link/delete.py | 20 ++++++++++++++++++++ app/func/link/delrecords.py | 20 ++++++++++++++++++++ app/func/link/records.py | 23 +++++++++++++++++++++++ app/func/link/renew.py | 23 +++++++++++++++++++++++ app/func/link_records.py | 24 ------------------------ app/func/log.py | 6 ++---- app/func/newlink.py | 2 +- app/func/remove_old_data.py | 9 +++++---- app/func/renew_link.py | 23 ----------------------- app/func/signup.py | 24 ------------------------ 13 files changed, 117 insertions(+), 120 deletions(-) delete mode 100644 app/func/del_link_records.py delete mode 100644 app/func/delete_link.py create mode 100644 app/func/generate_api_key.py create mode 100644 app/func/link/delete.py create mode 100644 app/func/link/delrecords.py create mode 100644 app/func/link/records.py create mode 100644 app/func/link/renew.py delete mode 100644 app/func/link_records.py delete mode 100644 app/func/renew_link.py delete mode 100644 app/func/signup.py (limited to 'app/func') diff --git a/app/func/del_link_records.py b/app/func/del_link_records.py deleted file mode 100644 index fbbce0e..0000000 --- a/app/func/del_link_records.py +++ /dev/null @@ -1,20 +0,0 @@ -import sqlalchemy - -from db import engine - -""" -Delete all of the IP log records that are associated with a specific link -""" -def del_link_records(link, owner): - with engine.begin() as conn: - try: - link_owner = conn.execute(sqlalchemy.text('SELECT owner FROM links WHERE link = :link'), [{'link': link}]).fetchone()[0] - except TypeError: - return 'Link does not exist', 200 - - if owner == link_owner: - with engine.begin() as conn: - conn.execute(sqlalchemy.text('DELETE FROM records WHERE link = :link'), [{'link': link}]) - return 'Link records have been deleted', 200 - else: - return 'You are not the owner of this link', 401 \ No newline at end of file diff --git a/app/func/delete_link.py b/app/func/delete_link.py deleted file mode 100644 index c036af3..0000000 --- a/app/func/delete_link.py +++ /dev/null @@ -1,20 +0,0 @@ -import sqlalchemy - -from db import engine - -""" -Delete the specified link from the users associated links -""" -def delete_link(link, owner): - with engine.begin() as conn: - try: - link_owner = conn.execute(sqlalchemy.text('SELECT owner FROM links WHERE link = :link'), [{'link': link}]).fetchone()[0] - except TypeError: - return 'Link does not exist', 200 - - if owner == link_owner: - with engine.begin() as conn: - conn.execute(sqlalchemy.text('DELETE FROM links WHERE link = :link'), [{'link': link}]) - return 'Link has been deleted', 200 - else: - return 'You are not the owner of this link', 401 \ No newline at end of file diff --git a/app/func/generate_api_key.py b/app/func/generate_api_key.py new file mode 100644 index 0000000..a40c96a --- /dev/null +++ b/app/func/generate_api_key.py @@ -0,0 +1,23 @@ +import sqlalchemy +from sqlalchemy import exc +import random +import string + +from db import engine + +""" +Generate and return a randomized API key string for the user +Keys are composed of 20 uppercase ASCII characters +""" +def generate_api_key(): + with engine.begin() as conn: + while True: + try: + api_key_string = ''.join(random.choices(string.ascii_uppercase, k=20)) + conn.execute(sqlalchemy.text('INSERT INTO keys(api_key) VALUES(:api_key)'), [{'api_key': api_key_string}]) + conn.commit() + break + except exc.IntegrityError: + continue + + return api_key_string \ No newline at end of file diff --git a/app/func/link/delete.py b/app/func/link/delete.py new file mode 100644 index 0000000..97b696e --- /dev/null +++ b/app/func/link/delete.py @@ -0,0 +1,20 @@ +import sqlalchemy + +from db import engine + +""" +Delete the specified link from the users associated links +""" +def delete_link(link, owner): + with engine.begin() as conn: + try: + link_owner = conn.execute(sqlalchemy.text('SELECT owner FROM links WHERE link = :link'), [{'link': link}]).fetchone()[0] + except TypeError: + return 404 + + if owner == link_owner: + with engine.begin() as conn: + conn.execute(sqlalchemy.text('DELETE FROM links WHERE link = :link'), [{'link': link}]) + return link + else: + return 401 \ No newline at end of file diff --git a/app/func/link/delrecords.py b/app/func/link/delrecords.py new file mode 100644 index 0000000..d82bfa5 --- /dev/null +++ b/app/func/link/delrecords.py @@ -0,0 +1,20 @@ +import sqlalchemy + +from db import engine + +""" +Delete all of the IP log records that are associated with a specific link +""" +def delete_link_records(link, owner): + with engine.begin() as conn: + try: + link_owner = conn.execute(sqlalchemy.text('SELECT owner FROM links WHERE link = :link'), [{'link': link}]).fetchone()[0] + except TypeError: + return 404 + + if owner == link_owner: + with engine.begin() as conn: + conn.execute(sqlalchemy.text('DELETE FROM records WHERE link = :link'), [{'link': link}]) + return link + else: + return 401 \ No newline at end of file diff --git a/app/func/link/records.py b/app/func/link/records.py new file mode 100644 index 0000000..56bb6d2 --- /dev/null +++ b/app/func/link/records.py @@ -0,0 +1,23 @@ +import sqlalchemy + +from db import engine + +""" +Retrieve all records associated with a specific link +""" +def get_link_records(link, owner): + with engine.begin() as conn: + try: + link_owner = conn.execute(sqlalchemy.text('SELECT owner FROM links WHERE link = :link'), [{'link': link}]).fetchone()[0] + except TypeError: + return 404 + + if owner == link_owner: + with engine.begin() as conn: + records = conn.execute(sqlalchemy.text('SELECT timestamp, ip, location, browser, os, user_agent, isp FROM records WHERE owner = :owner and link = :link'), [{'owner': owner, 'link': link}]).fetchall() + if not records: + return 204 + else: + return 401 + + return records \ No newline at end of file diff --git a/app/func/link/renew.py b/app/func/link/renew.py new file mode 100644 index 0000000..bcf0550 --- /dev/null +++ b/app/func/link/renew.py @@ -0,0 +1,23 @@ +import sqlalchemy +import datetime + +from db import engine + +""" +Renew a specified link so that the user can continue logging through that URL +Adds 7 days from the current date +""" +def renew_link(link, owner): + with engine.begin() as conn: + try: + link_owner = conn.execute(sqlalchemy.text('SELECT owner FROM links WHERE link = :link'), [{'link': link}]).fetchone()[0] + except TypeError: + return 404 + + if owner == link_owner: + with engine.begin() as conn: + expire_date = datetime.datetime.date(datetime.datetime.now()) + datetime.timedelta(days=7) + conn.execute(sqlalchemy.text('UPDATE links SET expire_date = :expire_date WHERE link = :link'), [{'expire_date': expire_date, 'link': link}]) + return link, expire_date + else: + return 401 \ No newline at end of file diff --git a/app/func/link_records.py b/app/func/link_records.py deleted file mode 100644 index a29f8dd..0000000 --- a/app/func/link_records.py +++ /dev/null @@ -1,24 +0,0 @@ -import sqlalchemy -import tabulate - -from db import engine - -""" -Retrieve all records associated with a specific link -""" -def link_records(link, owner): - with engine.begin() as conn: - try: - link_owner = conn.execute(sqlalchemy.text('SELECT owner FROM links WHERE link = :link'), [{'link': link}]).fetchone()[0] - except TypeError: - return 'Link does not exist', 200 - - if owner == link_owner: - with engine.begin() as conn: - records = conn.execute(sqlalchemy.text('SELECT timestamp, ip, location, browser, os, user_agent, isp FROM records WHERE owner = :owner and link = :link'), [{'owner': owner, 'link': link}]).fetchall() - if not records: - return 'No records are associated with this link', 200 - else: - return 'You are not the owner of this link', 401 - - return tabulate.tabulate(records, headers=['Timestamp', 'IP', 'Location', 'Browser', 'OS', 'User Agent', 'ISP']), 200 \ No newline at end of file diff --git a/app/func/log.py b/app/func/log.py index 1199f43..da6594a 100644 --- a/app/func/log.py +++ b/app/func/log.py @@ -39,7 +39,7 @@ ipgeolocation = ip2locationio.IPGeolocation(configuration) """ Create a new log record whenever a link is visited """ -def log(link, request): +def log(link, ip, user_agent): with engine.begin() as conn: try: redirect_link, owner = conn.execute(sqlalchemy.text('SELECT redirect_link, owner FROM links WHERE link = :link'), [{'link': link}]).fetchone() @@ -50,7 +50,7 @@ def log(link, request): if ip_to_location == 'TRUE': # Get IP to GEO via IP2Location.io try: - data = ipgeolocation.lookup(request.access_route[-1]) + data = ipgeolocation.lookup(ip) location = f'{data["country_name"]}, {data["city_name"]}' isp = data['as'] # Fatal error, API key is invalid or out of requests, quit @@ -63,8 +63,6 @@ def log(link, request): isp = '-' timestamp = datetime.datetime.now() - ip = request.access_route[-1] - user_agent = request.user_agent.string ua_string = user_agent_parser.Parse(user_agent) browser = ua_string['user_agent']['family'] os = f'{ua_string["os"]["family"]} {ua_string["os"]["major"]}' diff --git a/app/func/newlink.py b/app/func/newlink.py index c726499..06776e6 100644 --- a/app/func/newlink.py +++ b/app/func/newlink.py @@ -13,7 +13,7 @@ Links are composed of 5 uppercase ASCII characters + numbers """ def generate_link(redirect_link, owner): if not validators.url(redirect_link): - return None + return 422 with engine.begin() as conn: choices = string.ascii_uppercase + '1234567890' diff --git a/app/func/remove_old_data.py b/app/func/remove_old_data.py index 7380fc5..96d08fa 100644 --- a/app/func/remove_old_data.py +++ b/app/func/remove_old_data.py @@ -17,7 +17,8 @@ def remove_old_data(): link = row.link delete_links.append({'link': link}) - with engine.begin() as conn: - conn.execute(sqlalchemy.text('DELETE FROM links WHERE link = :link'), delete_links) - conn.execute(sqlalchemy.text('DELETE FROM records WHERE link = :link'), delete_links) - conn.commit() + if delete_links: + with engine.begin() as conn: + conn.execute(sqlalchemy.text('DELETE FROM links WHERE link = :link'), delete_links) + conn.execute(sqlalchemy.text('DELETE FROM records WHERE link = :link'), delete_links) + conn.commit() diff --git a/app/func/renew_link.py b/app/func/renew_link.py deleted file mode 100644 index 9d31c33..0000000 --- a/app/func/renew_link.py +++ /dev/null @@ -1,23 +0,0 @@ -import sqlalchemy -import datetime - -from db import engine - -""" -Renew a specified link so that the user can continue logging through that URL -Adds 7 days from the current date -""" -def renew_link(link, owner): - with engine.begin() as conn: - try: - link_owner = conn.execute(sqlalchemy.text('SELECT owner FROM links WHERE link = :link'), [{'link': link}]).fetchone()[0] - except TypeError: - return 'Link does not exist', 200 - - if owner == link_owner: - with engine.begin() as conn: - expire_date = datetime.datetime.date(datetime.datetime.now()) + datetime.timedelta(days=7) - conn.execute(sqlalchemy.text('UPDATE links SET expire_date = :expire_date WHERE link = :link'), [{'expire_date': expire_date, 'link': link}]) - return f'Link renewed, now expires on {expire_date}', 200 - else: - return 'You are not the owner of this link', 401 \ No newline at end of file diff --git a/app/func/signup.py b/app/func/signup.py deleted file mode 100644 index 275a14e..0000000 --- a/app/func/signup.py +++ /dev/null @@ -1,24 +0,0 @@ -import sqlalchemy -from sqlalchemy import exc -import random -import string - -from db import engine - -""" -Generate and return a randomized account string for the user -Account strings function as API authenticaton keys and are composed -of 20 uppercase ASCII characters -""" -def generate_account(): - with engine.begin() as conn: - while True: - try: - account_string = ''.join(random.choices(string.ascii_uppercase, k=20)) - conn.execute(sqlalchemy.text('INSERT INTO accounts(api_key) VALUES(:api_key)'), [{'api_key': account_string}]) - conn.commit() - break - except exc.IntegrityError: - continue - - return account_string \ No newline at end of file -- cgit v1.2.3-70-g09d2