Skip to content

Commit fb874fe

Browse files
mocsarkMocsar Kalmantiangolo
authored
✨ 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 <[email protected]> Co-authored-by: Sebastián Ramírez <[email protected]>
1 parent 2b9ed93 commit fb874fe

File tree

5 files changed

+51
-14
lines changed

5 files changed

+51
-14
lines changed

{{cookiecutter.project_slug}}/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,20 @@ If you need to install any additional package for the tests, add it to the file
134134

135135
If you use GitLab CI the tests will run automatically.
136136

137+
#### Local tests
138+
139+
Start the stack with this command:
140+
141+
```Bash
142+
DOMAIN=backend sh ./scripts/test-local.sh
143+
```
144+
The `./backend/app` directory is mounted as a "host volume" inside the docker container (set in the file `docker-compose.dev.volumes.yml`).
145+
You can rerun the test on live code:
146+
147+
```Bash
148+
docker-compose exec backend-tests /tests-start.sh
149+
```
150+
137151
#### Test running stack
138152

139153
If your stack is already up and you just want to run the tests, you can use:

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from sqlalchemy.orm import Session
44

55
from app.models.user import User
6-
from app.schemas.user import UserCreate, UserUpdate
6+
from app.schemas.user import UserCreate, UserUpdate, UserInDB
77
from app.core.security import verify_password, get_password_hash
88
from app.crud.base import CRUDBase
99

@@ -24,6 +24,15 @@ def create(self, db_session: Session, *, obj_in: UserCreate) -> User:
2424
db_session.refresh(db_obj)
2525
return db_obj
2626

27+
def update(self, db_session: Session, *, db_obj: User, obj_in: UserUpdate) -> User:
28+
if obj_in.password:
29+
update_data = obj_in.dict(exclude_unset=True)
30+
hashed_password = get_password_hash(obj_in.password)
31+
del update_data["password"]
32+
update_data["hashed_password"] = hashed_password
33+
use_obj_in = UserInDB.parse_obj(update_data)
34+
return super().update(db_session, db_obj=db_obj, obj_in=use_obj_in)
35+
2736
def authenticate(
2837
self, db_session: Session, *, email: str, password: str
2938
) -> Optional[User]:

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,29 @@ class UserBase(BaseModel):
1111
full_name: Optional[str] = None
1212

1313

14-
class UserBaseInDB(UserBase):
15-
id: int = None
16-
17-
class Config:
18-
orm_mode = True
19-
20-
2114
# Properties to receive via API on creation
22-
class UserCreate(UserBaseInDB):
15+
class UserCreate(UserBase):
2316
email: EmailStr
2417
password: str
2518

2619

2720
# Properties to receive via API on update
28-
class UserUpdate(UserBaseInDB):
21+
class UserUpdate(UserBase):
2922
password: Optional[str] = None
3023

3124

25+
class UserInDBBase(UserBase):
26+
id: int = None
27+
28+
class Config:
29+
orm_mode = True
30+
31+
3232
# Additional properties to return via API
33-
class User(UserBaseInDB):
33+
class User(UserInDBBase):
3434
pass
3535

3636

3737
# Additional properties stored in DB
38-
class UserInDB(UserBaseInDB):
38+
class UserInDB(UserInDBBase):
3939
hashed_password: str

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from fastapi.encoders import jsonable_encoder
22

33
from app import crud
4+
from app.core.security import get_password_hash, verify_password
45
from app.db.session import db_session
5-
from app.schemas.user import UserCreate
6+
from app.schemas.user import UserCreate, UserUpdate
67
from app.tests.utils.utils import random_lower_string, random_email
78

89

@@ -78,3 +79,16 @@ def test_get_user():
7879
user_2 = crud.user.get(db_session, id=user.id)
7980
assert user.email == user_2.email
8081
assert jsonable_encoder(user) == jsonable_encoder(user_2)
82+
83+
84+
def test_update_user():
85+
password = random_lower_string()
86+
email = random_email()
87+
user_in = UserCreate(email=email, password=password, is_superuser=True)
88+
user = crud.user.create(db_session, obj_in=user_in)
89+
new_password = random_lower_string()
90+
user_in = UserUpdate(password=new_password, is_superuser=True)
91+
crud.user.update(db_session, db_obj=user, obj_in=user_in)
92+
user_2 = crud.user.get(db_session, id=user.id)
93+
assert user.email == user_2.email
94+
assert verify_password(new_password, user_2.hashed_password)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ def authentication_token_from_email(email):
3838
user = crud.user.create(db_session=db_session, obj_in=user_in)
3939
else:
4040
user_in = UserUpdate(password=password)
41-
user = crud.user.update(db_session, obj_in=user, db_obj=user_in)
41+
user = crud.user.update(db_session, db_obj=user, obj_in=user_in)
4242

4343
return user_authentication_headers(get_server_api(), email, password)

0 commit comments

Comments
 (0)