Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ IMPR ] hashed passwords #237

Merged
merged 11 commits into from
Aug 6, 2024
4 changes: 2 additions & 2 deletions store/app/crud/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ async def get_user(self, id: str, throw_if_missing: bool = False) -> User | None
async def get_user(self, id: str, throw_if_missing: bool = False) -> User | None:
return await self._get_item(id, User, throw_if_missing=throw_if_missing)

async def _create_user_from_email(self, email: str) -> User:
user = User.create(email=email)
async def _create_user_from_email(self, email: str, password: str) -> User:
user = User.create(email=email, password=password)
await self._add_item(user, unique_fields=["email"])
return user

Expand Down
25 changes: 22 additions & 3 deletions store/app/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from pydantic import BaseModel

from store.settings import settings
from store.store.app.utils.password import hash_password
from store.utils import new_uuid


Expand All @@ -32,17 +33,35 @@ class RobolistBaseModel(BaseModel):
class User(RobolistBaseModel):
"""Defines the user model for the API.

Users are defined by their email, username and password hash. This is the
Users are defined by their email and hashed_password. This is the
simplest form of authentication, and is used for users who sign up with
their email and password.
"""

email: str
hashed_password: str
permissions: set[UserPermission] | None = None
created_at: int
updated_at: int
email_verified_at: int | None = None

@classmethod
def create(cls, email: str) -> Self:
return cls(id=new_uuid(), email=email, permissions=None)
def create(cls, email: str, password: str) -> Self:
now = int(time.time())
return cls(
id=new_uuid(),
email=email,
hashed_password=hash_password(password),
permissions=None,
created_at=now,
updated_at=now,
)

def update_timestamp(self) -> None:
self.updated_at = int(time.time())

def verify_email(self) -> None:
self.email_verified_at = int(time.time())


class OAuthKey(RobolistBaseModel):
Expand Down
15 changes: 15 additions & 0 deletions store/app/utils/password.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""Utility functions for hashing and verifying passwords.

For User sign up and login.
"""

import bcrypt


def hash_password(password: str) -> str:
salt = bcrypt.gensalt()
return bcrypt.hashpw(password.encode("utf-8"), salt).decode("utf-8")


def verify_password(plain_password: str, hashed_password: str) -> bool:
return bcrypt.checkpw(plain_password.encode("utf-8"), hashed_password.encode("utf-8"))
Loading