Skip to content

Commit

Permalink
Merge pull request #74 from PCS-Poli-USP/develop
Browse files Browse the repository at this point in the history
Deploy Forum: search bar and general forum
  • Loading branch information
VitorMakiyama authored Nov 26, 2024
2 parents 19077dc + da5a932 commit d342480
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 49 deletions.
29 changes: 0 additions & 29 deletions .github/workflows/ci_cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,6 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3

# - name: Check Alembic Migration Version
# id: alembicChecker
# uses: DevGlitch/[email protected]
# with:
# db_url: ${{ secrets.DB_URL }}
# migrations_path: ./migrations/

# - name: check Alembic migration
# id: alembicChecker
# uses: appleboy/[email protected]
# with:
# host: ${{ secrets.SSH_HOST }}
# username: ${{ secrets.SSH_USER }}
# password: ${{ secrets.SSH_PASSCODE }}
# port: ${{ secrets.SSH_PORT }}
# script: |
# cd /diskb/home/backend
# git pull origin develop
# . /diskb/home/backend/.venv/bin/activate
# alembic heads > heads_output.txt
# alembic current > current_output.txt
# if cmp -s heads_output.txt current_output.txt; then
# echo "No new migrations to apply."
# echo "new_migrations=false" >> $GITHUB_ENV
# else
# echo "New migrations found."
# echo "new_migrations=true" >> $GITHUB_ENV
# fi


- name: executing remote ssh commands using password
uses: appleboy/[email protected]
Expand Down
35 changes: 35 additions & 0 deletions migrations/versions/64a70f848243_forum_global.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""forum_global
Revision ID: 64a70f848243
Revises: 49bd2f582a5a
Create Date: 2024-11-21 22:36:19.346377
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
import sqlmodel


# revision identifiers, used by Alembic.
revision: str = '64a70f848243'
down_revision: Union[str, None] = '49bd2f582a5a'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('forumpost', 'class_id',
existing_type=sa.INTEGER(),
nullable=True)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('forumpost', 'class_id',
existing_type=sa.INTEGER(),
nullable=False)
# ### end Alembic commands ###
2 changes: 1 addition & 1 deletion server/exception_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ async def handle_google_auth_error(request, exc: GoogleAuthError) -> JSONRespons
def add_exception_handlers(app: FastAPI) -> None:
app.add_exception_handler(IntegrityError, handle_integrity_error) # type: ignore [arg-type]
app.add_exception_handler(NoResultFound, handle_no_result_found) # type: ignore [arg-type]
app.add_exception_handler(GoogleAuthError, handle_google_auth_error)
app.add_exception_handler(GoogleAuthError, handle_google_auth_error) # type: ignore [arg-type]
5 changes: 3 additions & 2 deletions server/models/database/forum_db_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
class ForumPost(SQLModel, table=True):
id: int = Field(default=None, primary_key=True)

