99 lines
4.4 KiB
Python
99 lines
4.4 KiB
Python
|
|
import os
|
|
import urllib.parse
|
|
import requests
|
|
from nicegui import ui, app
|
|
from data import data_api
|
|
|
|
def get_auth_url():
|
|
client_id = os.getenv("DISCORD_CLIENT_ID")
|
|
app_url = os.getenv("APP_URL")
|
|
redirect_uri = f"{app_url}/login/discord"
|
|
encoded_redirect_uri = urllib.parse.quote(redirect_uri, safe="")
|
|
|
|
# NEU: guilds.members.read erlaubt uns, die Rollen des Users in einem bestimmten Server abzufragen
|
|
return f"https://discord.com/api/oauth2/authorize?client_id={client_id}&redirect_uri={encoded_redirect_uri}&response_type=code&scope=identify%20guilds.members.read"
|
|
|
|
|
|
def setup_login_routes():
|
|
client_id = os.getenv("DISCORD_CLIENT_ID")
|
|
client_secret = os.getenv("DISCORD_CLIENT_SECRET")
|
|
app_url = os.getenv("APP_URL")
|
|
redirect_uri = f"{app_url}/login/discord"
|
|
|
|
@ui.page('/login/discord', dark=True)
|
|
def discord_callback(code: str = None):
|
|
if not code:
|
|
ui.label('Fehler: Kein Code erhalten.').classes('text-red-500')
|
|
return
|
|
|
|
token_data = {
|
|
'client_id': client_id,
|
|
'client_secret': client_secret,
|
|
'grant_type': 'authorization_code',
|
|
'code': code,
|
|
'redirect_uri': redirect_uri
|
|
}
|
|
|
|
token_response = requests.post('https://discord.com/api/oauth2/token', data=token_data)
|
|
token_json = token_response.json()
|
|
|
|
if 'access_token' in token_json:
|
|
access_token = token_json['access_token']
|
|
user_headers = {'Authorization': f"Bearer {access_token}"}
|
|
|
|
# 1. Die IDs aus der .env laden (Passe die Namen an, falls sie bei dir anders heißen!)
|
|
guild_id = os.getenv("DISCORD_SERVER_ID")
|
|
role_diceghosts = os.getenv("DISCORD_SERVER_DICEGHOST_ID")
|
|
role_friend = os.getenv("DISCORD_SERVER_FRIEND_ID")
|
|
|
|
# 2. Prüfen: Ist der Nutzer überhaupt auf unserem Server?
|
|
# Wir fragen Discord gezielt nach dem Profil des Nutzers auf DEINEM Server.
|
|
member_response = requests.get(f'https://discord.com/api/users/@me/guilds/{guild_id}/member', headers=user_headers)
|
|
|
|
# Ein HTTP Status-Code 200 bedeutet "OK". Alles andere (z.B. 404 Not Found) bedeutet: Er ist nicht auf dem Server!
|
|
if member_response.status_code != 200:
|
|
ui.label('Zugriff verweigert: Du bist nicht auf dem Diceghosts Server!').classes('text-red-500 text-xl font-bold p-4')
|
|
return # Bricht die Funktion hier ab. Kein Login!
|
|
|
|
# 3. Prüfen: Hat er die richtige Rolle?
|
|
member_json = member_response.json()
|
|
# Liste aller Rollen des Nutzers. Wenn er keine hat, nehmen wir eine leere Liste []
|
|
user_roles = member_json.get('roles', [])
|
|
|
|
# Wir prüfen, ob mindestens eine der beiden Rollen-IDs in seiner Liste auftaucht
|
|
if role_diceghosts not in user_roles and role_friend not in user_roles:
|
|
ui.label('Zugriff verweigert: Du hast nicht die benötigte Rolle (Diceghosts oder Friend)!').classes('text-red-500 text-xl font-bold p-4')
|
|
return # Bricht die Funktion hier ab. Kein Login!
|
|
|
|
# --- AB HIER: ZUGANG GEWÄHRT! ---
|
|
|
|
# Jetzt laden wir noch seine allgemeinen Discord-Daten (für Name und Profilbild)
|
|
user_response = requests.get('https://discord.com/api/users/@me', headers=user_headers)
|
|
user_json = user_response.json()
|
|
|
|
discord_id = user_json['id']
|
|
discord_name = user_json['username']
|
|
|
|
# --- BILD ABFANGEN ---
|
|
avatar_hash = user_json.get('avatar')
|
|
if avatar_hash:
|
|
avatar_url = f"https://cdn.discordapp.com/avatars/{discord_id}/{avatar_hash}.png"
|
|
else:
|
|
avatar_url = "https://cdn.discordapp.com/embed/avatars/0.png"
|
|
|
|
# In die Datenbank eintragen
|
|
player = data_api.get_or_create_player(discord_id, discord_name, avatar_url)
|
|
|
|
# Session updaten
|
|
app.storage.user['authenticated'] = True
|
|
app.storage.user['discord_id'] = discord_id
|
|
app.storage.user['discord_name'] = discord_name
|
|
app.storage.user['db_id'] = player[0]
|
|
app.storage.user['display_name'] = player[2]
|
|
app.storage.user['discord_avatar_url'] = player[3]
|
|
|
|
ui.navigate.to('/')
|
|
else:
|
|
ui.label('Fehler beim Login!').classes('text-red-500')
|