feat: Implement user validation and ownership checks for image, reward, and task APIs
All checks were successful
Gitea Actions Demo / build-and-push (push) Successful in 36s
All checks were successful
Gitea Actions Demo / build-and-push (push) Successful in 36s
- Added `get_validated_user_id` utility function to validate user authentication across multiple APIs. - Updated image upload, request, and listing endpoints to ensure user ownership and proper error handling. - Enhanced reward management endpoints to include user validation and ownership checks. - Modified task management endpoints to enforce user authentication and ownership verification. - Updated models to include `user_id` for images, rewards, tasks, and children to track ownership. - Implemented frontend changes to ensure UI reflects the ownership of tasks and rewards. - Added a new feature specification to prevent deletion of system tasks and rewards.
This commit is contained in:
@@ -9,6 +9,7 @@ class Child(BaseModel):
|
||||
rewards: list[str] = field(default_factory=list)
|
||||
points: int = 0
|
||||
image_id: str | None = None
|
||||
user_id: str | None = None
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, d: dict):
|
||||
@@ -19,10 +20,10 @@ class Child(BaseModel):
|
||||
rewards=d.get('rewards', []),
|
||||
points=d.get('points', 0),
|
||||
image_id=d.get('image_id'),
|
||||
user_id=d.get('user_id'),
|
||||
id=d.get('id'),
|
||||
created_at=d.get('created_at'),
|
||||
updated_at=d.get('updated_at')
|
||||
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
@@ -33,6 +34,7 @@ class Child(BaseModel):
|
||||
'tasks': self.tasks,
|
||||
'rewards': self.rewards,
|
||||
'points': self.points,
|
||||
'image_id': self.image_id
|
||||
'image_id': self.image_id,
|
||||
'user_id': self.user_id
|
||||
})
|
||||
return base
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
from dataclasses import dataclass
|
||||
from models.base import BaseModel
|
||||
|
||||
|
||||
@dataclass
|
||||
class Image(BaseModel):
|
||||
type: int
|
||||
extension: str
|
||||
permanent: bool = False
|
||||
user: str | None = None
|
||||
user_id: str | None = None
|
||||
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, d: dict):
|
||||
@@ -19,7 +21,7 @@ class Image(BaseModel):
|
||||
id=d.get('id'),
|
||||
created_at=d.get('created_at'),
|
||||
updated_at=d.get('updated_at'),
|
||||
user=d.get('user')
|
||||
user_id=d.get('user_id') if 'user_id' in d else d.get('user')
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
@@ -28,6 +30,6 @@ class Image(BaseModel):
|
||||
'type': self.type,
|
||||
'permanent': self.permanent,
|
||||
'extension': self.extension,
|
||||
'user': self.user
|
||||
'user_id': self.user_id
|
||||
})
|
||||
return base
|
||||
|
||||
@@ -5,6 +5,7 @@ from models.base import BaseModel
|
||||
class PendingReward(BaseModel):
|
||||
child_id: str
|
||||
reward_id: str
|
||||
user_id: str
|
||||
status: str = "pending" # pending, approved, rejected
|
||||
|
||||
@classmethod
|
||||
@@ -13,6 +14,7 @@ class PendingReward(BaseModel):
|
||||
child_id=d.get('child_id'),
|
||||
reward_id=d.get('reward_id'),
|
||||
status=d.get('status', 'pending'),
|
||||
user_id=d.get('user_id'),
|
||||
id=d.get('id'),
|
||||
created_at=d.get('created_at'),
|
||||
updated_at=d.get('updated_at')
|
||||
@@ -23,6 +25,7 @@ class PendingReward(BaseModel):
|
||||
base.update({
|
||||
'child_id': self.child_id,
|
||||
'reward_id': self.reward_id,
|
||||
'status': self.status
|
||||
'status': self.status,
|
||||
'user_id': self.user_id
|
||||
})
|
||||
return base
|
||||
|
||||
@@ -8,6 +8,7 @@ class Reward(BaseModel):
|
||||
description: str
|
||||
cost: int
|
||||
image_id: str | None = None
|
||||
user_id: str | None = None
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, d: dict):
|
||||
@@ -17,6 +18,7 @@ class Reward(BaseModel):
|
||||
description=d.get('description'),
|
||||
cost=d.get('cost', 0),
|
||||
image_id=d.get('image_id'),
|
||||
user_id=d.get('user_id'),
|
||||
id=d.get('id'),
|
||||
created_at=d.get('created_at'),
|
||||
updated_at=d.get('updated_at')
|
||||
@@ -28,6 +30,7 @@ class Reward(BaseModel):
|
||||
'name': self.name,
|
||||
'description': self.description,
|
||||
'cost': self.cost,
|
||||
'image_id': self.image_id
|
||||
'image_id': self.image_id,
|
||||
'user_id': self.user_id
|
||||
})
|
||||
return base
|
||||
|
||||
@@ -7,6 +7,7 @@ class Task(BaseModel):
|
||||
points: int
|
||||
is_good: bool
|
||||
image_id: str | None = None
|
||||
user_id: str | None = None
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, d: dict):
|
||||
@@ -15,17 +16,19 @@ class Task(BaseModel):
|
||||
points=d.get('points', 0),
|
||||
is_good=d.get('is_good', True),
|
||||
image_id=d.get('image_id'),
|
||||
user_id=d.get('user_id'),
|
||||
id=d.get('id'),
|
||||
created_at=d.get('created_at'),
|
||||
updated_at=d.get('updated_at')
|
||||
)
|
||||
|
||||
|
||||
def to_dict(self):
|
||||
base = super().to_dict()
|
||||
base.update({
|
||||
'name': self.name,
|
||||
'points': self.points,
|
||||
'is_good': self.is_good,
|
||||
'image_id': self.image_id
|
||||
'image_id': self.image_id,
|
||||
'user_id': self.user_id
|
||||
})
|
||||
return base
|
||||
|
||||
Reference in New Issue
Block a user