Implement RBAC in api-gw
This commit is contained in:
parent
7aa05f51ff
commit
51f0c7b168
|
@ -9,6 +9,7 @@ from src.api.models.users import User
|
||||||
auth_namespace = Namespace("auth")
|
auth_namespace = Namespace("auth")
|
||||||
|
|
||||||
auth_user_model = User.get_api_auth_user_model(auth_namespace)
|
auth_user_model = User.get_api_auth_user_model(auth_namespace)
|
||||||
|
auth_small_model = User.get_api_auth_small_model(auth_namespace)
|
||||||
auth_full_user_model = User.get_api_auth_full_user_model(auth_namespace)
|
auth_full_user_model = User.get_api_auth_full_user_model(auth_namespace)
|
||||||
auth_login_model = User.get_api_auth_login_model(auth_namespace)
|
auth_login_model = User.get_api_auth_login_model(auth_namespace)
|
||||||
auth_refresh_model = User.get_api_auth_refresh_model(auth_namespace)
|
auth_refresh_model = User.get_api_auth_refresh_model(auth_namespace)
|
||||||
|
@ -97,7 +98,7 @@ class Refresh(Resource):
|
||||||
|
|
||||||
|
|
||||||
class Status(Resource):
|
class Status(Resource):
|
||||||
@auth_namespace.marshal_with(auth_user_model)
|
@auth_namespace.marshal_with(auth_small_model)
|
||||||
@auth_namespace.response(200, "Success")
|
@auth_namespace.response(200, "Success")
|
||||||
@auth_namespace.response(401, "Invalid token")
|
@auth_namespace.response(401, "Invalid token")
|
||||||
@auth_namespace.expect(parser)
|
@auth_namespace.expect(parser)
|
||||||
|
|
|
@ -85,6 +85,16 @@ class User(db.Model):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_api_auth_small_model(cls, namespace):
|
||||||
|
return namespace.model(
|
||||||
|
"User",
|
||||||
|
{
|
||||||
|
"id": fields.Integer(required=True),
|
||||||
|
"airline": fields.Boolean(readOnly=True),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_api_auth_full_user_model(cls, namespace):
|
def get_api_auth_full_user_model(cls, namespace):
|
||||||
return namespace.clone(
|
return namespace.clone(
|
||||||
|
|
|
@ -31,12 +31,10 @@ export const createUser = (
|
||||||
return instance.post("users", credentials);
|
return instance.post("users", credentials);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchUsers = (): Promise<User[]> => {
|
export const fetchUserById = (id: number, token: string): Promise<User & { message?: string }> => {
|
||||||
return instance.get("users");
|
return instance.get("users/" + id, {
|
||||||
};
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
export const fetchUserById = (id: number): Promise<User> => {
|
|
||||||
return instance.get("users/" + id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const logIn = (
|
export const logIn = (
|
||||||
|
|
|
@ -48,7 +48,7 @@ export function AuthProvider({
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenStatus(existingToken)
|
tokenStatus(existingToken)
|
||||||
.then((res) => fetchUserById(res.id)
|
.then((res) => fetchUserById(res.id, existingToken)
|
||||||
.then((res) => setUser(res))
|
.then((res) => setUser(res))
|
||||||
.catch((_error) => { })
|
.catch((_error) => { })
|
||||||
.finally(() => setLoadingInitial(false))
|
.finally(() => setLoadingInitial(false))
|
||||||
|
@ -70,7 +70,7 @@ export function AuthProvider({
|
||||||
localStorage.setItem("token", x.access_token);
|
localStorage.setItem("token", x.access_token);
|
||||||
const airline = (jwt_decode(x.access_token) as TokenData).airline;
|
const airline = (jwt_decode(x.access_token) as TokenData).airline;
|
||||||
setIsAirline(airline)
|
setIsAirline(airline)
|
||||||
const user = fetchUserById(x.user_id as number)
|
const user = fetchUserById(x.user_id as number, x.access_token)
|
||||||
.then(y => {
|
.then(y => {
|
||||||
setUser(y);
|
setUser(y);
|
||||||
navigate("/home")
|
navigate("/home")
|
||||||
|
|
|
@ -5,7 +5,7 @@ from fastapi import APIRouter, Header, HTTPException, Request
|
||||||
|
|
||||||
from src.api.config import API_AUTH
|
from src.api.config import API_AUTH
|
||||||
from src.api.schemas.auth import RefreshToken, Token
|
from src.api.schemas.auth import RefreshToken, Token
|
||||||
from src.api.schemas.user import UserLogin, UserMin, UserRegister
|
from src.api.schemas.user import UserLogin, UserMin, UserRegister, UserStatus
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ async def refresh(token: RefreshToken, req: Request):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/status", response_model=UserMin)
|
@router.get("/status", response_model=UserStatus)
|
||||||
async def status(req: Request, authorization: Annotated[str | None, Header()] = None):
|
async def status(req: Request, authorization: Annotated[str | None, Header()] = None):
|
||||||
request_id = req.state.request_id
|
request_id = req.state.request_id
|
||||||
header = {
|
header = {
|
||||||
|
@ -57,3 +57,27 @@ async def status(req: Request, authorization: Annotated[str | None, Header()] =
|
||||||
if status < 200 or status > 204:
|
if status < 200 or status > 204:
|
||||||
raise HTTPException(status_code=status, detail=response)
|
raise HTTPException(status_code=status, detail=response)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
async def checkAuth(
|
||||||
|
req: Request,
|
||||||
|
authorization: Annotated[str | None, Header()] = None,
|
||||||
|
isAirline=False,
|
||||||
|
userId=None,
|
||||||
|
):
|
||||||
|
response = await status(req, authorization)
|
||||||
|
if isAirline:
|
||||||
|
if response["airline"]:
|
||||||
|
return response["id"]
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=403, detail="You don't have the required permissions."
|
||||||
|
)
|
||||||
|
elif userId:
|
||||||
|
if response["id"] != int(userId):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=403, detail="You don't have the required permissions."
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return response["id"]
|
||||||
|
|
|
@ -4,7 +4,7 @@ from asyncreq import request
|
||||||
from fastapi import APIRouter, Header, HTTPException, Request
|
from fastapi import APIRouter, Header, HTTPException, Request
|
||||||
|
|
||||||
from src.api.config import API_FLIGHTS
|
from src.api.config import API_FLIGHTS
|
||||||
from src.api.routes.auth import status as checkAuth
|
from src.api.routes.auth import checkAuth
|
||||||
from src.api.schemas.flight import Flight, FlightCreate, FlightUpdate
|
from src.api.schemas.flight import Flight, FlightCreate, FlightUpdate
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
@ -29,7 +29,7 @@ async def create_flight(
|
||||||
req: Request,
|
req: Request,
|
||||||
authorization: Annotated[str | None, Header()] = None,
|
authorization: Annotated[str | None, Header()] = None,
|
||||||
):
|
):
|
||||||
auth = await checkAuth(req, authorization)
|
auth = await checkAuth(req, authorization, isAirline=True)
|
||||||
flight_data = flight.model_dump()
|
flight_data = flight.model_dump()
|
||||||
flight_data["user_id"] = auth["id"]
|
flight_data["user_id"] = auth["id"]
|
||||||
request_id = req.state.request_id
|
request_id = req.state.request_id
|
||||||
|
@ -49,7 +49,7 @@ async def update_flight(
|
||||||
req: Request,
|
req: Request,
|
||||||
authorization: Annotated[str | None, Header()] = None,
|
authorization: Annotated[str | None, Header()] = None,
|
||||||
):
|
):
|
||||||
auth = await checkAuth(req, authorization)
|
auth = await checkAuth(req, authorization, isAirline=True)
|
||||||
update = flight_update.model_dump()
|
update = flight_update.model_dump()
|
||||||
update["user_id"] = auth["id"]
|
update["user_id"] = auth["id"]
|
||||||
request_id = req.state.request_id
|
request_id = req.state.request_id
|
||||||
|
|
|
@ -1,22 +1,15 @@
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
from asyncreq import request
|
from asyncreq import request
|
||||||
from fastapi import APIRouter, HTTPException, Request
|
from fastapi import APIRouter, Header, HTTPException, Request
|
||||||
|
|
||||||
from src.api.config import API_USERS
|
from src.api.config import API_USERS
|
||||||
|
from src.api.routes.auth import checkAuth
|
||||||
from src.api.schemas.user import User, UserRegister
|
from src.api.schemas.user import User, UserRegister
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.get("", response_model=list[User])
|
|
||||||
async def get_users(req: Request):
|
|
||||||
request_id = req.state.request_id
|
|
||||||
header = {"x-api-request-id": request_id}
|
|
||||||
(response, status, _) = await request(f"{API_USERS}", "GET", headers=header)
|
|
||||||
if status < 200 or status > 204:
|
|
||||||
raise HTTPException(status_code=status, detail=response)
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("", response_model=User)
|
@router.post("", response_model=User)
|
||||||
async def create_users(user: UserRegister, req: Request):
|
async def create_users(user: UserRegister, req: Request):
|
||||||
request_id = req.state.request_id
|
request_id = req.state.request_id
|
||||||
|
@ -30,7 +23,10 @@ async def create_users(user: UserRegister, req: Request):
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{id}", response_model=User)
|
@router.get("/{id}", response_model=User)
|
||||||
async def get_user(id: str, req: Request):
|
async def get_user(
|
||||||
|
id: str, req: Request, authorization: Annotated[str | None, Header()] = None
|
||||||
|
):
|
||||||
|
await checkAuth(req, authorization, userId=id)
|
||||||
request_id = req.state.request_id
|
request_id = req.state.request_id
|
||||||
header = {"x-api-request-id": request_id}
|
header = {"x-api-request-id": request_id}
|
||||||
(response, status, _) = await request(f"{API_USERS}/{id}", "GET", headers=header)
|
(response, status, _) = await request(f"{API_USERS}/{id}", "GET", headers=header)
|
||||||
|
@ -40,7 +36,13 @@ async def get_user(id: str, req: Request):
|
||||||
|
|
||||||
|
|
||||||
@router.put("/{id}", response_model=User)
|
@router.put("/{id}", response_model=User)
|
||||||
async def update_user(user: UserRegister, req: Request):
|
async def update_user(
|
||||||
|
id: str,
|
||||||
|
user: UserRegister,
|
||||||
|
req: Request,
|
||||||
|
authorization: Annotated[str | None, Header()] = None,
|
||||||
|
):
|
||||||
|
await checkAuth(req, authorization, userId=id)
|
||||||
request_id = req.state.request_id
|
request_id = req.state.request_id
|
||||||
header = {"x-api-request-id": request_id}
|
header = {"x-api-request-id": request_id}
|
||||||
(response, status, _) = await request(
|
(response, status, _) = await request(
|
||||||
|
@ -51,8 +53,11 @@ async def update_user(user: UserRegister, req: Request):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{id}", response_model=User)
|
@router.delete("/{id}")
|
||||||
async def delete_user(req: Request):
|
async def delete_user(
|
||||||
|
id: str, req: Request, authorization: Annotated[str | None, Header()] = None
|
||||||
|
):
|
||||||
|
await checkAuth(req, authorization, userId=id)
|
||||||
request_id = req.state.request_id
|
request_id = req.state.request_id
|
||||||
header = {"x-api-request-id": request_id}
|
header = {"x-api-request-id": request_id}
|
||||||
(response, status, _) = await request(f"{API_USERS}/{id}", "DELETE", headers=header)
|
(response, status, _) = await request(f"{API_USERS}/{id}", "DELETE", headers=header)
|
||||||
|
|
|
@ -15,6 +15,11 @@ class UserMin(BaseModel):
|
||||||
email: str
|
email: str
|
||||||
|
|
||||||
|
|
||||||
|
class UserStatus(BaseModel):
|
||||||
|
id: int
|
||||||
|
airline: bool
|
||||||
|
|
||||||
|
|
||||||
class UserRegister(BaseModel):
|
class UserRegister(BaseModel):
|
||||||
username: str
|
username: str
|
||||||
email: str
|
email: str
|
||||||
|
|
Loading…
Reference in New Issue