update many files
This commit is contained in:
+8
-22
@@ -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
@@ -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
@@ -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
@@ -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()
|
||||||
Reference in New Issue
Block a user