aboutsummaryrefslogtreecommitdiff
path: root/app/routes.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/routes.py')
-rw-r--r--app/routes.py228
1 files changed, 151 insertions, 77 deletions
diff --git a/app/routes.py b/app/routes.py
index fa73297..da8a502 100644
--- a/app/routes.py
+++ b/app/routes.py
@@ -1,120 +1,194 @@
import fastapi
-from fastapi import Security, HTTPException
-from fastapi.security import APIKeyHeader
-import tabulate
+from fastapi import Security, HTTPException, Request
import pydantic
import sqlalchemy
from db import engine
-from auth import auth
-from func.signup import generate_account
+from check_api_key import check_api_key
+from func.generate_api_key import generate_api_key
from func.newlink import generate_link
from func.log import log
-from func.delete_link import delete_link
-from func.renew_link import renew_link
-from func.link_records import link_records
-from func.del_link_records import del_link_records
+from func.link.delete import delete_link
+from func.link.renew import renew_link
+from func.link.records import get_link_records
+from func.link.delrecords import delete_link_records
+from func.remove_old_data import remove_old_data
+
+from apscheduler.schedulers.background import BackgroundScheduler
+from contextlib import asynccontextmanager
+
+
+@asynccontextmanager
+async def lifespan(app: fastapi.FastAPI):
+ # Create the scheduler
+ scheduler = BackgroundScheduler()
+ scheduler.add_job(remove_old_data, "cron", hour="0", minute="01")
+ scheduler.start()
+ yield
class Newlink(pydantic.BaseModel):
redirect_link: str
-app = fastapi.FastAPI()
-api_key_header = APIKeyHeader(name="X-API-Key")
+app = fastapi.FastAPI(lifespan=lifespan)
-def check_api_key(api_key_header: str = Security(api_key_header)) -> str:
- with engine.begin() as conn:
- response = conn.execute(sqlalchemy.text("SELECT api_key FROM accounts WHERE api_key = :api_key"), {'api_key': api_key_header}).fetchone()
- if response:
- return response[0]
- else:
- raise HTTPException(
- status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
- detail="Invalid or missing API key"
- )
-
-@app.get("/signup")
-async def signup():
- api_key = generate_account()
+@app.post("/api/getapikey")
+async def get_api_key():
+ """
+ Create a new API key
+ """
+ api_key = generate_api_key()
return {"api_key": api_key}
-@app.post("/newlink")
+@app.post("/api/genlink")
async def newlink(newlink: Newlink, api_key: str = Security(check_api_key)):
+ """
+ Generate a new link that will redirect to the specified URL and log IPs in the middle
+ """
data = generate_link(newlink.redirect_link, api_key)
- if data:
- return {"link": data[0], "expire_date": data[1]}
- else:
+ if data == 422:
raise HTTPException(
status_code=fastapi.status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Malformed redirect link provided"
)
+ return {"link": data[0], "expire_date": data[1]}
-@app.post("/links")
-async def links(api_key: str = Security(check_api_key)):
- with engine.begin() as conn:
- links = conn.execute(sqlalchemy.text("SELECT link, expire_date FROM links WHERE owner = :owner"), [{"owner": api_key}]).fetchall()
- response = []
- for link, expire_date in links:
- response.append({"link": link, "expire_date": expire_date})
- return response
-
-
-@app.post("/records")
+"""
+Return all records associated with an API key, no matter the link
+"""
+@app.get("/api/records")
async def records(api_key: str = Security(check_api_key)):
+ """
+ Get ALL IP logs records for every link tied to your API key
+ """
with engine.begin() as conn:
records = conn.execute(sqlalchemy.text("SELECT timestamp, ip, location, browser, os, user_agent, isp FROM records WHERE owner = :owner"), [{"owner": api_key}]).fetchall()
if not records:
- return flask.jsonify('No records found'), 200
+ return {"records": "No records are associated with this API key"}
+
+ response = []
+ for timestamp, ip, location, browser, os, user_agent, isp in records:
+ response.append({"timestamp": timestamp, "ip": ip, "location": location, "browser": browser, "os": os, "user_agent": user_agent, "isp": isp})
+
+ return response
- return tabulate.tabulate(records, headers=['Timestamp', 'IP', 'Location', 'Browser', 'OS', 'User Agent', 'ISP']), 200
+@app.get("/{link}")
+def link(link, request: Request):
+ ip = request.client.host
+ user_agent = request.headers.get("user-agent")
+ redirect_link = log(link, ip, user_agent)
+ return fastapi.responses.RedirectResponse(url=redirect_link)
-# """
-# Return all records associated with an account, no matter the link
-# """
-# @app.route('/records', methods=['POST'])
-# @auth.login_required
-# def records():
+"""
+Return all links associated with an API key
+"""
+@app.get("/api/links")
+async def links(api_key: str = Security(check_api_key)):
+ """
+ Retrieve all links that are currently tied to your API key
+ """
+ with engine.begin() as conn:
+ links = conn.execute(sqlalchemy.text("SELECT link, expire_date FROM links WHERE owner = :owner"), [{"owner": api_key}]).fetchall()
+
+ if not links:
+ return {"links": "No links are associated with this API key"}
+
+ response = []
+ for link, expire_date in links:
+ response.append({"link": link, "expire_date": expire_date})
+ return response
-# @app.route('/<link>', methods=['GET'])
-# def link(link):
-# redirect_link = log(link, flask.request)
-# return flask.redirect(redirect_link)
+@app.post("/api/{link}/delete")
+async def link_delete(link: str, api_key: str = Security(check_api_key)):
+ """
+ Delete the specified link and all records associated with it
+ """
+ data = delete_link(link, api_key)
+ if data == 404:
+ raise HTTPException(
+ status_code=fastapi.status.HTTP_404_NOT_FOUND,
+ detail="Link does not exist"
+ )
+ if data == 401:
+ raise HTTPException(
+ status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
+ detail="Link not associated with given API key"
+ )
+ else:
+ return {"link": f"The link {data} has been deleted"}
-# @app.route('/<link>/delete', methods=['POST'])
-# @auth.login_required
-# def link_delete(link):
-# response = delete_link(link, auth.current_user())
-# return flask.jsonify(msg=response[0]), response[1]
+@app.post("/api/{link}/renew")
+async def link_renew(link: str, api_key: str = Security(check_api_key)):
+ """
+ Renew a specifiec link (adds 7 more days from the current date)
+ """
+ data = renew_link(link, api_key)
+ if data == 404:
+ raise HTTPException(
+ status_code=fastapi.status.HTTP_404_NOT_FOUND,
+ detail="Link does not exist"
+ )
+ if data == 401:
+ raise HTTPException(
+ status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
+ detail="Link not associated with given API key"
+ )
+ else:
+ return {"link": f"The link {data[0]} has been renewed and will expire on {data[1]}"}
-# @app.route('/<link>/renew', methods=['POST'])
-# @auth.login_required
-# def renew_link(link):
-# response = renew_link(link, auth.current_user())
-# return flask.jsonify(msg=response[0]), response[1]
+@app.get("/api/{link}/records")
+async def link_records(link: str, api_key: str = Security(check_api_key)):
+ """
+ Retrieve all IP log records for the specified link
+ """
+ data = get_link_records(link, api_key)
+ if data == 404:
+ raise HTTPException(
+ status_code=fastapi.status.HTTP_404_NOT_FOUND,
+ detail="Link does not exist"
+ )
+ if data == 401:
+ raise HTTPException(
+ status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
+ detail="Link not associated with given API key"
+ )
+ if data == 204:
+ raise HTTPException(
+ status_code=fastapi.status.HTTP_204_NO_CONTENT,
+ detail="No records found"
+ )
+ else:
+ response = []
+ for timestamp, ip, location, browser, os, user_agent, isp in data:
+ response.append({"timestamp": timestamp, "ip": ip, "location": location, "browser": browser, "os": os, "user_agent": user_agent, "isp": isp})
-# @app.route('/<link>/records', methods=['POST'])
-# @auth.login_required
-# def records_link(link):
-# response = link_records(link, auth.current_user())
-# # If we jsonify the tabulate string it fucks it up, so we have to return
-# # it normally, this check does that
-# if response[0].startswith('Timestamp'):
-# return response[0], response[1]
-# else:
-# return flask.jsonify(msg=response[0]), response[1]
+ return response
-# @app.route('/<link>/delrecords', methods=['POST'])
-# @auth.login_required
-# def records_delete(link):
-# response = del_link_records(link, auth.current_user())
-# return flask.jsonify(msg=response[0]), response[1] \ No newline at end of file
+@app.post("/api/{link}/delrecords")
+async def link_delrecords(link: str, api_key: str = Security(check_api_key)):
+ """
+ Delete all IP log records for the specified link
+ """
+ data = delete_link_records(link, api_key)
+ if data == 404:
+ raise HTTPException(
+ status_code=fastapi.status.HTTP_404_NOT_FOUND,
+ detail="Link does not exist"
+ )
+ if data == 401:
+ raise HTTPException(
+ status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
+ detail="Link not associated with given API key"
+ )
+ else:
+ return {"link": f"The records for link {data} have been deleted"} \ No newline at end of file