mirror of
https://github.com/Xevion/linkpulse.git
synced 2026-01-31 02:24:44 -06:00
Minor formatting concerns, remove dangling IPAddress usage
This commit is contained in:
Vendored
+8
-1
@@ -4,19 +4,26 @@
|
|||||||
"backref",
|
"backref",
|
||||||
"bpython",
|
"bpython",
|
||||||
"Callsite",
|
"Callsite",
|
||||||
|
"clsx",
|
||||||
"excepthook",
|
"excepthook",
|
||||||
"inmemory",
|
"inmemory",
|
||||||
"linkpulse",
|
"linkpulse",
|
||||||
"migratehistory",
|
"migratehistory",
|
||||||
"Nixpacks",
|
"Nixpacks",
|
||||||
"ORJSON",
|
"ORJSON",
|
||||||
|
"pext",
|
||||||
|
"pwdlib",
|
||||||
|
"pytest",
|
||||||
"pytz",
|
"pytz",
|
||||||
|
"rtype",
|
||||||
"starlette",
|
"starlette",
|
||||||
"structlog",
|
"structlog",
|
||||||
|
"tailwindcss",
|
||||||
"timestamper"
|
"timestamper"
|
||||||
],
|
],
|
||||||
"python.analysis.extraPaths": ["./backend/"],
|
"python.analysis.extraPaths": ["./backend/"],
|
||||||
"[github-actions-workflow]": {
|
"[github-actions-workflow]": {
|
||||||
"editor.formatOnSave": false
|
"editor.formatOnSave": false
|
||||||
}
|
},
|
||||||
|
"python.analysis.diagnosticMode": "workspace"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,18 @@ setup_logging()
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import structlog
|
|
||||||
|
|
||||||
|
import structlog
|
||||||
|
|
||||||
logger = structlog.get_logger()
|
logger = structlog.get_logger()
|
||||||
|
|
||||||
|
|
||||||
def main(*args):
|
def main(*args: str) -> None:
|
||||||
"""
|
"""Primary entrypoint for the LinkPulse application
|
||||||
Primary entrypoint for the LinkPulse application
|
NOTE: Don't import any modules globally unless you're certain it's necessary. Imports should be tightly controlled.
|
||||||
- Don't import any modules globally unless you're certain it's necessary. Imports should be tightly controlled.
|
:param args: The command-line arguments to parse and execute.
|
||||||
"""
|
:type args: str"""
|
||||||
|
|
||||||
if args[0] == "serve":
|
if args[0] == "serve":
|
||||||
from linkpulse.utilities import is_development
|
from linkpulse.utilities import is_development
|
||||||
from uvicorn import run
|
from uvicorn import run
|
||||||
@@ -57,9 +58,9 @@ def main(*args):
|
|||||||
|
|
||||||
# import most useful objects, models, and functions
|
# import most useful objects, models, and functions
|
||||||
lp = linkpulse # alias
|
lp = linkpulse # alias
|
||||||
from linkpulse.utilities import get_db
|
|
||||||
from linkpulse.app import app
|
from linkpulse.app import app
|
||||||
from linkpulse.models import BaseModel, IPAddress
|
from linkpulse.models import BaseModel, User, Session
|
||||||
|
from linkpulse.utilities import get_db
|
||||||
|
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ with suppress(ImportError):
|
|||||||
|
|
||||||
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
|
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
|
||||||
"""Write your migrations here."""
|
"""Write your migrations here."""
|
||||||
|
|
||||||
@migrator.create_model
|
@migrator.create_model
|
||||||
class User(pw.Model):
|
class User(pw.Model):
|
||||||
id = pw.AutoField()
|
id = pw.AutoField()
|
||||||
@@ -48,12 +48,12 @@ def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
|
|||||||
class Meta:
|
class Meta:
|
||||||
table_name = "user"
|
table_name = "user"
|
||||||
|
|
||||||
migrator.remove_model('ipaddress')
|
migrator.remove_model("ipaddress")
|
||||||
|
|
||||||
|
|
||||||
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
|
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
|
||||||
"""Write your rollback migrations here."""
|
"""Write your rollback migrations here."""
|
||||||
|
|
||||||
@migrator.create_model
|
@migrator.create_model
|
||||||
class IPAddress(pw.Model):
|
class IPAddress(pw.Model):
|
||||||
ip = pw.CharField(max_length=255, primary_key=True)
|
ip = pw.CharField(max_length=255, primary_key=True)
|
||||||
@@ -63,4 +63,4 @@ def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
|
|||||||
class Meta:
|
class Meta:
|
||||||
table_name = "ipaddress"
|
table_name = "ipaddress"
|
||||||
|
|
||||||
migrator.remove_model('user')
|
migrator.remove_model("user")
|
||||||
|
|||||||
@@ -9,12 +9,21 @@ router = APIRouter()
|
|||||||
def validate_session(
|
def validate_session(
|
||||||
token: str, user: bool = True
|
token: str, user: bool = True
|
||||||
) -> Tuple[bool, bool, Optional[User]]:
|
) -> Tuple[bool, bool, Optional[User]]:
|
||||||
"""
|
"""Given a token, validate that the session exists and is not expired.
|
||||||
Given a token, validate that the session exists and is not expired.
|
|
||||||
|
|
||||||
This function has side effects:
|
This function has side effects:
|
||||||
- This function updates last_used if `user` is True.
|
- This function updates last_used if `user` is True.
|
||||||
- This function will invalidate the session if it is expired.
|
- This function will invalidate the session if it is expired.
|
||||||
|
|
||||||
|
:param token: The session token to validate.
|
||||||
|
:type token: str
|
||||||
|
:param user: Whether to update the last_used timestamp of the session.
|
||||||
|
:type user: bool
|
||||||
|
:return: A tuple containing:
|
||||||
|
- A boolean indicating if the session exists.
|
||||||
|
- A boolean indicating if the session is valid.
|
||||||
|
- The User object if the session is valid, otherwise None.
|
||||||
|
:rtype: Tuple[bool, bool, Optional[User]]
|
||||||
"""
|
"""
|
||||||
# Check if session exists
|
# Check if session exists
|
||||||
session = Session.get_or_none(Session.token == token)
|
session = Session.get_or_none(Session.token == token)
|
||||||
@@ -28,3 +37,46 @@ def validate_session(
|
|||||||
if user:
|
if user:
|
||||||
session.use()
|
session.use()
|
||||||
return True, True, session.user
|
return True, True, session.user
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/api/login")
|
||||||
|
async def login():
|
||||||
|
# Validate parameters
|
||||||
|
# Hash regardless of user existence to prevent timing attacks
|
||||||
|
# Check if user exists, return 401 if not
|
||||||
|
# Check if password matches, return 401 if not
|
||||||
|
# Create session
|
||||||
|
# Set Cookie of session token
|
||||||
|
# Return 200 with mild user information
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/api/logout")
|
||||||
|
async def logout():
|
||||||
|
# TODO: Force logout parameter, logout ALL sessions for User
|
||||||
|
# Get session token from Cookie
|
||||||
|
# Delete session
|
||||||
|
# Return 200
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/api/register")
|
||||||
|
async def register():
|
||||||
|
# Validate parameters
|
||||||
|
# Hash password
|
||||||
|
# Create User
|
||||||
|
# Create Session
|
||||||
|
# Set Cookie of session token
|
||||||
|
# Return 200 with mild user information
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/sessions")
|
||||||
|
async def sessions():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# GET /api/user/{id}/sessions
|
||||||
|
# GET /api/user/{id}/sessions/{token}
|
||||||
|
# DELETE /api/user/{id}/sessions
|
||||||
|
# POST /api/user/{id}/logout (delete all sessions)
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
"""Miscellaneous endpoints for the Linkpulse API."""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from fastapi_cache.decorator import cache
|
from fastapi_cache.decorator import cache
|
||||||
from linkpulse.utilities import get_db
|
from linkpulse.utilities import get_db
|
||||||
@@ -9,15 +13,19 @@ db = get_db()
|
|||||||
|
|
||||||
@router.get("/health")
|
@router.get("/health")
|
||||||
async def health():
|
async def health():
|
||||||
|
"""An endpoint to check if the service is running.
|
||||||
|
:return: OK
|
||||||
|
:rtype: Literal['OK']"""
|
||||||
# TODO: Check database connection
|
# TODO: Check database connection
|
||||||
return "OK"
|
return "OK"
|
||||||
|
|
||||||
|
|
||||||
@router.get("/api/migration")
|
@router.get("/api/migration")
|
||||||
@cache(expire=60)
|
@cache(expire=60)
|
||||||
async def get_migration():
|
async def get_migration() -> dict[str, Any]:
|
||||||
"""
|
"""Get the last migration name and timestamp from the migratehistory table.
|
||||||
Returns the details of the most recent migration.
|
:return: The last migration name and timestamp.
|
||||||
|
:rtype: dict[str, Any]
|
||||||
"""
|
"""
|
||||||
# Kind of insecure, but this is just a demo thing to show that migratehistory is available.
|
# Kind of insecure, but this is just a demo thing to show that migratehistory is available.
|
||||||
cursor = db.execute_sql(
|
cursor = db.execute_sql(
|
||||||
|
|||||||
Reference in New Issue
Block a user