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:
Mocsár Kálmán
2020-04-17 09:20:00 +02:00
committed by GitHub
parent 2b9ed9333a
commit fb874fea35
5 changed files with 54 additions and 17 deletions

View File

@@ -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:

View File

@@ -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]:

View File

@@ -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

View File

@@ -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)

View File

@@ -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)