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

- 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:
2026-01-31 19:48:51 -05:00
parent 6f5b61de7f
commit f14de28daa
18 changed files with 361 additions and 121 deletions

View File

@@ -48,6 +48,7 @@ function handleRewardTriggered(event: Event) {
const payload = event.payload as ChildRewardTriggeredEventPayload
if (child.value && payload.child_id == child.value.id) {
child.value.points = payload.points
childRewardListRef.value?.refresh()
}
}

View File

@@ -113,6 +113,7 @@ function onAddImage({ id, file }: { id: string; file: File }) {
async function updateAvatar(imageId: string) {
errorMsg.value = ''
successMsg.value = ''
//todo update avatar loading state
try {
const res = await fetch('/api/user/avatar', {
method: 'PUT',
@@ -123,7 +124,9 @@ async function updateAvatar(imageId: string) {
initialData.value.image_id = imageId
successMsg.value = 'Avatar updated!'
} catch {
errorMsg.value = 'Failed to update avatar.'
//errorMsg.value = 'Failed to update avatar.'
//todo update avatar error handling
errorMsg.value = ''
}
}

View File

@@ -2,7 +2,12 @@
import { ref, nextTick, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { eventBus } from '@/common/eventBus'
import { authenticateParent, isParentAuthenticated, logoutParent } from '../../stores/auth'
import {
authenticateParent,
isParentAuthenticated,
logoutParent,
logoutUser,
} from '../../stores/auth'
import '@/assets/styles.css'
import '@/assets/colors.css'
import ModalDialog from './ModalDialog.vue'
@@ -91,7 +96,7 @@ function closeDropdown() {
async function signOut() {
try {
await fetch('/api/logout', { method: 'POST' })
logoutParent()
logoutUser()
router.push('/auth')
} catch {
// Optionally show error

View File

@@ -24,6 +24,8 @@ export function loginUser() {
export function logoutUser() {
isUserLoggedIn.value = false
currentUserId.value = ''
logoutParent()
}
export async function checkAuth() {