<commit_before>import json
from collections import namedtuple
from corehq.apps.accounting.utils import domain_has_privilege
from corehq.apps.api.resources import HqBaseResource
from corehq.apps.api.resources.v0_1 import RequirePermissionAuthentication
from corehq.apps.app_manager.dbaccessors import get_app
from corehq.apps.domain.models import Domain
from corehq.apps.sms.mixin import (CommCareMobileContactMixin, apply_leniency,
    InvalidFormatException)
from corehq.apps.sms.models import SelfRegistrationInvitation
from corehq.apps.users.models import Permissions
from corehq import privileges
from django.http import HttpResponse, Http404
from tastypie.exceptions import ImmediateHttpResponse
from tastypie.validation import Validation


FieldDefinition = namedtuple('FieldDefinition', 'name required type')


class SelfRegistrationApiException(Exception):
    pass


class SelfRegistrationValidationException(Exception):
    def __init__(self, errors):
        self.errors = errors
        super(SelfRegistrationValidationException, self).__init__('')


class SelfRegistrationUserInfo(object):
    def __init__(self, phone_number, custom_user_data=None):
        self.phone_number = phone_number
        self.custom_user_data = custom_user_data


class SelfRegistrationInfo(object):
    def __init__(self, app_id, android_only=False, require_email=False, custom_registration_message=None):
        self.app_id = app_id
        self.android_only = android_only
        self.require_email = require_email
        self.custom_registration_message = custom_registration_message
        self.users = []

    def add_user(self, user_info):
        """
        :param user_info: should be an instance of SelfRegistrationUserInfo
        """
        self.users.append(user_info)


class UserSelfRegistrationValidation(Validation):

    def _validate_toplevel_fields(self, data, field_defs):
        """
        :param data: any dictionary of data
        :param field_defs: a list of FieldDefinition namedtuples representing the names
        and types of the fields to validate
        """
        for field_def in field_defs:
            if field_def.name not in data and field_def.required:
                raise SelfRegistrationValidationException(
                    {field_def.name: 'This field is required'}
                )

            if field_def.name in data:
                if not isinstance(data[field_def.name], field_def.type):
                    raise SelfRegistrationValidationException(
                        {field_def.name: 'Expected type: {}'.format(field_def.type.__name__)}
                    )

    def _validate_app_id(self, domain, app_id):
        try:
            get_app(domain, app_id, latest=True)
        except Http404:
            raise SelfRegistrationValidationException({'app_id': 'Invalid app_id specified'})

    def _validate_users(self, user_data):
        phone_numbers = set()
        for user_info in user_data:
            if not isinstance(user_info, dict):
                raise SelfRegistrationValidationException(
                    {'users': 'Expected a list of dictionaries'}
                )

            self._validate_toplevel_fields(user_info, [
                FieldDefinition('phone_number', True, basestring),
                FieldDefinition('custom_user_data', False, dict),
            ])

            phone_number = user_info['phone_number']
            if phone_number in phone_numbers:
                raise SelfRegistrationValidationException(
                    {'users': 'phone_number cannot be reused within a request: {}'.format(phone_number)}
                )
            phone_numbers.add(phone_number)

    def is_valid(self, bundle, request=None):
        if not request:
            raise SelfRegistrationApiException('Expected request to be present')

        try:
            self._validate_toplevel_fields(bundle.data, [
                FieldDefinition('app_id', True, basestring),
                FieldDefinition('users', True, list),
                FieldDefinition('android_only', False, bool),
                FieldDefinition('require_email', False, bool),
                FieldDefinition('custom_registration_message', False, basestring),
            ])

            self._validate_app_id(request.domain, bundle.data['app_id'])
            self._validate_users(bundle.data['users'])
        except SelfRegistrationValidationException as e:
            return e.errors

        return {}


