<commit_before>from __future__ import absolute_import, unicode_literals, print_function, division

import datetime

from django.contrib.auth import get_user_model
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.utils import timezone
from django.conf import settings

from rest_framework import serializers, fields, validators
from rest_framework_gis import serializers as serializers_gis
from drf_extra_fields.fields import Base64ImageField

from main.api.validators import get_record_validator_for_dataset
from main.constants import MODEL_SRID
from main.models import Program, Project, Site, Dataset, Record, Media, DatasetMedia, ProjectMedia
from main.utils_auth import is_admin
from main.utils_species import get_key_for_value

User = get_user_model()


class UsernameValidator(RegexValidator):
    """
    A username validator that allows `\` (backslash). This is a requirement imposed by NSW OEH.
    By default Django and DRF doesn't allow it.
    """
    regex = r'^[\w.@+-\\]+$'
    message = 'Enter a valid username. This value may contain only letters, numbers, and @/./+/-/_/\ characters.'


class WhoAmISerializer(serializers.ModelSerializer):
    is_admin = serializers.SerializerMethodField()
    is_data_engineer = serializers.SerializerMethodField()

    def get_is_admin(self, user):
        return is_admin(user)

    def get_is_data_engineer(self, user):
        return Program.objects.filter(data_engineers__in=[user.pk]).count() > 0

    class Meta:
        model = User
        fields = ('id', 'username', 'first_name', 'last_name', 'email', 'is_admin', 'is_data_engineer')


class CreateUserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(
        style={'input_type': 'password'},
        write_only=True
    )
    username = fields.CharField(
        max_length=150,
        required=True,
        validators=[
            validators.UniqueValidator(queryset=User.objects.all()),
            UsernameValidator()
        ]
    )

    def validate(self, attrs):
        user = User(**attrs)
        password = attrs.get('password')

        try:
            validate_password(password, user)
        except ValidationError as e:
            raise serializers.ValidationError({'password': list(e.messages)})

        return attrs

    def create(self, validated_data):
        try:
            user = User.objects.create_user(**validated_data)
            # assign new user as custodians of some projects if requested.
            # look for a 'projects' string or list in the post data
            # TODO: Should not create the user but return a 400 error if a requested project is not allowed
            # TODO: use a proper validator
            requested_project_names = self.context['request'].data['projects']
            # compare with the server settings allowed public projects
            allowed_project_names = settings.ALLOWED_PUBLIC_REGISTRATION_PROJECTS
            if allowed_project_names and requested_project_names:
                if not isinstance(requested_project_names, list):
                    requested_project_names = [requested_project_names]
                for project_name in [p for p in requested_project_names if p in allowed_project_names]:
                    project = Project.objects.filter(name=project_name).first()
                    if project is not None:
                        project.custodians.add(user)
            return user
        except Exception as e:
            self.fail('cannot create user: {}'.format(e))

    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'first_name', 'last_name', 'password')<commit_msg>Added guard against missing param<commit_after>from __future__ import absolute_import, unicode_literals, print_function, division

import datetime

from django.contrib.auth import get_user_model
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.utils import timezone
from django.conf import settings

from rest_framework import serializers, fields, validators
from rest_framework_gis import serializers as serializers_gis
from drf_extra_fields.fields import Base64ImageField

from main.api.validators import get_record_validator_for_dataset
from main.constants import MODEL_SRID
from main.models import Program, Project, Site, Dataset, Record, Media, DatasetMedia, ProjectMedia
from main.utils_auth import is_admin
from main.utils_species import get_key_for_value

User = get_user_model()


class UsernameValidator(RegexValidator):
    """
    A username validator that allows `\` (backslash). This is a requirement imposed by NSW OEH.
    By default Django and DRF doesn't allow it.
    """
    regex = r'^[\w.@+-\\]+$'
    message = 'Enter a valid username. This value may contain only letters, numbers, and @/./+/-/_/\ characters.'


class WhoAmISerializer(serializers.ModelSerializer):
    is_admin = serializers.SerializerMethodField()
    is_data_engineer = serializers.SerializerMethodField()

    def get_is_admin(self, user):
        return is_admin(user)

    def get_is_data_engineer(self, user):
        return Program.objects.filter(data_engineers__in=[user.pk]).count() > 0

    class Meta:
        model = User
        fields = ('id', 'username', 'first_name', 'last_name', 'email', 'is_admin', 'is_data_engineer')


class CreateUserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(
        style={'input_type': 'password'},
        write_only=True
    )
    username = fields.CharField(
        max_length=150,
        required=True,
        validators=[
            validators.UniqueValidator(queryset=User.objects.all()),
            UsernameValidator()
        ]
    )

    def validate(self, attrs):
        user = User(**attrs)
        password = attrs.get('password')

        try:
            validate_password(password, user)
        except ValidationError as e:
            raise serializers.ValidationError({'password': list(e.messages)})

        return attrs

    def create(self, validated_data):
        try:
            user = User.objects.create_user(**validated_data)
            # assign new user as custodians of some projects if requested.
            # look for a 'projects' string or list in the post data
            # TODO: Should not create the user but return a 400 error if a requested project is not allowed
            # TODO: use a proper validator
            request_data = self.context['request'].data
            if 'projects' in request_data:
                requested_project_names = request_data['projects']
                # compare with the server settings allowed public projects
                allowed_project_names = settings.ALLOWED_PUBLIC_REGISTRATION_PROJECTS
                if allowed_project_names and requested_project_names:
                    if not isinstance(requested_project_names, list):
                        requested_project_names = [requested_project_names]
                    for project_name in [p for p in requested_project_names if p in allowed_project_names]:
                        project = Project.objects.filter(name=project_name).first()
                        if project is not None:
                            project.custodians.add(user)
            return user
        except Exception as e:
            self.fail('cannot create user: {}'.format(e))

    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'first_name', 'last_name', 'password')
{'fraction_non_alphanumeric': 0.08083948698017877, 'fraction_numerical': 0.002331908278274388, 'mean_word_length': 2.9958592132505175, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '3728020', 'n_tokens_mistral': 2073, 'n_tokens_neox': 1995, 'n_words': 595}