Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions example/database-app/.env.testing
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
APP_NAME="Masonite Testing"
APP_ENV=testing

DB_HOST=localhost
DB_DATABASE=postgres_testing
DB_USER=postgres
DB_PASSWORD=postgres
DB_PORT=5432
DB_HOST=127.0.0.1
DB_DATABASE=database_app_test
DB_USERNAME=app
DB_PASSWORD=secret
DB_PORT=3306

LOG_CHANNEL=syslog
1 change: 1 addition & 0 deletions example/database-app/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.venv
storage
.claude
44 changes: 44 additions & 0 deletions example/database-app/app/http/controllers/auth_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from fastapi import HTTPException
import hashlib

from app.models.user import User
from app.models.profile import Profile
from app.http.schemas.auth import StudentRegistrationRequest, TeacherRegistrationRequest

class AuthController:
@staticmethod
async def register_teacher(data: TeacherRegistrationRequest):
# Check if user exists
existing_user = await User.where("email", data.email).first()
if existing_user:
raise HTTPException(status_code=400, detail="Email already registered")

# Hash password
hashed_password = hashlib.md5(data.password.encode()).hexdigest()

# Create user
user = User()
user.name = data.name
user.email = data.email
user.password = hashed_password
user.role = "teacher"
await user.save()

# Workaround for asyncpg insert bug in masoniteorm returning dict to primary key
actual_user_id = user.id.get("id") if isinstance(user.id, dict) else user.id

# Create teacher profile
profile = Profile()
profile.user_id = actual_user_id
profile.country = data.country
profile.phone_number = data.phone_number
profile.headline = data.headline
profile.description = data.description
profile.video_url = data.video_url
profile.hourly_rate = data.hourly_rate
import json
profile.languages_spoken = json.dumps(data.languages_spoken)
profile.subjects = json.dumps(data.subjects)
await profile.save()

return {"message": "Teacher registered successfully", "user_id": actual_user_id}
16 changes: 16 additions & 0 deletions example/database-app/app/http/schemas/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from pydantic import BaseModel, EmailStr, Field

class StudentRegistrationRequest(BaseModel):
name: str = Field(..., min_length=2, max_length=255)
email: EmailStr
password: str = Field(..., min_length=8)

class TeacherRegistrationRequest(StudentRegistrationRequest):
country: str = Field(..., min_length=2)
phone_number: str
headline: str = Field(..., min_length=5, max_length=255)
description: str = Field(..., min_length=50)
video_url: str
hourly_rate: int = Field(..., gt=0)
languages_spoken: list[str]
subjects: list[str]
9 changes: 5 additions & 4 deletions example/database-app/app/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .user import User
from .post import Post
from .tag import Tag
from .media import Media
from .post_tag import PostTag
from .profile import Profile
from .lesson import Lesson
from .course import Course
from .category import Category
from .review import Review
18 changes: 18 additions & 0 deletions example/database-app/app/models/category.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from typing import TYPE_CHECKING

from fastapi_startkit.masoniteorm.models import Model
from fastapi_startkit.masoniteorm.relationships import HasMany, HasManyThrough

if TYPE_CHECKING:
from app.models.course import Course
from app.models.lesson import Lesson


class Category(Model):
__table__ = "categories"

name: str
description: str | None

courses = HasMany("Course")
lessons = HasManyThrough(["Lesson", "Course"], "category_id", "course_id")
30 changes: 30 additions & 0 deletions example/database-app/app/models/course.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import TYPE_CHECKING

from fastapi_startkit.masoniteorm.models import Model
from fastapi_startkit.masoniteorm.relationships import BelongsTo, HasMany, BelongsToMany, MorphMany

if TYPE_CHECKING:
from app.models.category import Category
from app.models.lesson import Lesson
from app.models.user import User
from app.models.review import Review


class Course(Model):
__table__ = "courses"

title: str
description: str | None
price: int

category = BelongsTo("Category")
lessons = HasMany("Lesson")
students = BelongsToMany(
"User",
local_foreign_key="course_id",
other_foreign_key="user_id",
table="course_user",
with_timestamps=True,
with_fields=["progress", "completed_at"]
)
reviews = MorphMany("Review", "reviewable_type", "reviewable_id")
17 changes: 17 additions & 0 deletions example/database-app/app/models/lesson.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from typing import TYPE_CHECKING

from fastapi_startkit.masoniteorm.models import Model
from fastapi_startkit.masoniteorm.relationships import BelongsTo, MorphMany

if TYPE_CHECKING:
from app.models.course import Course
from app.models.review import Review


