update many files

This commit is contained in:
ben
2026-08-03 16:21:10 +02:00
parent 9e69edc08b
commit cff9aa0dd1
5 changed files with 220 additions and 110 deletions
+8 -22
View File
@@ -5,7 +5,10 @@ from datetime import datetime, timedelta
from fastapi import Header, HTTPException from fastapi import Header, HTTPException
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
security = HTTPBearer()
load_dotenv() load_dotenv()
SECRET_KEY = os.getenv("SECRET_KEY") SECRET_KEY = os.getenv("SECRET_KEY")
@@ -64,19 +67,10 @@ def verify_user(username, password):
return None return None
def get_current_user(authorization: str = Header(None)): def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security)
if authorization is None: ):
raise HTTPException( token = credentials.credentials
status_code=401,
detail="Missing token"
)
try:
scheme, token = authorization.split(" ")
if scheme.lower() != "bearer":
raise Exception()
payload = jwt.decode( payload = jwt.decode(
token, token,
@@ -84,12 +78,4 @@ def get_current_user(authorization: str = Header(None)):
algorithms=[ALGORITHM] algorithms=[ALGORITHM]
) )
user_id = payload["user_id"] return payload["user_id"]
return user_id
except JWTError:
raise HTTPException(
status_code=401,
detail="Invalid token"
)
+115 -54
View File
@@ -1,22 +1,24 @@
from fastapi import FastAPI from fastapi import FastAPI, Depends
from pydantic import BaseModel from pydantic import BaseModel
from database import fetch_all from database import fetch_all, fetch_one
from events import create_event from events import create_event
from auth import create_user, verify_user, create_token from auth import create_user, verify_user, create_token, get_current_user
from rooms import create_room, search_room, accept_room from rooms import create_room, search_room, accept_room
class Login(BaseModel): class Login(BaseModel):
username: str username: str
password: str password: str
class UserCreate(BaseModel): class UserCreate(BaseModel):
username: str username: str
password: str password: str
class EventCreate(BaseModel): class EventCreate(BaseModel):
room_id: int room_id: int
creator_id: int
type: str type: str
title: str title: str
description: str description: str
@@ -26,19 +28,20 @@ class EventCreate(BaseModel):
status: str status: str
min_people: int min_people: int
class RoomCreate(BaseModel): class RoomCreate(BaseModel):
room_name: str room_name: str
creator_id: int
invite_code: str invite_code: str
class RoomSearch(BaseModel): class RoomSearch(BaseModel):
user_id: int
invite_code: str invite_code: str
class RoomJoin(BaseModel): class RoomJoin(BaseModel):
user_id: int
invite_code: str invite_code: str
app = FastAPI( app = FastAPI(
title="Calendar API", title="Calendar API",
description="Room based agenda system", description="Room based agenda system",
@@ -50,8 +53,7 @@ app = FastAPI(
def home(): def home():
return { return {
"status": "online", "status": "online",
"service": "Calendar API", "service": "Calendar API"
"cheese": "tasty"
} }
@@ -66,42 +68,15 @@ def database_status():
} }
@app.post("/events") # users
def api_create_event(event: EventCreate):
event_id = create_event(
room_id=event.room_id,
creator_id=event.creator_id,
type=event.type,
title=event.title,
description=event.description,
start_time=event.start_time,
end_time=event.end_time,
visibility=event.visibility,
status=event.status,
min_people=event.min_people
)
return {
"status": "created",
"event_id": event_id
}
@app.get("/events")
def get_events():
events = fetch_all("SELECT * FROM events;")
return {
"events": [dict(event) for event in events]
}
@app.post("/create-user") @app.post("/create-user")
def api_create_user(user: UserCreate): def api_create_user(user: UserCreate):
user_id = create_user( user_id = create_user(
username=user.username, user.username,
password=user.password, user.password
) )
return { return {
@@ -109,6 +84,7 @@ def api_create_user(user: UserCreate):
"user_id": user_id "user_id": user_id
} }
@app.post("/login") @app.post("/login")
def api_login(login: Login): def api_login(login: Login):
@@ -131,46 +107,65 @@ def api_login(login: Login):
} }
@app.post("/create_room") @app.get("/me")
def api_create_room(room: RoomCreate): def get_me(
user_id: int = Depends(get_current_user)
):
return {
"user_id": user_id
}
# rooms
@app.post("/create-room")
def api_create_room(
room: RoomCreate,
user_id: int = Depends(get_current_user)
):
room_id = create_room( room_id = create_room(
room.room_name, room.room_name,
room.creator_id, user_id,
room.invite_code room.invite_code
) )
if room_id is None:
return { return {
"status": "failed" "status": "created",
}
return {
"status": "success",
"room_id": room_id "room_id": room_id
} }
@app.post("/search-room") @app.post("/search-room")
def api_search_room(search_for_room: RoomSearch): def api_search_room(
room: RoomSearch
):
room_name = search_room( room_name = search_room(
search_for_room.invite_code room.invite_code
) )
if room_name is None: if room_name is None:
return { return {
"status": "failed" "status": "failed",
"reason": "room_not_found"
} }
return { return {
"status": "success", "status": "found",
"room_name": room_name "room_name": room_name
} }
@app.post("/join-room") @app.post("/join-room")
def api_join_room(room: RoomJoin): def api_join_room(
room: RoomJoin,
user_id: int = Depends(get_current_user)
):
result = accept_room( result = accept_room(
room.user_id, user_id,
room.invite_code room.invite_code
) )
@@ -184,3 +179,69 @@ def api_join_room(room: RoomJoin):
"status": "joined", "status": "joined",
**result **result
} }
# events
@app.post("/events")
def api_create_event(
event: EventCreate,
user_id: int = Depends(get_current_user)
):
# check of gebruiker lid is
member = fetch_one(
"""
SELECT *
FROM room_members
WHERE room_id = ?
AND user_id = ?
""",
(
event.room_id,
user_id
)
)
if member is None:
return {
"status": "failed",
"reason": "not_room_member"
}
event_id = create_event(
room_id=event.room_id,
creator_id=user_id,
type=event.type,
title=event.title,
description=event.description,
start_time=event.start_time,
end_time=event.end_time,
visibility=event.visibility,
status=event.status,
min_people=event.min_people
)
return {
"status": "created",
"event_id": event_id
}
@app.get("/events")
def get_events(
user_id: int = Depends(get_current_user)
):
events = fetch_all(
"""
SELECT *
FROM events
WHERE creator_id = ?
""",
(user_id,)
)
return {
"events": [dict(event) for event in events]
}
+29 -14
View File
@@ -81,39 +81,54 @@ def search_room(
return room["name"] return room["name"]
def accept_room( def accept_room(user_id, invite_code):
user_id,
invite_code
):
query = """ query = """
SELECT id SELECT id
FROM rooms FROM rooms
WHERE invite_code = ? WHERE invite_code = ?
""" """
room = fetch_one( room = fetch_one(
query, query,
( (invite_code,)
invite_code,
)
) )
if room is None: if room is None:
return None return None
room_id = room["id"] room_id = room["id"]
role = DEFAULT_ROLE
query2 = """ # check dubbele join
INSERT INTO "main"."room_members" existing = fetch_one(
("room_id", "user_id", "role") """
VALUES (?, ?, ?); SELECT id
FROM room_members
WHERE room_id = ?
AND user_id = ?
""",
(
room_id,
user_id
)
)
if existing:
return None
query = """
INSERT INTO room_members
(room_id, user_id, role)
VALUES (?, ?, ?)
""" """
member_id = execute( member_id = execute(
query2, query,
( (
room_id, room_id,
user_id, user_id,
role "member"
) )
) )
Binary file not shown.
+60 -12
View File
@@ -3,8 +3,13 @@ import sqlite3
DB_NAME = "calendar.db" DB_NAME = "calendar.db"
conn = sqlite3.connect(DB_NAME) conn = sqlite3.connect(DB_NAME)
# SQLite foreign keys activeren
conn.execute("PRAGMA foreign_keys = ON;")
cur = conn.cursor() cur = conn.cursor()
cur.execute(""" cur.execute("""
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -13,73 +18,116 @@ CREATE TABLE IF NOT EXISTS users (
); );
""") """)
cur.execute(""" cur.execute("""
CREATE TABLE IF NOT EXISTS rooms ( CREATE TABLE IF NOT EXISTS rooms (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, name TEXT NOT NULL,
owner_id INTEGER NOT NULL, owner_id INTEGER NOT NULL,
invite_code TEXT UNIQUE, invite_code TEXT NOT NULL UNIQUE,
FOREIGN KEY (owner_id) REFERENCES users(id) FOREIGN KEY (owner_id) REFERENCES users(id)
); );
""") """)
cur.execute(""" cur.execute("""
CREATE TABLE IF NOT EXISTS room_members ( CREATE TABLE IF NOT EXISTS room_members (
room_id INTEGER NOT NULL, room_id INTEGER NOT NULL,
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL,
role TEXT NOT NULL DEFAULT 'member', role TEXT NOT NULL DEFAULT 'member'
CHECK(role IN ('owner', 'admin', 'member')),
PRIMARY KEY (room_id, user_id), PRIMARY KEY (room_id, user_id),
FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE, FOREIGN KEY (room_id)
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE REFERENCES rooms(id)
ON DELETE CASCADE,
FOREIGN KEY (user_id)
REFERENCES users(id)
ON DELETE CASCADE
); );
""") """)
cur.execute(""" cur.execute("""
CREATE TABLE IF NOT EXISTS events ( CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
room_id INTEGER NOT NULL, room_id INTEGER NOT NULL,
creator_id INTEGER NOT NULL, creator_id INTEGER NOT NULL,
type TEXT NOT NULL CHECK(type IN ('private', 'busy', 'proposal')), type TEXT NOT NULL
CHECK(type IN ('private', 'busy', 'proposal')),
title TEXT NOT NULL, title TEXT NOT NULL,
description TEXT, description TEXT,
start_time TEXT NOT NULL, start_time TEXT NOT NULL,
end_time TEXT NOT NULL, end_time TEXT NOT NULL,
visibility TEXT NOT NULL CHECK(visibility IN ('private', 'busy_only', 'room')), visibility TEXT NOT NULL
CHECK(visibility IN ('private', 'busy_only', 'room')),
status TEXT NOT NULL DEFAULT 'draft' status TEXT NOT NULL DEFAULT 'draft'
CHECK(status IN ('draft', 'proposed', 'confirmed', 'cancelled')), CHECK(status IN ('draft', 'proposed', 'confirmed', 'cancelled')),
min_people INTEGER DEFAULT 0, min_people INTEGER DEFAULT 0,
FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE, FOREIGN KEY (room_id)
FOREIGN KEY (creator_id) REFERENCES users(id) REFERENCES rooms(id)
ON DELETE CASCADE,
FOREIGN KEY (creator_id)
REFERENCES users(id)
); );
""") """)
cur.execute(""" cur.execute("""
CREATE TABLE IF NOT EXISTS event_signups ( CREATE TABLE IF NOT EXISTS event_signups (
event_id INTEGER NOT NULL, event_id INTEGER NOT NULL,
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL,
status TEXT NOT NULL DEFAULT 'going' status TEXT NOT NULL DEFAULT 'going'
CHECK(status IN ('going', 'maybe', 'declined')), CHECK(status IN ('going', 'maybe', 'declined')),
PRIMARY KEY (event_id, user_id), PRIMARY KEY(event_id, user_id),
FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE, FOREIGN KEY(event_id)
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE REFERENCES events(id)
ON DELETE CASCADE,
FOREIGN KEY(user_id)
REFERENCES users(id)
ON DELETE CASCADE
); );
""") """)
# Snellere zoekopdrachten
cur.execute("""
CREATE INDEX IF NOT EXISTS idx_room_members_user
ON room_members(user_id);
""")
cur.execute("""
CREATE INDEX IF NOT EXISTS idx_events_room
ON events(room_id);
""")
conn.commit() conn.commit()
print("Database aangemaakt.") print("Database aangemaakt.")
print("Tabellen:") print("Tabellen:")
for row in cur.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"):
for row in cur.execute(
"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"
):
print(" -", row[0]) print(" -", row[0])
conn.close() conn.close()