Skip to content

Commit

Permalink
✨ Update CRUD utils for users handling password hashing (#106)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
3 people authored Apr 17, 2020
1 parent 2b9ed93 commit fb874fe
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 14 deletions.
14 changes: 14 additions & 0 deletions {{cookiecutter.project_slug}}/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
11 changes: 10 additions & 1 deletion {{cookiecutter.project_slug}}/backend/app/app/crud/crud_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
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

Expand All @@ -24,6 +24,15 @@ def create(self, db_session: Session, *, obj_in: UserCreate) -> User:
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]:
Expand Down
22 changes: 11 additions & 11 deletions {{cookiecutter.project_slug}}/backend/app/app/schemas/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
@@ -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


Expand Down Expand Up @@ -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)
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit fb874fe

Please sign in to comment.