-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
37 changed files
with
1,752 additions
and
274 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DB_URI="" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,40 @@ | ||
"""FastAPI server.""" | ||
|
||
from fastapi import FastAPI, Request, status | ||
import textwrap | ||
|
||
from fastapi import FastAPI, status | ||
from fastapi.middleware.cors import CORSMiddleware | ||
from fastapi.responses import ORJSONResponse | ||
|
||
from src.core.config.api import APIConfig | ||
|
||
app = FastAPI( | ||
rosa = FastAPI( | ||
title=APIConfig.TITLE, | ||
version=APIConfig.VERSION, | ||
description=APIConfig.DESCRIPTION, | ||
summary=APIConfig.SUMMARY, | ||
description=textwrap.dedent(APIConfig.DESCRIPTION), | ||
default_response_class=ORJSONResponse, | ||
docs_url=f"/{APIConfig.VERSION}/docs", | ||
redoc_url=f"/{APIConfig.VERSION}/redoc", | ||
openapi_url=f"/{APIConfig.VERSION}/openapi.json", | ||
root_path=f"/{APIConfig.VERSION}", | ||
redirect_slashes=True, | ||
) | ||
|
||
app.add_middleware( | ||
rosa.add_middleware( | ||
middleware_class=CORSMiddleware, | ||
allow_origins=APIConfig.CORS_ORIGINS, | ||
) | ||
|
||
|
||
@app.get( | ||
f"/{APIConfig.VERSION}/", | ||
@rosa.get( | ||
"/", | ||
status_code=status.HTTP_200_OK, | ||
response_class=ORJSONResponse, | ||
) | ||
def home(request: Request) -> ORJSONResponse: | ||
def home() -> ORJSONResponse: | ||
"""Home route.""" | ||
return ORJSONResponse(content={"content": "successful response."}) | ||
|
||
|
||
from src.cms.api import article, author, category | ||
|
||
rosa.include_router(router=article) | ||
rosa.include_router(router=author) | ||
rosa.include_router(router=category) |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .user import User |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
"""User model.""" | ||
|
||
from sqlalchemy import ForeignKey | ||
from sqlalchemy.orm import Mapped, mapped_column | ||
from sqlalchemy.types import INTEGER, TEXT | ||
from src.core.database.db import Base | ||
|
||
|
||
class User(Base): | ||
"""User schema.""" | ||
|
||
__tablename__: str = "user" | ||
|
||
id: Mapped[int] = mapped_column( | ||
name="id", | ||
primary_key=True, | ||
autoincrement="auto", | ||
type_=INTEGER, | ||
) | ||
name: Mapped[str] = mapped_column( | ||
name="username", | ||
type_=TEXT, | ||
nullable=False, | ||
unique=True, | ||
) | ||
|
||
email: Mapped[str] = mapped_column( | ||
name="email", | ||
type_=TEXT, | ||
nullable=False, | ||
unique=True, | ||
) | ||
|
||
is_superuser: Mapped[bool] = mapped_column(default=False) | ||
|
||
password_hash: Mapped[str] = mapped_column( | ||
name="password_hash", | ||
type_=TEXT, | ||
nullable=False, | ||
) | ||
|
||
published_article_id: Mapped[int] = mapped_column( | ||
ForeignKey("article.id"), | ||
type_=INTEGER, | ||
nullable=True, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
"""API routes.""" | ||
|
||
from .article import article | ||
from .author import author | ||
from .category import category | ||
|
||
__all__: list[str] = [ | ||
"article", | ||
"author", | ||
"category", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
"""Article routes.""" | ||
|
||
from fastapi import APIRouter, Query, status | ||
from fastapi.responses import ORJSONResponse | ||
from src.cms.services.articles import fetch_latest_articles_from_db | ||
from src.core.config.api import ArticleConfig | ||
|
||
article = APIRouter( | ||
prefix="/article", | ||
tags=["article"], | ||
default_response_class=ORJSONResponse, | ||
) | ||
|
||
|
||
@article.get( | ||
path="/", | ||
response_class=ORJSONResponse, | ||
tags=["article"], | ||
summary="List all articles in reverse chronological order.", | ||
description="Get the list of all articles ordered in reverse chronological order.", | ||
deprecated=False, | ||
name="Article", | ||
status_code=status.HTTP_200_OK, | ||
) | ||
def fetch_articles( | ||
fetch_count: int = Query( | ||
default=ArticleConfig.DEFAULT_FETCHABLE_ARTICLES, | ||
alias="fetch_count", | ||
le=ArticleConfig.MAX_FETCHABLE_ARTICLES, | ||
ge=ArticleConfig.MIN_FETCHABLE_ARTICLES, | ||
), | ||
) -> ORJSONResponse: | ||
""" | ||
Fetch articles and return. | ||
Parameters | ||
---------- | ||
fetch_count : int, optional | ||
Number of articles to fetch, by default 10. | ||
Returns | ||
------- | ||
ORJSONResponse | ||
Returns list of articles in reverse chronological order. | ||
""" | ||
if fetch_count > ArticleConfig.MAX_FETCHABLE_ARTICLES: | ||
fetch_count = ArticleConfig.MAX_FETCHABLE_ARTICLES | ||
elif fetch_count < ArticleConfig.MIN_FETCHABLE_ARTICLES: | ||
fetch_count = ArticleConfig.MIN_FETCHABLE_ARTICLES | ||
|
||
articles = fetch_latest_articles_from_db(n=fetch_count) | ||
return ORJSONResponse(content=articles) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
"""Author routes.""" | ||
|
||
from fastapi import APIRouter, Query, status | ||
from fastapi.responses import ORJSONResponse | ||
from src.cms.services.authors import fetch_articles_by_author, fetch_authors_from_db | ||
from src.core.config.api import ArticleConfig | ||
|
||
author = APIRouter( | ||
prefix="/author", | ||
tags=["author"], | ||
default_response_class=ORJSONResponse, | ||
) | ||
|
||
|
||
@author.get( | ||
path="/", | ||
response_class=ORJSONResponse, | ||
tags=["author"], | ||
summary="List all published authors.", | ||
description="List all published authors in the alphabetic order of their first name", | ||
deprecated=False, | ||
name="Author", | ||
status_code=status.HTTP_200_OK, | ||
) | ||
def fetch_authors( | ||
fetch_count: int = Query( | ||
default=ArticleConfig.DEFAULT_FETCHABLE_ARTICLES, | ||
alias="fetch_count", | ||
le=ArticleConfig.MAX_FETCHABLE_ARTICLES, | ||
ge=ArticleConfig.MIN_FETCHABLE_ARTICLES, | ||
), | ||
) -> ORJSONResponse: | ||
""" | ||
Fetch authors and return. | ||
Parameters | ||
---------- | ||
fetch_count : int, optional | ||
Number of authors to fetch, by default 10. | ||
Returns | ||
------- | ||
ORJSONResponse | ||
Returns list of authors in alphabetical order. | ||
""" | ||
if fetch_count > ArticleConfig.MAX_FETCHABLE_ARTICLES: | ||
fetch_count = ArticleConfig.MAX_FETCHABLE_ARTICLES | ||
elif fetch_count < ArticleConfig.MIN_FETCHABLE_ARTICLES: | ||
fetch_count = ArticleConfig.MIN_FETCHABLE_ARTICLES | ||
|
||
authors = fetch_authors_from_db() | ||
return ORJSONResponse(content=authors) | ||
|
||
|
||
@author.get( | ||
path="/{author_slug}/", | ||
response_class=ORJSONResponse, | ||
tags=["author", "article"], | ||
summary="List all articles in reverse chronological order.", | ||
description="Get the list of all articles ordered in reverse chronological order.", | ||
deprecated=False, | ||
name="Category-wise articles", | ||
status_code=status.HTTP_200_OK, | ||
) | ||
def fetch_articles(author_slug: str) -> ORJSONResponse: | ||
""" | ||
Fetch articles by author and return. | ||
Parameters | ||
---------- | ||
fetch_count : int, optional | ||
Number of articles to fetch, by default 10. | ||
Returns | ||
------- | ||
ORJSONResponse | ||
Returns list of articles in reverse chronological order. | ||
""" | ||
articles = fetch_articles_by_author(author_slug=author_slug) | ||
return ORJSONResponse(content=articles) |
Oops, something went wrong.