feat: Implement task and reward tracking feature
All checks were successful
Gitea Actions Demo / build-and-push (push) Successful in 24s
All checks were successful
Gitea Actions Demo / build-and-push (push) Successful in 24s
- Added tracking events for tasks, penalties, and rewards with timestamps. - Created new TinyDB table for tracking records to maintain audit history. - Developed backend API for querying tracking events with filters and pagination. - Implemented logging for tracking events with per-user rotating log files. - Added unit tests for tracking event creation, querying, and anonymization. - Deferred frontend changes for future implementation. - Established acceptance criteria and documentation for the tracking feature. feat: Introduce account deletion scheduler - Implemented a scheduler to delete accounts marked for deletion after a configurable threshold. - Added new fields to the User model to manage deletion status and attempts. - Created admin API endpoints for managing deletion thresholds and viewing the deletion queue. - Integrated error handling and logging for the deletion process. - Developed unit tests for the deletion scheduler and related API endpoints. - Documented the deletion process and acceptance criteria.
This commit is contained in:
@@ -15,3 +15,23 @@ export function isEmailValid(email: string): boolean {
|
||||
export function isPasswordStrong(password: string): boolean {
|
||||
return /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]{8,}$/.test(password)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch tracking events for a child with optional filters.
|
||||
*/
|
||||
export async function getTrackingEventsForChild(params: {
|
||||
childId: string
|
||||
entityType?: 'task' | 'reward' | 'penalty'
|
||||
action?: 'activated' | 'requested' | 'redeemed' | 'cancelled'
|
||||
limit?: number
|
||||
offset?: number
|
||||
}): Promise<Response> {
|
||||
const query = new URLSearchParams()
|
||||
query.set('child_id', params.childId)
|
||||
if (params.entityType) query.set('entity_type', params.entityType)
|
||||
if (params.action) query.set('action', params.action)
|
||||
if (params.limit) query.set('limit', params.limit.toString())
|
||||
if (params.offset) query.set('offset', params.offset.toString())
|
||||
|
||||
return fetch(`/api/admin/tracking?${query.toString()}`)
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ export interface Event {
|
||||
| ChildRewardsSetEventPayload
|
||||
| TaskModifiedEventPayload
|
||||
| RewardModifiedEventPayload
|
||||
| TrackingEventCreatedPayload
|
||||
}
|
||||
|
||||
export interface ChildModifiedEventPayload {
|
||||
@@ -135,3 +136,45 @@ export interface RewardModifiedEventPayload {
|
||||
reward_id: string
|
||||
operation: 'ADD' | 'DELETE' | 'EDIT'
|
||||
}
|
||||
|
||||
export interface TrackingEventCreatedPayload {
|
||||
tracking_event_id: string
|
||||
child_id: string
|
||||
entity_type: EntityType
|
||||
action: ActionType
|
||||
}
|
||||
|
||||
export type EntityType = 'task' | 'reward' | 'penalty'
|
||||
export type ActionType = 'activated' | 'requested' | 'redeemed' | 'cancelled'
|
||||
|
||||
export interface TrackingEvent {
|
||||
id: string
|
||||
user_id: string | null
|
||||
child_id: string
|
||||
entity_type: EntityType
|
||||
entity_id: string
|
||||
action: ActionType
|
||||
points_before: number
|
||||
points_after: number
|
||||
delta: number
|
||||
occurred_at: string
|
||||
created_at: number
|
||||
updated_at: number
|
||||
metadata?: Record<string, any> | null
|
||||
}
|
||||
|
||||
export const TRACKING_EVENT_FIELDS = [
|
||||
'id',
|
||||
'user_id',
|
||||
'child_id',
|
||||
'entity_type',
|
||||
'entity_id',
|
||||
'action',
|
||||
'points_before',
|
||||
'points_after',
|
||||
'delta',
|
||||
'occurred_at',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'metadata',
|
||||
] as const
|
||||
|
||||
Reference in New Issue
Block a user