\ No newline at end of file
diff --git a/backend/app/email-templates/build/reset_password.html b/backend/app/email-templates/build/reset_password.html
new file mode 100644
index 0000000..4148a5b
--- /dev/null
+++ b/backend/app/email-templates/build/reset_password.html
@@ -0,0 +1,25 @@
+
{{ project_name }} - Password Recovery
Hello {{ username }}
We've received a request to reset your password. You can do it by clicking the button below:
This password will expire in {{ valid_hours }} hours.
If you didn't request a password recovery you can disregard this email.
\ No newline at end of file
diff --git a/backend/app/email-templates/build/test_email.html b/backend/app/email-templates/build/test_email.html
new file mode 100644
index 0000000..04d0d85
--- /dev/null
+++ b/backend/app/email-templates/build/test_email.html
@@ -0,0 +1,25 @@
+
{{ project_name }}
Test email for: {{ email }}
\ No newline at end of file
diff --git a/backend/app/email-templates/src/new_account.mjml b/backend/app/email-templates/src/new_account.mjml
new file mode 100644
index 0000000..f41a3e3
--- /dev/null
+++ b/backend/app/email-templates/src/new_account.mjml
@@ -0,0 +1,15 @@
+
+
+
+
+ {{ project_name }} - New Account
+ Welcome to your new account!
+ Here are your account details:
+ Username: {{ username }}
+ Password: {{ password }}
+ Go to Dashboard
+
+
+
+
+
diff --git a/backend/app/email-templates/src/reset_password.mjml b/backend/app/email-templates/src/reset_password.mjml
new file mode 100644
index 0000000..743f5d7
--- /dev/null
+++ b/backend/app/email-templates/src/reset_password.mjml
@@ -0,0 +1,17 @@
+
+
+
+
+ {{ project_name }} - Password Recovery
+ Hello {{ username }}
+ We've received a request to reset your password. You can do it by clicking the button below:
+ Reset password
+ Or copy and paste the following link into your browser:
+ {{ link }}
+ This password will expire in {{ valid_hours }} hours.
+
+ If you didn't request a password recovery you can disregard this email.
+
+
+
+
diff --git a/backend/app/email-templates/src/test_email.mjml b/backend/app/email-templates/src/test_email.mjml
new file mode 100644
index 0000000..45d58d6
--- /dev/null
+++ b/backend/app/email-templates/src/test_email.mjml
@@ -0,0 +1,11 @@
+
+
+
+
+ {{ project_name }}
+ Test email for: {{ email }}
+
+
+
+
+
diff --git a/backend/app/core/initial_data.py b/backend/app/initial_data.py
similarity index 100%
rename from backend/app/core/initial_data.py
rename to backend/app/initial_data.py
diff --git a/backend/app/models/user.py b/backend/app/models.py
similarity index 52%
rename from backend/app/models/user.py
rename to backend/app/models.py
index 33b1412..2389b4a 100644
--- a/backend/app/models/user.py
+++ b/backend/app/models.py
@@ -1,9 +1,8 @@
import uuid
+
from pydantic import EmailStr
from sqlmodel import Field, Relationship, SQLModel
-from app.models.item import Item
-
# Shared properties
class UserBase(SQLModel):
@@ -44,7 +43,7 @@ class UpdatePassword(SQLModel):
class User(UserBase, table=True):
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
hashed_password: str
- items: list[Item] = Relationship(back_populates="owner", cascade_delete=True)
+ items: list["Item"] = Relationship(back_populates="owner", cascade_delete=True)
# Properties to return via API, id is always required
@@ -54,4 +53,61 @@ class UserPublic(UserBase):
class UsersPublic(SQLModel):
data: list[UserPublic]
- count: int
\ No newline at end of file
+ count: int
+
+
+# Shared properties
+class ItemBase(SQLModel):
+ title: str = Field(min_length=1, max_length=255)
+ description: str | None = Field(default=None, max_length=255)
+
+
+# Properties to receive on item creation
+class ItemCreate(ItemBase):
+ pass
+
+
+# Properties to receive on item update
+class ItemUpdate(ItemBase):
+ title: str | None = Field(default=None, min_length=1, max_length=255) # type: ignore
+
+
+# Database model, database table inferred from class name
+class Item(ItemBase, table=True):
+ id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
+ owner_id: uuid.UUID = Field(
+ foreign_key="user.id", nullable=False, ondelete="CASCADE"
+ )
+ owner: User | None = Relationship(back_populates="items")
+
+
+# Properties to return via API, id is always required
+class ItemPublic(ItemBase):
+ id: uuid.UUID
+ owner_id: uuid.UUID
+
+
+class ItemsPublic(SQLModel):
+ data: list[ItemPublic]
+ count: int
+
+
+# Generic message
+class Message(SQLModel):
+ message: str
+
+
+# JSON payload containing access token
+class Token(SQLModel):
+ access_token: str
+ token_type: str = "bearer"
+
+
+# Contents of JWT token
+class TokenPayload(SQLModel):
+ sub: str | None = None
+
+
+class NewPassword(SQLModel):
+ token: str
+ new_password: str = Field(min_length=8, max_length=40)
diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py
deleted file mode 100644
index 0519ecb..0000000
--- a/backend/app/models/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/backend/app/models/auth.py b/backend/app/models/auth.py
deleted file mode 100644
index 0f12523..0000000
--- a/backend/app/models/auth.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from sqlmodel import SQLModel, Field
-
-
-# JSON payload containing access token
-class Token(SQLModel):
- access_token: str
- token_type: str = "bearer"
-
-
-# Contents of JWT token
-class TokenPayload(SQLModel):
- sub: str | None = None
-
-
-class NewPassword(SQLModel):
- token: str
- new_password: str = Field(min_length=8, max_length=40)
\ No newline at end of file
diff --git a/backend/app/models/item.py b/backend/app/models/item.py
deleted file mode 100644
index 68a55d0..0000000
--- a/backend/app/models/item.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import uuid
-from sqlmodel import Field, Relationship, SQLModel
-
-from app.models.user import User
-
-
-# Shared properties
-class ItemBase(SQLModel):
- title: str = Field(min_length=1, max_length=255)
- description: str | None = Field(default=None, max_length=255)
-
-
-# Properties to receive on item creation
-class ItemCreate(ItemBase):
- pass
-
-
-# Properties to receive on item update
-class ItemUpdate(ItemBase):
- title: str | None = Field(default=None, min_length=1, max_length=255) # type: ignore
-
-
-# Database model, database table inferred from class name
-class Item(ItemBase, table=True):
- id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
- owner_id: uuid.UUID = Field(
- foreign_key="user.id", nullable=False, ondelete="CASCADE"
- )
- owner: User | None = Relationship(back_populates="items")
-
-
-# Properties to return via API, id is always required
-class ItemPublic(ItemBase):
- id: uuid.UUID
- owner_id: uuid.UUID
-
-
-class ItemsPublic(SQLModel):
- data: list[ItemPublic]
- count: int
\ No newline at end of file
diff --git a/backend/app/models/todo.py b/backend/app/models/todo.py
new file mode 100644
index 0000000..6e53672
--- /dev/null
+++ b/backend/app/models/todo.py
@@ -0,0 +1,13 @@
+from sqlalchemy import Column, Integer, String, Boolean, DateTime
+from sqlalchemy.sql import func
+from app.db.base_class import Base
+
+class Todo(Base):
+ __tablename__ = "todos"
+
+ id = Column(Integer, primary_key=True, index=True)
+ title = Column(String, index=True)
+ description = Column(String, nullable=True)
+ completed = Column(Boolean, default=False)
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
+ updated_at = Column(DateTime(timezone=True), onupdate=func.now())
\ No newline at end of file
diff --git a/backend/app/repositories/item.py b/backend/app/repositories/item.py
deleted file mode 100644
index a28e359..0000000
--- a/backend/app/repositories/item.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import uuid
-from sqlmodel import Session
-
-from app.models import Item, ItemCreate
-
-
-def create_item(*, session: Session, item_in: ItemCreate, owner_id: uuid.UUID) -> Item:
- db_item = Item.model_validate(item_in, update={"owner_id": owner_id})
- session.add(db_item)
- session.commit()
- session.refresh(db_item)
- return db_item
\ No newline at end of file
diff --git a/backend/app/schemas/todo.py b/backend/app/schemas/todo.py
new file mode 100644
index 0000000..2332745
--- /dev/null
+++ b/backend/app/schemas/todo.py
@@ -0,0 +1,22 @@
+from pydantic import BaseModel
+from datetime import datetime
+from typing import Optional
+
+class TodoBase(BaseModel):
+ title: str
+ description: Optional[str] = None
+ completed: bool = False
+
+class TodoCreate(TodoBase):
+ pass
+
+class TodoUpdate(TodoBase):
+ pass
+
+class Todo(TodoBase):
+ id: int
+ created_at: datetime
+ updated_at: Optional[datetime] = None
+
+ class Config:
+ from_attributes = True
\ No newline at end of file
diff --git a/backend/app/services/auth.py b/backend/app/services/auth.py
deleted file mode 100644
index 5c3c52a..0000000
--- a/backend/app/services/auth.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from sqlmodel import Session
-
-from app.core.security import verify_password
-from app.repositories.user import get_user_by_email
-
-
-def authenticate(*, session: Session, email: str, password: str) -> User | None:
- db_user = get_user_by_email(session=session, email=email)
- if not db_user:
- return None
- if not verify_password(password, db_user.hashed_password):
- return None
- return db_user
\ No newline at end of file
diff --git a/backend/app/tests/api/routes/test_login.py b/backend/app/tests/api/routes/test_login.py
index a814205..80fa787 100644
--- a/backend/app/tests/api/routes/test_login.py
+++ b/backend/app/tests/api/routes/test_login.py
@@ -9,7 +9,7 @@ from app.crud import create_user
from app.models import UserCreate
from app.tests.utils.user import user_authentication_headers
from app.tests.utils.utils import random_email, random_lower_string
-from app.utils.common import generate_password_reset_token
+from app.utils import generate_password_reset_token
def test_get_access_token(client: TestClient) -> None:
diff --git a/backend/app/core/tests_pre_start.py b/backend/app/tests_pre_start.py
similarity index 100%
rename from backend/app/core/tests_pre_start.py
rename to backend/app/tests_pre_start.py
diff --git a/backend/app/utils/common.py b/backend/app/utils.py
similarity index 100%
rename from backend/app/utils/common.py
rename to backend/app/utils.py
diff --git a/backend/requirements.txt b/backend/requirements.txt
deleted file mode 100644
index 7bae48a..0000000
--- a/backend/requirements.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-pydantic>=2.8.2
-sqlmodel>=0.0.14
-python-jose[cryptography]>=3.3.0
-passlib[bcrypt]>=1.7.4
-python-multipart>=0.0.6
-email-validator>=2.1.0.post1
\ No newline at end of file
diff --git a/scripts/generate-client.sh b/scripts/generate-client.sh
index f688c18..1e76864 100644
--- a/scripts/generate-client.sh
+++ b/scripts/generate-client.sh
@@ -9,4 +9,4 @@ cd ..
mv openapi.json frontend/
cd frontend
npm run generate-client
-npx biome format --write ./src/client
\ No newline at end of file
+npx biome format --write ./src/client