remake apis 0.151
This commit is contained in:
@@ -9,6 +9,10 @@ https://ru.homyk.space {
|
||||
}
|
||||
|
||||
handle_path /main/* {
|
||||
forward_auth backend:{$PORT} {
|
||||
uri /api/verify
|
||||
copy_headers Authorization
|
||||
}
|
||||
root * /srv/main
|
||||
file_server
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
from fastapi import FastAPI, Depends, HTTPException,status
|
||||
from fastapi import FastAPI, Depends, HTTPException,status, Response, Cookie
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
import server.backend.schema.pydantic as pydantic
|
||||
import server.backend.database.db as db
|
||||
from server.backend.auth.JWT import signJWT, decodeJWT
|
||||
api = FastAPI(openapi_url="/api/openapi.json",docs_url="/api/docs", redoc_url="/api/redoc")
|
||||
security = HTTPBearer()
|
||||
security = HTTPBearer(auto_error=False)
|
||||
|
||||
async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)):
|
||||
token = credentials.credentials
|
||||
async def get_current_user(
|
||||
credentials: HTTPAuthorizationCredentials = Depends(security),
|
||||
token_cookie: str = Cookie(default=None)
|
||||
):
|
||||
token = credentials.credentials if credentials else token_cookie
|
||||
if not token:
|
||||
raise HTTPException(status_code=401, detail="Not authenticated")
|
||||
user = decodeJWT(token)
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
|
||||
raise HTTPException(status_code=401, detail="Invalid token")
|
||||
return user
|
||||
async def check_roles(user=Depends(get_current_user)):
|
||||
user_check = await db.list_user(user["user_id"])
|
||||
@@ -58,10 +63,29 @@ async def list_users(user=Depends(check_roles)):
|
||||
list_of_users = await db.list_users()
|
||||
return list_of_users
|
||||
|
||||
@api.post("/api/auth",response_model=pydantic.Token)
|
||||
async def auth(code:pydantic.UserAccess):
|
||||
@api.post("/api/auth")
|
||||
async def auth(code: pydantic.UserAccess, response: Response):
|
||||
login = await db.login_user(code)
|
||||
if login == None:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Forbidden")
|
||||
if login is None:
|
||||
raise HTTPException(status_code=401, detail="Forbidden")
|
||||
token = signJWT(login)
|
||||
response.set_cookie(
|
||||
key="token",
|
||||
value=token,
|
||||
httponly=True,
|
||||
secure=True,
|
||||
samesite="strict"
|
||||
)
|
||||
return {"access_token": token, "token_type": "bearer"}
|
||||
@api.get("/api/verify")
|
||||
async def verify(token: str = Cookie(default=None)):
|
||||
if not token:
|
||||
raise HTTPException(status_code=401, detail="No token")
|
||||
user = decodeJWT(token)
|
||||
if not user:
|
||||
raise HTTPException(status_code=401, detail="Invalid token")
|
||||
return {"status": "ok"}
|
||||
@api.post("/api/logout")
|
||||
async def logout(response: Response):
|
||||
response.delete_cookie(key="token")
|
||||
return {"status": "ok"}
|
||||
@@ -1,73 +1,64 @@
|
||||
function getToken() {
|
||||
return localStorage.getItem("token") || sessionStorage.getItem("token");
|
||||
}
|
||||
function tokenCheck(){
|
||||
const token = getToken();
|
||||
if (token) {
|
||||
window.location.href = "https://ru.homyk.space/main/";
|
||||
}
|
||||
}
|
||||
document.getElementById('loginForm').addEventListener('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
const password = document.getElementById('password').value;
|
||||
const userData = {
|
||||
password
|
||||
};
|
||||
try {
|
||||
const response = await fetch("https://ru.homyk.space/api/auth", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
code: userData.password
|
||||
}),
|
||||
});
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fetch('/api/verify', { credentials: 'include' })
|
||||
.then(r => { if (r.ok) window.location.href = '/main/'; })
|
||||
.catch(() => {});
|
||||
|
||||
const data = await response.json(); // читаем только один раз
|
||||
if (response.ok) { // сохраняем только при успехе
|
||||
// в sessionstorage до перезахода в браузер(
|
||||
sessionStorage.setItem("token", data.access_token);
|
||||
|
||||
window.location.href = 'https://ru.homyk.space/main/';
|
||||
} else { //парсинг и вывод ошибок, если есть
|
||||
if (Array.isArray(data.detail)) {
|
||||
const messages = data.detail.map(e => {
|
||||
const field = e.loc.filter(locPart => locPart !== 'body').join(' -> ');
|
||||
return `${field}: ${e.msg}`;
|
||||
});
|
||||
showError(messages);
|
||||
} else if (typeof data.detail === 'string') {
|
||||
showError([data.detail]);
|
||||
document.getElementById('loginForm').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const code = document.getElementById('password').value;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/auth', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include', // ← чтобы браузер принял cookie
|
||||
body: JSON.stringify({ code })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
window.location.href = '/main/';
|
||||
} else {
|
||||
showError(['Unknown error']);
|
||||
if (Array.isArray(data.detail)) {
|
||||
const messages = data.detail.map(e => {
|
||||
const field = e.loc.filter(p => p !== 'body').join(' -> ');
|
||||
return `${field}: ${e.msg}`;
|
||||
});
|
||||
showError(messages);
|
||||
} else if (typeof data.detail === 'string') {
|
||||
showError([data.detail]);
|
||||
} else {
|
||||
showError(['Unknown error']);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
showError(['Connection error: ' + err.message]);
|
||||
}
|
||||
} catch (err) {
|
||||
showError(['Connection error: ' + err.message]);
|
||||
}
|
||||
});
|
||||
});
|
||||
function showError(messages){ //Добавление их на form со стилями
|
||||
|
||||
function showError(messages) {
|
||||
let errorElem = document.getElementById('formError');
|
||||
let container = document.getElementById('glass-container');
|
||||
if (!errorElem){
|
||||
if (!errorElem) {
|
||||
errorElem = document.createElement('div');
|
||||
errorElem.style.transition="3s";
|
||||
errorElem.id = 'formError';
|
||||
errorElem.style.color = 'red';
|
||||
errorElem.style.marginTop = '20px';
|
||||
errorElem.style.fontSize = '14px';
|
||||
errorElem.style.fontWeight = '100';
|
||||
errorElem.style.marginBottom = '20px';
|
||||
errorElem.style.lineHeight="120%";
|
||||
errorElem.style.height = 'auto';
|
||||
const form = document.getElementById('loginForm');
|
||||
form.insertAdjacentElement('afterend', errorElem);
|
||||
};
|
||||
errorElem.style.cssText = `
|
||||
color: red;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 100;
|
||||
line-height: 120%;
|
||||
transition: 3s;
|
||||
`;
|
||||
document.getElementById('loginForm').insertAdjacentElement('afterend', errorElem);
|
||||
}
|
||||
errorElem.innerHTML = '';
|
||||
messages.forEach(msg => {
|
||||
const li = document.createElement('li');
|
||||
li.style.listStyleType="none";
|
||||
li.style.listStyleType = 'none';
|
||||
li.textContent = msg;
|
||||
errorElem.appendChild(li);
|
||||
});
|
||||
|
||||
@@ -1,29 +1,23 @@
|
||||
function getToken() {
|
||||
return localStorage.getItem("token") || sessionStorage.getItem("token");
|
||||
}
|
||||
|
||||
function tokenCheck() {
|
||||
const token = getToken();
|
||||
if (!token) {
|
||||
window.location.href = "https://ru.homyk.space";
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
tokenCheck();
|
||||
|
||||
document.getElementById('logoutForm').addEventListener('submit', function(e) {
|
||||
// Проверка авторизации через cookie
|
||||
fetch('/api/verify', { credentials: 'include' })
|
||||
.then(r => { if (!r.ok) window.location.href = '/'; })
|
||||
.catch(() => { window.location.href = '/'; });
|
||||
|
||||
// Logout — удаляем cookie на бэкенде
|
||||
document.getElementById('logoutForm').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
localStorage.removeItem("token");
|
||||
sessionStorage.removeItem("token");
|
||||
tokenCheck();
|
||||
await fetch('/api/logout', {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
});
|
||||
window.location.href = '/';
|
||||
});
|
||||
|
||||
document.querySelector(".form-info").addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const token = getToken();
|
||||
|
||||
const guestData = {
|
||||
name: document.getElementById('ffname').value || "",
|
||||
middlename: document.getElementById('fmname').value || "",
|
||||
@@ -36,15 +30,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
.join(', ')
|
||||
};
|
||||
|
||||
console.log(guestData);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/update', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`
|
||||
},
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include', // ← токен идёт через cookie
|
||||
body: JSON.stringify(guestData)
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user