✨ Update CRUD utils for users handling password hashing (#106)
* Add some information how to run backand test for local backand development * Bug fixes in backend app * 🎨 Update format * ✅ Use random_email for test_update_user Co-authored-by: Mocsar Kalman <mocsar.kalman@gravityrd.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
@@ -134,6 +134,20 @@ If you need to install any additional package for the tests, add it to the file
|
||||
|
||||
If you use GitLab CI the tests will run automatically.
|
||||
|
||||
#### Local tests
|
||||
|
||||
Start the stack with this command:
|
||||
|
||||
```Bash
|
||||
DOMAIN=backend sh ./scripts/test-local.sh
|
||||
```
|
||||
The `./backend/app` directory is mounted as a "host volume" inside the docker container (set in the file `docker-compose.dev.volumes.yml`).
|
||||
You can rerun the test on live code:
|
||||
|
||||
```Bash
|
||||
docker-compose exec backend-tests /tests-start.sh
|
||||
```
|
||||
|
||||
#### Test running stack
|
||||
|
||||
If your stack is already up and you just want to run the tests, you can use:
|
||||
|
@@ -3,7 +3,7 @@ from typing import Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models.user import User
|
||||
from app.schemas.user import UserCreate, UserUpdate
|
||||
from app.schemas.user import UserCreate, UserUpdate, UserInDB
|
||||
from app.core.security import verify_password, get_password_hash
|
||||
from app.crud.base import CRUDBase
|
||||
|
||||
@@ -24,6 +24,15 @@ class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
|
||||
db_session.refresh(db_obj)
|
||||
return db_obj
|
||||
|
||||
def update(self, db_session: Session, *, db_obj: User, obj_in: UserUpdate) -> User:
|
||||
if obj_in.password:
|
||||
update_data = obj_in.dict(exclude_unset=True)
|
||||
hashed_password = get_password_hash(obj_in.password)
|
||||
del update_data["password"]
|
||||
update_data["hashed_password"] = hashed_password
|
||||
use_obj_in = UserInDB.parse_obj(update_data)
|
||||
return super().update(db_session, db_obj=db_obj, obj_in=use_obj_in)
|
||||
|
||||
def authenticate(
|
||||
self, db_session: Session, *, email: str, password: str
|
||||
) -> Optional[User]:
|
||||
|
@@ -11,29 +11,29 @@ class UserBase(BaseModel):
|
||||
full_name: Optional[str] = None
|
||||
|
||||
|
||||
class UserBaseInDB(UserBase):
|
||||
# Properties to receive via API on creation
|
||||
class UserCreate(UserBase):
|
||||
email: EmailStr
|
||||
password: str
|
||||
|
||||
|
||||
# Properties to receive via API on update
|
||||
class UserUpdate(UserBase):
|
||||
password: Optional[str] = None
|
||||
|
||||
|
||||
class UserInDBBase(UserBase):
|
||||
id: int = None
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
# Properties to receive via API on creation
|
||||
class UserCreate(UserBaseInDB):
|
||||
email: EmailStr
|
||||
password: str
|
||||
|
||||
|
||||
# Properties to receive via API on update
|
||||
class UserUpdate(UserBaseInDB):
|
||||
password: Optional[str] = None
|
||||
|
||||
|
||||
# Additional properties to return via API
|
||||
class User(UserBaseInDB):
|
||||
class User(UserInDBBase):
|
||||
pass
|
||||
|
||||
|
||||
# Additional properties stored in DB
|
||||
class UserInDB(UserBaseInDB):
|
||||
class UserInDB(UserInDBBase):
|
||||
hashed_password: str
|
||||
|
@@ -1,8 +1,9 @@
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
|
||||
from app import crud
|
||||
from app.core.security import get_password_hash, verify_password
|
||||
from app.db.session import db_session
|
||||
from app.schemas.user import UserCreate
|
||||
from app.schemas.user import UserCreate, UserUpdate
|
||||
from app.tests.utils.utils import random_lower_string, random_email
|
||||
|
||||
|
||||
@@ -78,3 +79,16 @@ def test_get_user():
|
||||
user_2 = crud.user.get(db_session, id=user.id)
|
||||
assert user.email == user_2.email
|
||||
assert jsonable_encoder(user) == jsonable_encoder(user_2)
|
||||
|
||||
|
||||
def test_update_user():
|
||||
password = random_lower_string()
|
||||
email = random_email()
|
||||
user_in = UserCreate(email=email, password=password, is_superuser=True)
|
||||
user = crud.user.create(db_session, obj_in=user_in)
|
||||
new_password = random_lower_string()
|
||||
user_in = UserUpdate(password=new_password, is_superuser=True)
|
||||
crud.user.update(db_session, db_obj=user, obj_in=user_in)
|
||||
user_2 = crud.user.get(db_session, id=user.id)
|
||||
assert user.email == user_2.email
|
||||
assert verify_password(new_password, user_2.hashed_password)
|
||||
|
@@ -38,6 +38,6 @@ def authentication_token_from_email(email):
|
||||
user = crud.user.create(db_session=db_session, obj_in=user_in)
|
||||
else:
|
||||
user_in = UserUpdate(password=password)
|
||||
user = crud.user.update(db_session, obj_in=user, db_obj=user_in)
|
||||
user = crud.user.update(db_session, db_obj=user, obj_in=user_in)
|
||||
|
||||
return user_authentication_headers(get_server_api(), email, password)
|
||||
|
Reference in New Issue
Block a user