Skip to content

Commit 74777b7

Browse files
committed
two changes this commit: update sqlalchemy to conform better to sqlalchemy 2.0 and add project update (untested) capabilities
1 parent 5f763c0 commit 74777b7

File tree

3 files changed

+57
-33
lines changed

3 files changed

+57
-33
lines changed

api/auth/main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ async def is_user_authenticated(request: Request) -> dict:
184184
):
185185
raise HTTPException(status_code=401)
186186
# TODO: add email verification implementation once postgres is set up
187+
# i think the above is checking that the user is still valid
187188
except Exception as e:
188189
raise HTTPException(status_code=401) from e
189190
return decoded_jwt

api/projects/main.py

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import sqlalchemy
99
from fastapi import APIRouter, Depends, HTTPException, Request
1010
from pydantic import BaseModel
11+
from typing import Optional, Any, List
1112
from sqlalchemy.ext.asyncio import AsyncSession
1213
from sqlalchemy.orm import selectinload
1314

@@ -21,6 +22,15 @@ class CreateProjectRequest(BaseModel):
2122

2223
project_name: str
2324

25+
class updateProjectRequest(BaseModel):
26+
"Update project request from client"
27+
28+
project_id: int
29+
project_name: Optional[str] = None
30+
hackatime_projects: Optional[List[str]] = None
31+
32+
class Config:
33+
extra = "forbid"
2434

2535
router = APIRouter()
2636

@@ -29,10 +39,40 @@ class CreateProjectRequest(BaseModel):
2939

3040

3141
# @protect
32-
async def update_project():
42+
@router.post("/api/projects/update")
43+
async def update_project(
44+
request: Request,
45+
project_request: updateProjectRequest,
46+
session: AsyncSession = Depends(get_db)
47+
):
3348
"""Update project details"""
34-
# TODO: implement update project functionality
3549

50+
user_email = request.state.user["sub"]
51+
52+
project_raw = await session.execute(
53+
sqlalchemy.select(UserProject).where(
54+
UserProject.id == project_request.project_id,
55+
UserProject.user_email == user_email
56+
)
57+
58+
)
59+
60+
project = project_raw.scalar_one_or_none()
61+
62+
if project is None:
63+
raise HTTPException(
64+
status_code=500
65+
) # if you get this good on you lmao
66+
67+
update_data = project_request.model_dump(exclude_unset=True, exclude={"project_id"})
68+
69+
for field, value in update_data.items():
70+
setattr(project, field, value)
71+
72+
await session.commit()
73+
await session.refresh(project)
74+
75+
return {"success": True}
3676

3777
@router.get("/api/projects")
3878
@require_auth
@@ -77,26 +117,11 @@ async def create_project(
77117
user_email=user_email,
78118
hackatime_projects=[],
79119
hackatime_total_hours=0.0,
80-
last_updated=datetime.datetime.now(datetime.timezone.utc),
120+
# last_updated=datetime.datetime.now(datetime.timezone.utc), this should no longer need manual setting
81121
)
82122

83123
session.add(new_project)
84124
await session.commit()
85125
await session.refresh(new_project)
86126

87127
return {"success": True}
88-
89-
90-
# async def run():
91-
# conn = await asyncpg.connect(user='user', password='password',
92-
# database='database', host='127.0.0.1')
93-
# values = await conn.fetch(
94-
# 'SELECT * FROM mytable WHERE id = $1',
95-
# 10,
96-
# )
97-
# await conn.close()
98-
99-
# asyncio.run(run())
100-
101-
# def foo():
102-
# return "abc"

models/user.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
SmallInteger,
1414
String,
1515
)
16-
from sqlalchemy.orm import declarative_base, relationship
16+
from sqlalchemy.orm import declarative_base, relationship, Mapped, MappedColumn
1717

1818
Base = declarative_base()
1919

@@ -23,10 +23,10 @@ class User(Base):
2323

2424
__tablename__ = "users"
2525

26-
id = Column(Integer, autoincrement=True, primary_key=True, unique=True)
27-
email = Column(String, nullable=False, unique=True)
28-
permissions = Column(ARRAY(SmallInteger), nullable=False, server_default="{}")
29-
projects = relationship(
26+
id: Mapped[int] = MappedColumn(Integer, autoincrement=True, primary_key=True, unique=True)
27+
email: Mapped[str] = MappedColumn(String, nullable=False, unique=True)
28+
permissions: Mapped[list[int]] = MappedColumn(ARRAY(SmallInteger), nullable=False, server_default="{}")
29+
projects: Mapped[list["UserProject"]] = relationship(
3030
"UserProject", back_populates="user", cascade="all, delete-orphan"
3131
)
3232

@@ -36,20 +36,18 @@ class UserProject(Base):
3636

3737
__tablename__ = "projects"
3838

39-
id = Column(Integer, primary_key=True, autoincrement=True)
40-
name = Column(String, nullable=False)
41-
user_email = Column(String, ForeignKey("users.email"), nullable=False)
42-
hackatime_projects = Column(JSON, nullable=False, default=list)
43-
hackatime_total_hours = Column(Float, nullable=False, default=0.0)
44-
last_updated = Column(
39+
id: Mapped[int] = MappedColumn(Integer, primary_key=True, autoincrement=True)
40+
name: Mapped[str] = MappedColumn(String, nullable=False)
41+
user_email: Mapped[str] = MappedColumn(String, ForeignKey("users.email"), nullable=False)
42+
hackatime_projects: Mapped[list[str]] = MappedColumn(JSON, nullable=False, default=list)
43+
hackatime_total_hours: Mapped[float] = MappedColumn(Float, nullable=False, default=0.0)
44+
last_updated: Mapped[DateTime] = MappedColumn(
4545
DateTime(timezone=True),
4646
nullable=False,
4747
default=lambda: datetime.now(timezone.utc),
48+
onupdate=lambda: datetime.now(timezone.utc),
4849
)
4950

5051
# Relationship back to user
51-
user = relationship("User", back_populates="projects")
52+
user: Mapped["User"] = relationship("User", back_populates="projects")
5253

53-
54-
# class UserProject(Base):
55-
# id = Column(String, primary_key=True)

0 commit comments

Comments
 (0)