Update routes.py

This commit is contained in:
dev 2026-10-08 09:38:19 +00:00
parent 4fac502e7c
commit b33f8527ac

159
routes.py
View File

@ -4603,8 +4603,8 @@ def register_routes(app, ctx):
payload["versions"] = [] payload["versions"] = []
return jsonify({"page": payload, "shared": True}) return jsonify({"page": payload, "shared": True})
@app.route("/api/profile") @app.route("/api/profile")
def api_get_my_profile(): def api_get_my_profile():
user, error = require_user() user, error = require_user()
if error: if error:
return error return error
@ -4618,12 +4618,14 @@ def register_routes(app, ctx):
role, role,
status, status,
restricted_until, restricted_until,
created_at created_at,
last_login_at
FROM users FROM users
WHERE id = ? WHERE id = ?
""", """,
(user["id"],), (user["id"],),
).fetchone() ).fetchone()
profile_row = db.execute( profile_row = db.execute(
""" """
SELECT SELECT
@ -4634,39 +4636,59 @@ def register_routes(app, ctx):
bio_mode, bio_mode,
website, website,
location, location,
status_message,
banner_attachment_id,
updated_at updated_at
FROM user_profiles FROM user_profiles
WHERE user_id = ? WHERE user_id = ?
""", """,
(user["id"],), (user["id"],),
).fetchone() ).fetchone()
settings_row = db.execute( settings_row = db.execute(
""" """
SELECT SELECT
name_color name_color,
profile_background_color,
profile_banner_color,
profile_visibility,
last_active_visibility,
presence_mode
FROM user_settings FROM user_settings
WHERE user_id = ? WHERE user_id = ?
""", """,
(user["id"],), (user["id"],),
).fetchone() ).fetchone()
return jsonify({"profile": profile_payload(html_module, user_payload, user_row, profile_row, settings_row, user)}) return jsonify({
"profile": profile_payload(
html_module,
user_payload,
user_row,
profile_row,
settings_row,
user,
)
})
@app.route("/api/profile", methods=["PATCH"])
def api_update_my_profile(): @app.route("/api/profile", methods=["PATCH"])
def api_update_my_profile():
if not csrf_valid(): if not csrf_valid():
return jsonify({"error": "Security token expired.", "code": "csrf"}), 403 return jsonify({"error": "Security token expired.", "code": "csrf"}), 403
limited = rate_limited("profile") limited = rate_limited("profile")
if limited: if limited:
return limited return limited
user, error = require_writable_user() user, error = require_writable_user()
if error: if error:
return error return error
try: try:
data = safe_json() data = safe_json()
except ValueError as error: except ValueError as exc:
return jsonify({"error": str(error)}), 400 return jsonify({"error": str(exc)}), 400
display_name = str(data.get("display_name", "")).strip() display_name = str(data.get("display_name", "")).strip()
badge_text = str(data.get("badge_text", "")).strip() badge_text = str(data.get("badge_text", "")).strip()
@ -4674,6 +4696,8 @@ def register_routes(app, ctx):
bio_mode = str(data.get("bio_mode", "txt")).strip().lower() bio_mode = str(data.get("bio_mode", "txt")).strip().lower()
website = str(data.get("website", "")).strip() website = str(data.get("website", "")).strip()
location = str(data.get("location", "")).strip() location = str(data.get("location", "")).strip()
status_message = str(data.get("status_message", "")).strip()
banner_attachment_id = data.get("banner_attachment_id")
if len(display_name) > MAX_DISPLAY_NAME_LENGTH: if len(display_name) > MAX_DISPLAY_NAME_LENGTH:
return jsonify({"error": "Display name is too long."}), 400 return jsonify({"error": "Display name is too long."}), 400
@ -4687,6 +4711,33 @@ def register_routes(app, ctx):
return jsonify({"error": "Website is too long."}), 400 return jsonify({"error": "Website is too long."}), 400
if len(location) > MAX_LOCATION_LENGTH: if len(location) > MAX_LOCATION_LENGTH:
return jsonify({"error": "Location is too long."}), 400 return jsonify({"error": "Location is too long."}), 400
if len(status_message) > constants["MAX_STATUS_MESSAGE_LENGTH"]:
return jsonify({"error": "Status message is too long."}), 400
if banner_attachment_id in ("", None):
banner_attachment_id = None
else:
try:
banner_attachment_id = int(banner_attachment_id)
except (TypeError, ValueError):
return jsonify({"error": "Invalid banner attachment."}), 400
with get_db() as db:
attachment = db.execute(
"""
SELECT
id,
uploader_user_id
FROM attachments
WHERE id = ?
""",
(banner_attachment_id,),
).fetchone()
if not attachment:
return jsonify({"error": "Banner attachment not found."}), 404
if int(attachment["uploader_user_id"]) != int(user["id"]):
return jsonify({"error": "You can only use your own uploaded image as banner."}), 403
db_write( db_write(
""" """
@ -4698,6 +4749,8 @@ def register_routes(app, ctx):
bio_mode = ?, bio_mode = ?,
website = ?, website = ?,
location = ?, location = ?,
status_message = ?,
banner_attachment_id = ?,
updated_at = ? updated_at = ?
WHERE user_id = ? WHERE user_id = ?
""", """,
@ -4708,6 +4761,8 @@ def register_routes(app, ctx):
bio_mode, bio_mode,
website, website,
location, location,
status_message,
banner_attachment_id,
now_iso(), now_iso(),
user["id"], user["id"],
), ),
@ -4722,12 +4777,14 @@ def register_routes(app, ctx):
role, role,
status, status,
restricted_until, restricted_until,
created_at created_at,
last_login_at
FROM users FROM users
WHERE id = ? WHERE id = ?
""", """,
(user["id"],), (user["id"],),
).fetchone() ).fetchone()
profile_row = db.execute( profile_row = db.execute(
""" """
SELECT SELECT
@ -4738,23 +4795,49 @@ def register_routes(app, ctx):
bio_mode, bio_mode,
website, website,
location, location,
status_message,
banner_attachment_id,
updated_at updated_at
FROM user_profiles FROM user_profiles
WHERE user_id = ? WHERE user_id = ?
""", """,
(user["id"],), (user["id"],),
).fetchone() ).fetchone()
settings_row = db.execute( settings_row = db.execute(
"SELECT name_color FROM user_settings WHERE user_id = ?", """
SELECT
name_color,
profile_background_color,
profile_banner_color,
profile_visibility,
last_active_visibility,
presence_mode
FROM user_settings
WHERE user_id = ?
""",
(user["id"],), (user["id"],),
).fetchone() ).fetchone()
audit("profile_updated", user["id"], "user", str(user["id"])) audit("profile_updated", user["id"], "user", str(user["id"]))
return jsonify({"profile": profile_payload(html_module, user_payload, user_row, profile_row, settings_row, user)})
@app.route("/api/profiles/<string:username>") return jsonify({
def api_get_public_profile(username: str): "profile": profile_payload(
html_module,
user_payload,
user_row,
profile_row,
settings_row,
user,
)
})
@app.route("/api/profiles/<string:username>")
def api_get_public_profile(username: str):
normalized = normalize_username(username) normalized = normalize_username(username)
viewer = current_user()
with get_db() as db: with get_db() as db:
user_row = db.execute( user_row = db.execute(
""" """
@ -4764,14 +4847,17 @@ def register_routes(app, ctx):
role, role,
status, status,
restricted_until, restricted_until,
created_at created_at,
last_login_at
FROM users FROM users
WHERE username = ? WHERE username = ?
""", """,
(normalized,), (normalized,),
).fetchone() ).fetchone()
if not user_row: if not user_row:
return jsonify({"error": "Profile not found."}), 404 return jsonify({"error": "Profile not found."}), 404
profile_row = db.execute( profile_row = db.execute(
""" """
SELECT SELECT
@ -4782,17 +4868,56 @@ def register_routes(app, ctx):
bio_mode, bio_mode,
website, website,
location, location,
status_message,
banner_attachment_id,
updated_at updated_at
FROM user_profiles FROM user_profiles
WHERE user_id = ? WHERE user_id = ?
""", """,
(user_row["id"],), (user_row["id"],),
).fetchone() ).fetchone()
settings_row = db.execute( settings_row = db.execute(
"SELECT name_color FROM user_settings WHERE user_id = ?", """
SELECT
name_color,
profile_background_color,
profile_banner_color,
profile_visibility,
last_active_visibility,
presence_mode
FROM user_settings
WHERE user_id = ?
""",
(user_row["id"],), (user_row["id"],),
).fetchone() ).fetchone()
return jsonify({"profile": profile_payload(html_module, user_payload, user_row, profile_row, settings_row, current_user())})
profile_visibility = (
settings_row["profile_visibility"]
if settings_row and "profile_visibility" in settings_row.keys()
else "public"
)
is_self = bool(viewer and int(viewer["id"]) == int(user_row["id"]))
if profile_visibility == "private":
if not is_self and not (viewer and viewer["role"] in {"moderator", "admin"}):
return jsonify({"error": "Profile not available."}), 403
if profile_visibility == "members":
if not is_self and not viewer:
return jsonify({"error": "Profile not available."}), 403
return jsonify({
"profile": profile_payload(
html_module,
user_payload,
user_row,
profile_row,
settings_row,
viewer,
)
})
@app.route("/api/settings") @app.route("/api/settings")
def api_get_settings(): def api_get_settings():