requirements.txt changed, auth.py file added for user management, announcement_service_spec.yaml changed since api definition did not load, main.py changes to access new mongoDB collection, patchnotes_controller.py expendet so save user last login

This commit is contained in:
Justin Weins 2025-05-21 17:02:09 +02:00
parent bdf0466d79
commit 7f8d7cbc86
5 changed files with 78 additions and 41 deletions

View File

@ -16,8 +16,6 @@ paths:
operationId: listPatchnotes
parameters:
- $ref: '#/components/parameters/SinceParam'
- $ref: '#/components/parameters/LimitParam'
- $ref: '#/components/parameters/OffsetParam'
responses:
"200":
description: list of patch notes
@ -55,6 +53,23 @@ paths:
"400":
description: bad payload
/patchnotes/all:
get:
tags: [Patchnotes]
summary: Returns **all** patch notes (admin area)
operationId: listAllPatchnotes
responses:
"200":
description: list of all patch notes
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/patch_notes'
"404":
description: no Patch notes found
/patchnotes/{patchID}:
parameters:
- in: path
@ -119,25 +134,6 @@ components:
schema:
type: string
format: date
LimitParam:
name: limit
in: query
description: Maximum number of items to return
required: false
schema:
type: integer
default: 20
minimum: 1
maximum: 100
OffsetParam:
name: offset
in: query
description: Pagination offset
required: false
schema:
type: integer
default: 0
minimum: 0
schemas:
patch_notes:
@ -161,10 +157,10 @@ components:
title: Patch note 1
changes: Fixed export bug
version: 1.0.0
patch_date: 2025-01-02
patch_date: '2025-01-02' # ← als String in Quotes!
patch_notes_input:
description: Schema for POST/PUT (server generates patchID & patch_date if omitted)
description: Schema for POST/PUT (server generates patchID if omitted)
type: object
properties:
title:
@ -177,6 +173,11 @@ components:
type: string
format: date
required: [title, changes, version, patch_date]
example:
title: Patch note 1
changes: Fixed export bug
version: 1.0.0
patch_date: '2025-01-02' # ← ebenfalls in Quotes
responses:
Error400:

View File

@ -6,13 +6,18 @@ from connexion.middleware import MiddlewarePosition
from flask import Flask
from openapi_server import encoder
from pymongo import MongoClient
from pymongo import MongoClient, ASCENDING
from starlette.middleware.cors import CORSMiddleware
import re
client = MongoClient(host='mongodb://admin:admin@announcement-service-database-svc:27017/?authSource=admin')
db = client["MainDB"]
collection = db['patch_notes']
last_login_collection = db["user_last_login"]
last_login_collection.create_index(
[("user_id", ASCENDING)], unique=True, name="user_id_unique"
)
app = connexion.FlaskApp(__name__, specification_dir='./openapi/')

View File

@ -15,8 +15,9 @@ from connexion import ProblemException
from flask import Response
from __main__ import collection
from openapi_server.__main__ import collection
from openapi_server.__main__ import collection, last_login_collection
from openapi_server.models.patch_notes import PatchNotes
from openapi_server.utils.auth import current_user_id
def create_patchnote(body): # noqa: E501
@ -119,36 +120,46 @@ def get_patchnote(patch_id): # noqa: E501
def list_patchnotes(since: str | None = None):
# 1) validate query param only if present
"""GET /patchnotes liefert neue Patchnotes und setzt last_login."""
user_id = current_user_id() # 1) aktueller Benutzer
# 2) Wenn ?since fehlt, gespeichertes last_login holen
if since is None:
rec = last_login_collection.find_one({"user_id": user_id})
since = rec["last_login"] if rec else None
# 3) Datum validieren (nur wenn vorhanden)
if since:
try:
datetime.strptime(since, "%Y-%m-%d")
except ValueError:
raise ProblemException(
title="Bad Request",
detail="The date is invalid. Needs to be in this format YYYY-MM-DD",
detail="since must be YYYY-MM-DD",
status=400,
)
query = {"patch_date": {"$gte": since}}
mongo_filter = {"patch_date": {"$gte": since}}
else:
query = {} # no filter -> all notes
mongo_filter = {} # erster Login → alle Notes
# 2) fetch from Mongo
docs = list(collection.find(query).sort("patch_date", 1))
# 3) ensure every patch_date is *string* before serialising
# 4) Patchnotes abholen
docs = list(collection.find(mongo_filter).sort("patch_date", 1))
for d in docs:
if isinstance(d.get("patch_date"), (datetime, date)):
d["patch_date"] = d["patch_date"].strftime("%Y-%m-%d")
d.pop("_id", None) # optional: hide Mongos internal id
d.pop("_id", None)
if isinstance(d["patch_date"], (datetime, date)):
d["patch_date"] = d["patch_date"].isoformat()
# 4) serialise default=str handles any remaining non-JSON types
return Response(
json_util.dumps(docs, default=str),
mimetype="application/json",
status=200,
# 5) Heutiges Datum als neuen last_login speichern
today = date.today().isoformat()
last_login_collection.update_one(
{"user_id": user_id},
{"$set": {"last_login": today}},
upsert=True,
)
return Response(json_util.dumps(docs), mimetype="application/json", status=200)
def update_patchnote(patch_id, body): # noqa: E501
"""Updates one patch note (full replace)
@ -206,3 +217,5 @@ def update_patchnote(patch_id, body): # noqa: E501
mimetype="application/json",
status=200,
)

View File

@ -0,0 +1,15 @@
import jwt
from connexion import ProblemException
from flask import request
def current_user_id() -> str:
"""Liest die User-UUID (sub) aus dem Bearer-JWT im Authorization-Header."""
auth = request.headers.get("Authorization", "")
if not auth.startswith("Bearer "):
raise ProblemException(status=401, detail="Missing Bearer token")
token = auth.split()[1]
# ↓ Für Demo ohne Signaturprüfung produktiv natürlich verifizieren!
payload = jwt.decode(token, options={"verify_signature": False})
return payload["sub"]

View File

@ -15,3 +15,6 @@ flask_cors >= 5.0.1
typing_extensions==4.12.2
Flask-Testing==0.8.1
starlette==0.46.1
typing_extensions==4.12.2
PyJWT==2.10.1