class_id: int = Field(
foreign_key="class.id"
class_id: int | None = Field(
foreign_key="class.id",
nullable=True
)

subject_id : int = Field(
Expand Down
4 changes: 2 additions & 2 deletions server/models/http/requests/forum_request_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class ForumPostRegister(BaseModel):
user_id: int
content: str
class_id: int
class_id: int | None = None
subject_id: int
filter_tags: list[int] | None = None

Expand Down Expand Up @@ -42,4 +42,4 @@ class ForumPostLike(BaseModel):
like_state: bool

class ForumUserLikesRegister(BaseModel):
user_id: int
user_id: int
6 changes: 3 additions & 3 deletions server/models/http/responses/forum_post_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ForumPostResponse(BaseModel):
user_id: int
user_name: str
content : str | None
class_id : int
class_id : int | None
subject_id: int
created_at : datetime
replies_count: int
Expand Down Expand Up @@ -40,7 +40,7 @@ class ForumPostReplyResponse(ForumPostResponse):
reply_of_post_id: int | None

@classmethod
def from_forum_reply(cls, reply: ForumPost, mobile_user_id: int, session: Session) -> "ForumPostReplyResponse":
def from_forum_reply(cls, reply: ForumPost, mobile_user_id: int | None, session: Session) -> "ForumPostReplyResponse":

return cls(
id = reply.id,
Expand All @@ -57,5 +57,5 @@ def from_forum_reply(cls, reply: ForumPost, mobile_user_id: int, session: Sessio
)

@classmethod
def from_forum_post_reply_list(cls, replies: list[ForumPost], mobile_user_id: int, session: Session) -> list["ForumPostReplyResponse"]:
def from_forum_post_reply_list(cls, replies: list[ForumPost], mobile_user_id: int | None, session: Session) -> list["ForumPostReplyResponse"]:
return [cls.from_forum_reply(reply, mobile_user_id, session) for reply in replies]
12 changes: 10 additions & 2 deletions server/repositories/forum_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,29 @@ def get_post_like_reaction(mobile_user_id: int | None, post_id: int, session:Ses
return user_liked_this_post

@staticmethod
def get_all_posts(*, subject_id: int, filter_tags: list[int] | None, session: Session) -> list[ForumPost]:
def get_all_posts(*, subject_id: int, filter_tags: list[int] | None, search_keyword: str | None,session: Session) -> list[ForumPost]:
"""Returns all posts matching, ordered by desceding creation date (newer first), the filter_tags criteria as follows:\n
- Each filter tags must be an prime number (e.g.: 2, 3, 5...)
- Multiple filter tags will be the multiplication of corresponding tag numbers: (e.g.: 10 = 2*5 - tags 2 and 5)
- If a post has no filter, its filter_tags will be 1 (not a prime multiplication)
- To search, all posts with ANY filter_tags combination received from the request are going to be returned
- e.g.:filter_tags = [2, 5, 3], from request, means posts with the following filter_tags will be returned: [2, 5, 3, 10, 6, 15, 30]
Return posts filtered by keyword, if it was found in the request
"""
statement = select(ForumPost).where(
col(ForumPost.subject_id)==subject_id,
col(ForumPost.reply_of_post_id)==None,
col(ForumPost.enabled) == True) \
.order_by(col(ForumPost.created_at).desc())

if search_keyword != None:
search_term = f"%{search_keyword}%"
statement = select(ForumPost).where(
col(ForumPost.subject_id)==subject_id,
col(ForumPost.enabled) == True,
ForumPost.content.ilike(search_term)) \
.order_by(col(ForumPost.created_at).desc())

if filter_tags != None:
# if there are filter tags, use them to search
filter_expressions = []
Expand Down Expand Up @@ -181,7 +190,6 @@ def change_forum_post_like(

return post


class PostNotFoundException(HTTPException):
def __init__(self, post_id: int) -> None:
super().__init__(
Expand Down
31 changes: 28 additions & 3 deletions server/repositories/subject_repository.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from ast import Sub
from datetime import date
from fastapi import HTTPException, status
from sqlalchemy.exc import IntegrityError, NoResultFound
from sqlalchemy.exc import NoResultFound
from sqlmodel import Session, col, select

from server.deps.authenticate import BuildingDep
from server.deps.session_dep import SessionDep
from server.models.database.subject_building_link import SubjectBuildingLink
from server.models.database.subject_db_model import Subject
from server.models.http.requests.subject_request_models import (
Expand All @@ -14,6 +13,7 @@
from server.repositories.building_repository import BuildingRepository
from server.repositories.calendar_repository import CalendarRepository
from server.services.jupiter_crawler.crawler import JupiterCrawler
from server.utils.enums.subject_type import SubjectType


class SubjectRepository:
Expand Down Expand Up @@ -145,6 +145,31 @@ def delete(*, id: int, session: Session) -> None:
session.delete(subject)
session.commit()

@staticmethod
def create_general_forum(*,id: int, name: str, session: Session) -> Subject:
new_subject = Subject(
id=id,
name=name,
code="",
professors=[],
type= SubjectType.OTHER,
work_credit=0,
class_credit=0,
activation=date.today(),
)
session.add(new_subject)
session.commit()
session.refresh(new_subject)
return new_subject

@staticmethod
def get_by_name(*, name: str, session: Session) -> Subject:
statement = select(Subject).where(Subject.name == name)
try:
subject = session.exec(statement).one()
return subject
except NoResultFound:
raise SubjectNotFound()

class SubjectNotFound(HTTPException):
def __init__(self) -> None:
Expand Down
28 changes: 21 additions & 7 deletions server/routes/public/forum_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from server.deps.session_dep import SessionDep
from server.models.database.forum_db_model import ForumPost
from server.models.database.subject_db_model import Subject
from server.models.http.requests.forum_request_models import (
ForumPostRegister,
to_forumpost_model,
Expand All @@ -16,6 +17,7 @@
ForumPostResponse,
)
from server.repositories.forum_repository import ForumRepository
from server.repositories.subject_repository import SubjectNotFound, SubjectRepository
from server.utils.google_auth_utils import authenticate_with_google
from server.services.gmail_service import gmail_login, gmail_send_message

Expand All @@ -29,26 +31,40 @@ async def get_posts(
session: SessionDep,
subject_id: int,
user_id: int | None = None,
filter_tags: List[int] = Query(None)
) -> list[ForumPostResponse]:
"""Get all posts by tags, also gets all posts reaction information based on the user_id"""
filter_tags: List[int] = Query(None),
search_keyword: str | None = None
) -> list[ForumPostReplyResponse]:
"""Get all posts by tags, also gets all posts reaction information based on the user_id
If a search keyword is present in the request, return posts with that word
"""
posts = ForumRepository.get_all_posts(
subject_id=subject_id,
filter_tags=filter_tags,
search_keyword=search_keyword,
session=session
)

return ForumPostResponse.from_forum_post_list(user_id, posts, session)
return ForumPostReplyResponse.from_forum_post_reply_list(posts, user_id, session)


@router.post("/posts")
async def create_forum_post(
input: ForumPostRegister, session: SessionDep, authorization: str = Header(None),
) -> ForumPostResponse:
"""Create a forum post with provided tags"""
"""Create a forum post with provided tags. The General Forum is associeted with subject_id == -1"""
# authenticate before creating and saving a post
authenticate_with_google(authorization)

if input.subject_id == -1:
globalForumSubject: Subject
try:
globalForumSubject = SubjectRepository.get_by_name(name="Forum Geral", session=session)
except SubjectNotFound:
globalForumSubject = SubjectRepository.create_general_forum(id=input.subject_id, name="Forum Geral", session=session)

input.subject_id = globalForumSubject.id # type: ignore
input.class_id = None

forum_post = ForumRepository.create(
input=to_forumpost_model(input),
session=session
Expand Down Expand Up @@ -139,5 +155,3 @@ async def update_forum_post_like(
like_changed_post = ForumRepository.change_forum_post_like(post_id=post_id, mobile_user_id=input.user_id, like_state=input.like_state ,session=session, )

return like_changed_post


0 comments on commit d342480

Please sign in to comment.