mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			54 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			54 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import logging
 | 
						|
from datetime import timedelta
 | 
						|
 | 
						|
from altcha import ChallengeOptions, create_challenge
 | 
						|
from django.conf import settings
 | 
						|
from django.http import HttpRequest, HttpResponseBase
 | 
						|
from django.utils.timezone import now as timezone_now
 | 
						|
from django.utils.translation import gettext as _
 | 
						|
from pydantic import BaseModel
 | 
						|
 | 
						|
from zerver.lib.exceptions import JsonableError
 | 
						|
from zerver.lib.response import json_success
 | 
						|
from zerver.lib.typed_endpoint import typed_endpoint_without_parameters
 | 
						|
 | 
						|
 | 
						|
class AltchaPayload(BaseModel):
 | 
						|
    algorithm: str
 | 
						|
    challenge: str
 | 
						|
    number: int
 | 
						|
    salt: str
 | 
						|
    signature: str
 | 
						|
 | 
						|
 | 
						|
@typed_endpoint_without_parameters
 | 
						|
def get_challenge(
 | 
						|
    request: HttpRequest,
 | 
						|
) -> HttpResponseBase:
 | 
						|
    if not settings.USING_CAPTCHA or not settings.ALTCHA_HMAC_KEY:  # nocoverage
 | 
						|
        raise JsonableError(_("Challenges are not enabled."))
 | 
						|
 | 
						|
    now = timezone_now()
 | 
						|
    expires = now + timedelta(minutes=1)
 | 
						|
    try:
 | 
						|
        challenge = create_challenge(
 | 
						|
            ChallengeOptions(
 | 
						|
                hmac_key=settings.ALTCHA_HMAC_KEY,
 | 
						|
                max_number=500000,
 | 
						|
                expires=expires,
 | 
						|
            )
 | 
						|
        )
 | 
						|
        session_challenges = request.session.get("altcha_challenges", [])
 | 
						|
        # We prune out expired challenges not for correctness (the
 | 
						|
        # expiration is validated separately) but to prevent this from
 | 
						|
        # growing without bound
 | 
						|
        session_challenges = [(c, e) for (c, e) in session_challenges if e > now.timestamp()]
 | 
						|
        request.session["altcha_challenges"] = [
 | 
						|
            *session_challenges,
 | 
						|
            (challenge.challenge, expires.timestamp()),
 | 
						|
        ]
 | 
						|
        return json_success(request, data=challenge.__dict__)
 | 
						|
    except Exception as e:  # nocoverage
 | 
						|
        logging.exception(e)
 | 
						|
        raise JsonableError(_("Failed to generate challenge"))
 |