Browse Source

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>
pull/13907/head
Mocsár Kálmán 5 years ago
committed by GitHub
parent
commit
fb874fea35
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      {{cookiecutter.project_slug}}/README.md
  2. 11
      {{cookiecutter.project_slug}}/backend/app/app/crud/crud_user.py
  3. 22
      {{cookiecutter.project_slug}}/backend/app/app/schemas/user.py
  4. 16
      {{cookiecutter.project_slug}}/backend/app/app/tests/crud/test_user.py
  5. 2
      {{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py

14
{{cookiecutter.project_slug}}/README.md

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

11
{{cookiecutter.project_slug}}/backend/app/app/crud/crud_user.py

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

22
{{cookiecutter.project_slug}}/backend/app/app/schemas/user.py

@ -11,29 +11,29 @@ class UserBase(BaseModel):
full_name: Optional[str] = None
class UserBaseInDB(UserBase):
id: int = None
class Config:
orm_mode = True
# Properties to receive via API on creation
class UserCreate(UserBaseInDB):
class UserCreate(UserBase):
email: EmailStr
password: str
# Properties to receive via API on update
class UserUpdate(UserBaseInDB):
class UserUpdate(UserBase):
password: Optional[str] = None
class UserInDBBase(UserBase):
id: int = None
class Config:
orm_mode = True
# 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

16
{{cookiecutter.project_slug}}/backend/app/app/tests/crud/test_user.py

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

2
{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py

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

Loading…
Cancel
Save