import logging
from flask import Blueprint, redirect, make_response
from tinydb import Query
from utils.digest_token import validate_and_consume_token, validate_unsubscribe_token
from db.db import users_db
from api.child_action_helpers import approve_chore, reject_chore, approve_reward_request, deny_reward
digest_action_api = Blueprint('digest_action_api', __name__)
logger = logging.getLogger(__name__)
_ERROR_HTML = """
Link Error
This link is invalid or has expired.
Action links expire after 24 hours and can only be used once.
"""
_UNSUB_HTML = """
Unsubscribed
You have been unsubscribed from daily digest emails.
To re-enable, visit your profile in the app.
"""
_UNSUB_ERROR_HTML = """
Link Error
This unsubscribe link is invalid or has expired.
"""
@digest_action_api.route('/digest-action/', methods=['GET'])
def handle_digest_action(token_id: str):
"""
Validate a digest action token and execute the corresponding action.
On success: 302 redirect to the ParentView deep link.
On failure: 400 HTML error page.
"""
from flask import current_app
frontend_url = current_app.config.get('FRONTEND_URL', 'https://localhost:5173')
token = validate_and_consume_token(token_id)
if not token:
return make_response(_ERROR_HTML, 400)
user_id = token.user_id
child_id = token.child_id
entity_id = token.entity_id
entity_type = token.entity_type
action = token.action
try:
if entity_type == 'chore' and action == 'approve':
approve_chore(user_id, child_id, entity_id)
elif entity_type == 'chore' and action == 'deny':
reject_chore(user_id, child_id, entity_id)
elif entity_type == 'reward' and action == 'approve':
approve_reward_request(user_id, child_id, entity_id)
elif entity_type == 'reward' and action == 'deny':
deny_reward(user_id, child_id, entity_id)
else:
return make_response(_ERROR_HTML, 400)
except Exception as e:
logger.error(f'Error executing digest action {action}/{entity_type}: {e}')
return make_response(_ERROR_HTML, 400)
deep_link = (
f"{frontend_url}/parent/{child_id}"
f"?scrollTo={entity_id}&entityType={entity_type}"
)
return redirect(deep_link, 302)
@digest_action_api.route('/digest-unsubscribe/', methods=['GET'])
def handle_digest_unsubscribe(token: str):
user_id = validate_unsubscribe_token(token)
if not user_id:
return make_response(_UNSUB_ERROR_HTML, 400)
UserQ = Query()
users_db.update({'email_digest_enabled': False}, UserQ.id == user_id)
logger.info(f'User {user_id} unsubscribed from digest via email link')
return make_response(_UNSUB_HTML, 200)