class UserSelfRegistrationResource(HqBaseResource):<commit_msg>Use apply_leniency when comparing phone numbers<commit_after>import json
from collections import namedtuple
from corehq.apps.accounting.utils import domain_has_privilege
from corehq.apps.api.resources import HqBaseResource
from corehq.apps.api.resources.v0_1 import RequirePermissionAuthentication
from corehq.apps.app_manager.dbaccessors import get_app
from corehq.apps.domain.models import Domain
from corehq.apps.sms.mixin import (CommCareMobileContactMixin, apply_leniency,
    InvalidFormatException)
from corehq.apps.sms.models import SelfRegistrationInvitation
from corehq.apps.users.models import Permissions
from corehq import privileges
from django.http import HttpResponse, Http404
from tastypie.exceptions import ImmediateHttpResponse
from tastypie.validation import Validation


FieldDefinition = namedtuple('FieldDefinition', 'name required type')


class SelfRegistrationApiException(Exception):
    pass


class SelfRegistrationValidationException(Exception):
    def __init__(self, errors):
        self.errors = errors
        super(SelfRegistrationValidationException, self).__init__('')


class SelfRegistrationUserInfo(object):
    def __init__(self, phone_number, custom_user_data=None):
        self.phone_number = phone_number
        self.custom_user_data = custom_user_data


class SelfRegistrationInfo(object):
    def __init__(self, app_id, android_only=False, require_email=False, custom_registration_message=None):
        self.app_id = app_id
        self.android_only = android_only
        self.require_email = require_email
        self.custom_registration_message = custom_registration_message
        self.users = []

    def add_user(self, user_info):
        """
        :param user_info: should be an instance of SelfRegistrationUserInfo
        """
        self.users.append(user_info)


class UserSelfRegistrationValidation(Validation):

    def _validate_toplevel_fields(self, data, field_defs):
        """
        :param data: any dictionary of data
        :param field_defs: a list of FieldDefinition namedtuples representing the names
        and types of the fields to validate
        """
        for field_def in field_defs:
            if field_def.name not in data and field_def.required:
                raise SelfRegistrationValidationException(
                    {field_def.name: 'This field is required'}
                )

            if field_def.name in data:
                if not isinstance(data[field_def.name], field_def.type):
                    raise SelfRegistrationValidationException(
                        {field_def.name: 'Expected type: {}'.format(field_def.type.__name__)}
                    )

    def _validate_app_id(self, domain, app_id):
        try:
            get_app(domain, app_id, latest=True)
        except Http404:
            raise SelfRegistrationValidationException({'app_id': 'Invalid app_id specified'})

    def _validate_users(self, user_data):
        phone_numbers = set()
        for user_info in user_data:
            if not isinstance(user_info, dict):
                raise SelfRegistrationValidationException(
                    {'users': 'Expected a list of dictionaries'}
                )

            self._validate_toplevel_fields(user_info, [
                FieldDefinition('phone_number', True, basestring),
                FieldDefinition('custom_user_data', False, dict),
            ])

            phone_number = apply_leniency(user_info['phone_number'])
            if phone_number in phone_numbers:
                raise SelfRegistrationValidationException(
                    {'users': 'phone_number cannot be reused within a request: {}'.format(phone_number)}
                )
            phone_numbers.add(phone_number)

    def is_valid(self, bundle, request=None):
        if not request:
            raise SelfRegistrationApiException('Expected request to be present')

        try:
            self._validate_toplevel_fields(bundle.data, [
                FieldDefinition('app_id', True, basestring),
                FieldDefinition('users', True, list),
                FieldDefinition('android_only', False, bool),
                FieldDefinition('require_email', False, bool),
                FieldDefinition('custom_registration_message', False, basestring),
            ])

            self._validate_app_id(request.domain, bundle.data['app_id'])
            self._validate_users(bundle.data['users'])
        except SelfRegistrationValidationException as e:
            return e.errors

        return {}


class UserSelfRegistrationResource(HqBaseResource):
{'fraction_non_alphanumeric': 0.07438197330999781, 'fraction_numerical': 0.0017501640778823015, 'mean_word_length': 2.8578059071729958, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6592116', 'n_tokens_mistral': 2396, 'n_tokens_neox': 2281, 'n_words': 560}