class Lesson(Model):
__table__ = "lessons"

title: str

course = BelongsTo("Course")
reviews = MorphMany("Review", "reviewable_type", "reviewable_id")
17 changes: 0 additions & 17 deletions example/database-app/app/models/media.py

This file was deleted.

22 changes: 0 additions & 22 deletions example/database-app/app/models/post.py

This file was deleted.

9 changes: 0 additions & 9 deletions example/database-app/app/models/post_tag.py

This file was deleted.

25 changes: 25 additions & 0 deletions example/database-app/app/models/profile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from typing import TYPE_CHECKING

from fastapi_startkit.masoniteorm.models import Model
from fastapi_startkit.masoniteorm.relationships import BelongsTo

if TYPE_CHECKING:
from app.models.user import User


class Profile(Model):
__table__ = "profiles"

bio: str | None
website: str | None
avatar_url: str | None
country: str | None
phone_number: str | None
headline: str | None
description: str | None
video_url: str | None
hourly_rate: int | None
languages_spoken: dict | list | None
subjects: dict | list | None

user = BelongsTo("User")
12 changes: 12 additions & 0 deletions example/database-app/app/models/review.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from typing import TYPE_CHECKING

from fastapi_startkit.masoniteorm.models import Model
from fastapi_startkit.masoniteorm.relationships import MorphTo

class Review(Model):
__table__ = "reviews"

reviewable_type: str
content: str

reviewable = MorphTo("Review", morph_key="reviewable_type", morph_id="reviewable_id")
14 changes: 0 additions & 14 deletions example/database-app/app/models/tag.py

This file was deleted.

17 changes: 13 additions & 4 deletions example/database-app/app/models/user.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
from typing import TYPE_CHECKING

from fastapi_startkit.masoniteorm.models import Model
from fastapi_startkit.masoniteorm.relationships import HasMany
from fastapi_startkit.masoniteorm.relationships import HasMany, HasOne, BelongsToMany

if TYPE_CHECKING:
from app.models.post import Post
from app.models.profile import Profile
from app.models.course import Course


class User(Model):
__table__ = "users"

id: int
name: str
email: str
role: str

posts: list["Post"] = HasMany("Post")
profile = HasOne("Profile")
courses = BelongsToMany(
"Course",
local_foreign_key="user_id",
other_foreign_key="course_id",
table="course_user",
with_timestamps=True,
with_fields=["progress", "completed_at"]
)
31 changes: 31 additions & 0 deletions example/database-app/app/students/controllers/auth_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import hashlib

from fastapi import HTTPException

from app.http.schemas.auth import StudentRegistrationRequest
from app.models import User, Profile


async def register(request: StudentRegistrationRequest):
existing_user = await User.where("email", request.email).first()
if existing_user:
raise HTTPException(status_code=400, detail="Email already registered")

password = hashlib.md5(request.password.encode()).hexdigest()
user = User(
name=request.name,
email=request.email,
password=password,
role="student",
)
await user.save()

profile = Profile()
profile.user_id = user.id
await profile.save()

return {"message": "Student registered successfully", "user_id": user.id}


def login():
pass
7 changes: 7 additions & 0 deletions example/database-app/app/students/requests/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from pydantic import BaseModel, Field, EmailStr


class StudentRegistrationRequest(BaseModel):
name: str = Field(..., min_length=2, max_length=255)
email: EmailStr
password: str = Field(..., min_length=8)
1 change: 1 addition & 0 deletions example/database-app/artisan
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3

import sys
print("Artisan starting...")
from bootstrap.application import app

if __name__ == "__main__":
Expand Down
12 changes: 10 additions & 2 deletions example/database-app/bootstrap/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@
from providers.fastapi_provider import FastAPIServiceProvider

from config.app import AppConfig

print("Loading Application class...")
from fastapi_startkit.application import Application
from fastapi_startkit.exceptions import ExceptionHandler
from fastapi_startkit.logging.providers import LogProvider
from fastapi_startkit.masoniteorm.providers import DatabaseProvider


class _FallbackHandler:
async def render(self, request, exc):
from fastapi.responses import JSONResponse
return JSONResponse(status_code=500, content={"detail": "Internal Server Error"})


class AppExceptionHandler(ExceptionHandler):
def register(self):
pass
self.register_handler(Exception, _FallbackHandler())


app: Application[AppConfig] = Application(
Expand All @@ -27,4 +35,4 @@ def register(self):
FastAPIServiceProvider,
],
exception_handler=AppExceptionHandler,
)
)
Loading
Loading