mirror of
https://github.com/rommapp/romm.git
synced 2026-06-28 06:46:00 +00:00
fix: Use request body for user creation and update endpoints
Stop using query parameters for user creation and update endpoints in the API. Instead, use the request body to pass user data. This change stops leaking sensitive information like passwords in the URL. Fixes #2010
This commit is contained in:
@@ -1,25 +1,16 @@
|
||||
from fastapi import UploadFile
|
||||
from fastapi.param_functions import Form
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class UserForm:
|
||||
def __init__(
|
||||
self,
|
||||
username: str | None = None,
|
||||
password: str | None = None,
|
||||
email: str | None = None,
|
||||
role: str | None = None,
|
||||
enabled: bool | None = None,
|
||||
avatar: UploadFile | None = None,
|
||||
ra_username: str | None = None,
|
||||
):
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.email = email
|
||||
self.role = role
|
||||
self.enabled = enabled
|
||||
self.avatar = avatar
|
||||
self.ra_username = ra_username
|
||||
class UserForm(BaseModel):
|
||||
username: str | None = None
|
||||
password: str | None = None
|
||||
email: str | None = None
|
||||
role: str | None = None
|
||||
enabled: bool | None = None
|
||||
ra_username: str | None = None
|
||||
avatar: UploadFile | None = None
|
||||
|
||||
|
||||
class OAuth2RequestForm:
|
||||
|
||||
@@ -71,7 +71,7 @@ def test_get_user(client, access_token, editor_user):
|
||||
def test_add_user_from_admin_user(client, access_token, new_user_role):
|
||||
response = client.post(
|
||||
"/api/users",
|
||||
params={
|
||||
json={
|
||||
"username": "new_user",
|
||||
"password": "new_user_password",
|
||||
"email": "new_user@example.com",
|
||||
@@ -122,7 +122,7 @@ def test_add_user_from_unauthorized_user(
|
||||
):
|
||||
response = client.post(
|
||||
"/api/users",
|
||||
params={
|
||||
json={
|
||||
"username": "new_user",
|
||||
"password": "new_user_password",
|
||||
"email": "new_user@example.com",
|
||||
@@ -136,7 +136,7 @@ def test_add_user_from_unauthorized_user(
|
||||
def test_add_user_with_existing_username(client, access_token, admin_user):
|
||||
response = client.post(
|
||||
"/api/users",
|
||||
params={
|
||||
json={
|
||||
"username": admin_user.username,
|
||||
"password": "new_user_password",
|
||||
"email": "new_user@example.com",
|
||||
@@ -155,7 +155,7 @@ def test_update_user(client, access_token, editor_user):
|
||||
|
||||
response = client.put(
|
||||
f"/api/users/{editor_user.id}",
|
||||
params={"username": "editor_user_new_username", "role": "viewer"},
|
||||
data={"username": "editor_user_new_username", "role": "viewer"},
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -8,7 +8,7 @@ from decorators.auth import protected_route
|
||||
from endpoints.forms.identity import UserForm
|
||||
from endpoints.responses import MessageResponse
|
||||
from endpoints.responses.identity import InviteLinkSchema, UserSchema
|
||||
from fastapi import Body, Depends, HTTPException, Request, status
|
||||
from fastapi import Body, Form, HTTPException, Request, status
|
||||
from handler.auth import auth_handler
|
||||
from handler.auth.constants import Scope
|
||||
from handler.database import db_user_handler
|
||||
@@ -31,7 +31,11 @@ router = APIRouter(
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
)
|
||||
def add_user(
|
||||
request: Request, username: str, password: str, email: str, role: str
|
||||
request: Request,
|
||||
username: str = Body(..., embed=True),
|
||||
email: str = Body(..., embed=True),
|
||||
password: str = Body(..., embed=True),
|
||||
role: str = Body(..., embed=True),
|
||||
) -> UserSchema:
|
||||
"""Create user endpoint
|
||||
|
||||
@@ -219,7 +223,7 @@ def get_user(request: Request, id: int) -> UserSchema:
|
||||
|
||||
@protected_route(router.put, "/{id}", [Scope.ME_WRITE])
|
||||
async def update_user(
|
||||
request: Request, id: int, form_data: Annotated[UserForm, Depends()]
|
||||
request: Request, id: int, form_data: Annotated[UserForm, Form()]
|
||||
) -> UserSchema:
|
||||
"""Update user endpoint
|
||||
|
||||
|
||||
@@ -19,11 +19,7 @@ async function createUser({
|
||||
email: string;
|
||||
role: string;
|
||||
}): Promise<{ data: UserSchema }> {
|
||||
return api.post(
|
||||
"/users",
|
||||
{},
|
||||
{ params: { username, password, email, role } },
|
||||
);
|
||||
return api.post("/users", { username, password, email, role });
|
||||
}
|
||||
|
||||
async function createInviteLink({
|
||||
@@ -67,18 +63,18 @@ async function updateUser({
|
||||
`/users/${id}`,
|
||||
{
|
||||
avatar: avatar || null,
|
||||
username: attrs.username,
|
||||
password: attrs.password,
|
||||
email: attrs.email,
|
||||
enabled: attrs.enabled,
|
||||
role: attrs.role,
|
||||
ra_username: attrs.ra_username,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": avatar ? "multipart/form-data" : "application/json",
|
||||
},
|
||||
params: {
|
||||
username: attrs.username,
|
||||
password: attrs.password,
|
||||
email: attrs.email,
|
||||
enabled: attrs.enabled,
|
||||
role: attrs.role,
|
||||
ra_username: attrs.ra_username,
|
||||
"Content-Type": avatar
|
||||
? "multipart/form-data"
|
||||
: "application/x-www-form-urlencoded",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user