worikng base version

This commit is contained in:
2025-07-16 21:19:02 +05:00
parent c6d78e3648
commit 3d310760ba
2 changed files with 106 additions and 17 deletions

View File

@ -1,3 +1,5 @@
import base64
import json
from fastapi import HTTPException from fastapi import HTTPException
from .models import UserLogin, UserInDB, Session, UserCreate from .models import UserLogin, UserInDB, Session, UserCreate
from .utils import ( from .utils import (
@ -61,10 +63,12 @@ class AuthService:
} }
async def validate(self, access_token: str, client_token: str): async def validate(self, access_token: str, client_token: str):
print(f"Searching for access_toke and client_token: '{access_token}', '{client_token}")
session = await sessions_collection.find_one({ session = await sessions_collection.find_one({
"access_token": access_token, "access_token": access_token,
"client_token": client_token, "client_token": client_token,
}) })
print("Session from DB:", session)
if not session or datetime.utcnow() > session["expires_at"]: if not session or datetime.utcnow() > session["expires_at"]:
return False return False
return True return True
@ -80,3 +84,83 @@ class AuthService:
{"$set": {"access_token": new_access_token}}, {"$set": {"access_token": new_access_token}},
) )
return {"accessToken": new_access_token, "clientToken": client_token} return {"accessToken": new_access_token, "clientToken": client_token}
async def get_minecraft_profile(self, uuid: str):
formatted_uuid = f"{uuid[:8]}-{uuid[8:12]}-{uuid[12:16]}-{uuid[16:20]}-{uuid[20:]}"
user = await users_collection.find_one({"uuid": formatted_uuid})
if not user:
raise HTTPException(
status_code=404,
detail=f"User not found (searched for UUID: {formatted_uuid})"
)
textures = {
"timestamp": int(datetime.now().timestamp()),
"profileId": formatted_uuid,
"profileName": user["username"],
"textures": {
"SKIN": {"url": user.get("skin_url", "")},
"CAPE": {"url": user.get("cloak_url", "")}
} if user.get("skin_url") or user.get("cloak_url") else {}
}
textures_json = json.dumps(textures).encode()
base64_textures = base64.b64encode(textures_json).decode()
return {
"id": formatted_uuid,
"name": user["username"],
"properties": [
{
"name": "textures",
"value": base64_textures
}
]
}
async def join_server(self, request_data: dict):
access_token = request_data.get("accessToken")
selected_profile = request_data.get("selectedProfile")
server_id = request_data.get("serverId")
if not all([access_token, selected_profile, server_id]):
raise HTTPException(status_code=400, detail="Missing required parameters")
decoded_token = decode_token(access_token)
if not decoded_token:
raise HTTPException(status_code=401, detail="Invalid access token")
token_uuid = decoded_token.get("uuid", "").replace("-", "")
if token_uuid != selected_profile:
raise HTTPException(status_code=403, detail="Token doesn't match selected profile")
return True
async def has_joined(self, username: str, server_id: str):
user = await users_collection.find_one({"username": username})
if not user:
raise HTTPException(status_code=404, detail="User not found")
response_uuid = user["uuid"].replace("-", "")
textures = {}
if user.get("skin_url"):
textures["SKIN"] = {"url": user["skin_url"]}
if user.get("cloak_url"):
textures["CAPE"] = {"url": user["cloak_url"]}
textures_value = base64.b64encode(json.dumps({
"timestamp": int(datetime.now().timestamp()),
"profileId": response_uuid,
"profileName": username,
"textures": textures
}).encode()).decode()
return {
"id": response_uuid,
"name": username,
"properties": [{
"name": "textures",
"value": textures_value
}] if textures else []
}

View File

@ -1,11 +1,17 @@
from fastapi import FastAPI, Depends, HTTPException, Body import base64
from datetime import datetime
import json
from fastapi import FastAPI, Depends, HTTPException, Body, Request, Response
from fastapi.security import OAuth2PasswordBearer from fastapi.security import OAuth2PasswordBearer
from .models import UserCreate, UserLogin, ValidateRequest from .models import UserCreate, UserLogin, ValidateRequest
from .auth import AuthService from .auth import AuthService
from .database import users_collection from .database import users_collection
from .utils import decode_token
import os import os
from typing import Union from typing import Union
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
import logging
# logging.basicConfig(level=logging.DEBUG)
app = FastAPI() app = FastAPI()
auth_service = AuthService() auth_service = AuthService()
@ -51,23 +57,22 @@ async def refresh_token(access_token: str, client_token: str):
raise HTTPException(status_code=401, detail="Invalid tokens") raise HTTPException(status_code=401, detail="Invalid tokens")
return result return result
# Эндпоинт для проверки скинов (Minecraft использует его) @app.get("/sessionserver/session/minecraft/profile/{uuid}")
@app.get("/session/hasJoined") async def get_minecraft_profile(uuid: str, unsigned: bool = False):
async def has_joined(username: str, serverId: str): return await auth_service.get_minecraft_profile(uuid)
user = await users_collection.find_one({"username": username})
if not user:
raise HTTPException(status_code=404, detail="User not found")
return { @app.post("/sessionserver/session/minecraft/join")
"id": user["uuid"], async def join_server(request_data: dict = Body(...)):
"name": username, try:
"properties": [ await auth_service.join_server(request_data)
{ return Response(status_code=204)
"name": "textures", except Exception as e:
"value": "base64_encoded_skin_data", # Здесь можно добавить скины print("Error in join_server:", str(e))
} raise
],
} @app.get("/sessionserver/session/minecraft/hasJoined")
async def has_joined(username: str, serverId: str):
return await auth_service.has_joined(username, serverId)
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn