temp update

This commit is contained in:
2024-08-02 07:01:32 +00:00
parent 37a253e63a
commit 9d0d3ea102
5 changed files with 307 additions and 65 deletions

View File

@ -244,3 +244,11 @@ LOGGING = {
}, },
}, },
} }
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
]

View File

@ -3,12 +3,18 @@ from django.conf import settings
from .models import CustomUser from .models import CustomUser
from django.contrib.auth.backends import ModelBackend from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import check_password
import logging
logger = logging.getLogger(__name__)
class EmailOrUsernameModelBackend(ModelBackend): class EmailOrUsernameModelBackend(ModelBackend):
""" """
This is a ModelBacked that allows authentication This is a ModelBacked that allows authentication
with either a username or an email address. with either a username or an email address.
"""
""" """
def authenticate(self, username=None, password=None): def authenticate(self, username=None, password=None):
if '@' in username: if '@' in username:
@ -26,4 +32,35 @@ class EmailOrUsernameModelBackend(ModelBackend):
try: try:
return CustomUser.objects.get(pk=username) return CustomUser.objects.get(pk=username)
except get_user_model().DoesNotExist: except get_user_model().DoesNotExist:
return None return None
"""
def authenticate(self, request, username=None, password=None, **kwargs):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = CustomUser.objects.get(**kwargs)
if check_password(password, user.password):
logger.info(f"User authenticated successfully: {username}")
return user
else:
logger.warning(f"Password mismatch for user: {username}")
except CustomUser.DoesNotExist:
logger.warning(f"User does not exist: {username}")
except Exception as e:
logger.error(f"Authentication error for {username}: {str(e)}")
return None
def get_user(self, user_id):
try:
user = CustomUser.objects.get(pk=user_id)
logger.info(f"User retrieved: {user.username or user.email}")
return user
except CustomUser.DoesNotExist:
logger.warning(f"User with id {user_id} does not exist")
return None
except Exception as e:
logger.error(f"Error retrieving user with id {user_id}: {str(e)}")
return None

View File

@ -1,3 +1,4 @@
from django.contrib.auth.hashers import make_password
from dataclasses import field from dataclasses import field
import email import email
from enum import unique from enum import unique
@ -146,28 +147,28 @@ class JpnAdminMainPerf(models.Model):
# ### # ###
# ### Cities # ### Cities
# ### # ###
# class JpnSubPerf(models.Model): class JpnSubPerf(models.Model):
# geom = models.MultiPolygonField(blank=True, null=True) geom = models.MultiPolygonField(blank=True, null=True)
# adm0_en = models.CharField(max_length=254, blank=True, null=True) adm0_en = models.CharField(max_length=254, blank=True, null=True)
# adm0_ja = models.CharField(max_length=254, blank=True, null=True) adm0_ja = models.CharField(max_length=254, blank=True, null=True)
# adm0_pcode = models.CharField(max_length=254, blank=True, null=True) adm0_pcode = models.CharField(max_length=254, blank=True, null=True)
# adm1_en = models.CharField(max_length=254, blank=True, null=True) adm1_en = models.CharField(max_length=254, blank=True, null=True)
# adm1_ja = models.CharField(max_length=254, blank=True, null=True) adm1_ja = models.CharField(max_length=254, blank=True, null=True)
# adm1_pcode = models.CharField(max_length=254, blank=True, null=True) adm1_pcode = models.CharField(max_length=254, blank=True, null=True)
# adm2_ja = models.CharField(max_length=254, blank=True, null=True) adm2_ja = models.CharField(max_length=254, blank=True, null=True)
# adm2_en = models.CharField(max_length=254, blank=True, null=True) adm2_en = models.CharField(max_length=254, blank=True, null=True)
# adm2_pcode = models.CharField(max_length=254, blank=True, null=True) adm2_pcode = models.CharField(max_length=254, blank=True, null=True)
# name_modified = models.CharField(max_length=254, blank=True, null=True) name_modified = models.CharField(max_length=254, blank=True, null=True)
# area_name = models.CharField(max_length=254, blank=True, null=True) area_name = models.CharField(max_length=254, blank=True, null=True)
# list_order =models.IntegerField(default=0) list_order =models.IntegerField(default=0)
# class Meta: class Meta:
# managed = False managed = False
# db_table = 'jpn_sub_perf' db_table = 'jpn_sub_perf'
# indexes = [ indexes = [
# models.Index(fields=['geom'], name='jpn_sub_perf_geom_idx'), models.Index(fields=['geom'], name='jpn_sub_perf_geom_idx'),
# # Add other fields for indexing as per the requirements # Add other fields for indexing as per the requirements
# ] ]
### ###
### Gifu Areas ### Gifu Areas
@ -234,6 +235,10 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
objects = CustomUserManager() objects = CustomUserManager()
def set_password(self, raw_password):
self.password = make_password(raw_password)
self._password = raw_password
def __str__(self): def __str__(self):
return self.email return self.email
@ -253,6 +258,20 @@ class TempUser(models.Model):
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
expires_at = models.DateTimeField() expires_at = models.DateTimeField()
def set_password(self, raw_password):
self.password = make_password(raw_password)
def check_password(self, raw_password):
return check_password(raw_password, self.password)
# TempUserの作成時にこのメソッドを使用
@classmethod
def create_temp_user(cls, email, password, **kwargs):
temp_user = cls(email=email, **kwargs)
temp_user.set_password(password)
temp_user.save()
return temp_user
def __str__(self): def __str__(self):
return self.email return self.email

View File

@ -1,8 +1,14 @@
from django.contrib.auth.hashers import make_password, check_password
from django.contrib.auth import get_user_model
User = get_user_model()
import uuid import uuid
from django.db import IntegrityError from django.db import IntegrityError
from django.conf import settings from django.conf import settings
from django.urls import reverse from django.urls import reverse
from django.contrib.auth.password_validation import validate_password from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.db import transaction from django.db import transaction
from rest_framework import serializers from rest_framework import serializers
@ -73,10 +79,11 @@ class GifuAreaSerializer(serializers.ModelSerializer):
class UserRegistrationSerializer(serializers.ModelSerializer): class UserRegistrationSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=True, validators=[validate_password]) password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
password2 = serializers.CharField(write_only=True, required=True, validators=[validate_password])
class Meta: class Meta:
model = CustomUser model = CustomUser
fields = ('email', 'password', 'firstname', 'lastname', 'date_of_birth', 'female') fields = ('email', 'password', 'password2', 'firstname', 'lastname', 'date_of_birth', 'female')
extra_kwargs = { extra_kwargs = {
'email': {'required': True}, 'email': {'required': True},
'firstname': {'required': True}, 'firstname': {'required': True},
@ -84,38 +91,68 @@ class UserRegistrationSerializer(serializers.ModelSerializer):
'date_of_birth': {'required': True}, 'date_of_birth': {'required': True},
} }
def validate(self, attrs):
if attrs['password'] != attrs['password2']:
raise serializers.ValidationError({"password": "Password fields didn't match."})
try:
validate_password(attrs['password'])
except ValidationError as e:
raise serializers.ValidationError({"password": list(e.messages)})
return attrs
def validate_email(self, value): def validate_email(self, value):
if CustomUser.objects.filter(email=value).exists() or TempUser.objects.filter(email=value).exists(): if CustomUser.objects.filter(email=value).exists() or TempUser.objects.filter(email=value).exists():
raise serializers.ValidationError("この電子メールアドレスは既に使用されています。") raise serializers.ValidationError("この電子メールアドレスは既に使用されています。")
return value return value
def create(self, validated_data): def create(self, validated_data):
try: raw_password = validated_data.get('password')
user = CustomUser.objects.create_user(
email=validated_data['email'], # デバッグコード
password=validated_data['password'], hashed_password = make_password(raw_password)
firstname=validated_data['firstname'], print(f"Hashed password during registration: {hashed_password}")
lastname=validated_data['lastname'], is_valid = check_password(raw_password, hashed_password)
date_of_birth=validated_data['date_of_birth'], print(f"Password is valid during registration: {is_valid}")
female=validated_data.get('female', False),
group='' # この値は必要に応じて変更してください validated_data['password'] = hashed_password
) return super(UserRegistrationSerializer, self).create(validated_data)
return user
except ValidationError as e: #validated_data['password'] = make_password(validated_data.get('password'))
raise serializers.ValidationError({"password": list(e.messages)}) #return super(UserRegistrationSerializer, self).create(validated_data)
# try:
# with transaction.atomic():
# password = validated_data['password'].encode('utf-8').decode('utf-8')
#
# user = CustomUser.objects.create_user(
# email=validated_data['email'],
# password=password, # validated_data['password'],
# firstname=validated_data['firstname'],
# lastname=validated_data['lastname'],
# date_of_birth=validated_data['date_of_birth'],
# female=validated_data.get('female', False),
# group='' # この値は必要に応じて変更してください
# )
# logger.debug(f"Creating user with data: {validated_data}")
# user.set_password(validated_data['password'])
# user.save()
#
# return user
# except ValidationError as e:
# raise serializers.ValidationError({"password": list(e.messages)})
''' #class CreateUserSerializer(serializers.ModelSerializer):
class CreateUserSerializer(serializers.ModelSerializer): # class Meta:
class Meta: # model = CustomUser
model = CustomUser # fields = ('email', 'password')
fields = ('email', 'password') # extra_kwargs = {'password': {'write_only': True}}
extra_kwargs = {'password': {'write_only': True}} #
# def create(self, validated_data):
def create(self, validated_data): # user = CustomUser.objects.create_user(validated_data['email'],validated_data['password'], '大垣-初心者','','')
user = CustomUser.objects.create_user(validated_data['email'],validated_data['password'], '大垣-初心者','','') # return user
return user
'''
class TempUserRegistrationSerializer(serializers.ModelSerializer): class TempUserRegistrationSerializer(serializers.ModelSerializer):
class Meta: class Meta:
@ -124,6 +161,9 @@ class TempUserRegistrationSerializer(serializers.ModelSerializer):
def create(self, validated_data): def create(self, validated_data):
validated_data['verification_code'] = str(uuid.uuid4()) validated_data['verification_code'] = str(uuid.uuid4())
raw_password = validated_data.get('password')
hashed_password = make_password(raw_password)
validated_data['password'] = hashed_password
return TempUser.objects.create(**validated_data) return TempUser.objects.create(**validated_data)
@ -162,14 +202,32 @@ class RogUserSerializer(serializers.ModelSerializer):
class LoginUserSerializer(serializers.Serializer): class LoginUserSerializer(serializers.Serializer):
email = serializers.CharField() #email = serializers.CharField()
email = serializers.EmailField()
password = serializers.CharField() password = serializers.CharField()
def validate(self, data): def validate(self, data):
user = authenticate(**data) email = data.get('email')
if user and user.is_active: password = data.get('password')
return user
raise serializers.ValidationError("Invalid Details.") if email and password:
user = authenticate(username=email, password=password)
if user:
if user.is_active:
return user
raise serializers.ValidationError("User account is disabled.")
else:
# Check if the user exists
try:
user_obj = User.objects.get(email=email)
raise serializers.ValidationError("Incorrect password.")
except User.DoesNotExist:
raise serializers.ValidationError("User with this email does not exist.")
else:
raise serializers.ValidationError("Must include 'email' and 'password'.")
class UseractionsSerializer(serializers.ModelSerializer): class UseractionsSerializer(serializers.ModelSerializer):

View File

@ -1,3 +1,8 @@
from .models import JpnSubPerf # このインポート文をファイルの先頭に追加
from django.contrib.auth import get_user_model
User = get_user_model()
import traceback
import requests import requests
from rest_framework import serializers from rest_framework import serializers
from django.db import IntegrityError from django.db import IntegrityError
@ -398,13 +403,28 @@ def ExtentForLocations(request):
return JsonResponse(locs['geom__extent'], safe=False) return JsonResponse(locs['geom__extent'], safe=False)
def ExtentForSubPerf(request): def ExtentForSubPerf_old(request):
sub_perf_id = request.GET.get('sub_perf') sub_perf_id = request.GET.get('sub_perf')
sub_perf = JpnSubPerf.objects.get(id=sub_perf_id) sub_perf = JpnSubPerf.objects.get(id=sub_perf_id)
ext = sub_perf.geom.extent ext = sub_perf.geom.extent
# iata = serializers.serialize("json",ext) # iata = serializers.serialize("json",ext)
return JsonResponse(ext, safe=False) return JsonResponse(ext, safe=False)
def ExtentForSubPerf(request):
sub_perf_id = request.GET.get('sub_perf')
if not sub_perf_id:
return JsonResponse({"error": "sub_perf parameter is required"}, status=400)
try:
sub_perf = JpnSubPerf.objects.get(id=sub_perf_id)
ext = sub_perf.geom.extent
return JsonResponse(ext, safe=False)
except ObjectDoesNotExist:
return JsonResponse({"error": "Specified sub_perf does not exist"}, status=404)
except Exception as e:
return JsonResponse({"error": "Error on ExtentForSubPerf : {e}"}, status=404)
def CatView(request): def CatView(request):
lat1 = float(request.GET.get('la1')) lat1 = float(request.GET.get('la1'))
@ -457,17 +477,94 @@ class RegistrationAPI(generics.GenericAPIView):
}) })
class LoginView(APIView):
def post(self, request):
email = request.data.get('email')
password = request.data.get('password')
# デバッグコード
from django.contrib.auth.hashers import make_password, check_password
user = CustomUser.objects.filter(email=email).first()
if user:
stored_hash = user.password
print(f"Stored hashed password: {stored_hash}")
is_valid = check_password(raw_password, stored_hash)
print(f"Password is valid during login: {is_valid}")
user = authenticate(request, username=email, password=raw_password)
if user:
token, _ = Token.objects.get_or_create(user=user)
return Response({'token': token.key}, status=status.HTTP_200_OK)
else:
return Response({'error': 'Invalid credentials'}, status=status.HTTP_400_BAD_REQUEST)
#user = authenticate(request, username=email, password=password)
#if user:
# token, _ = Token.objects.get_or_create(user=user)
# return Response({'token': token.key}, status=status.HTTP_200_OK)
#else:
# return Response({'error': 'Invalid credentials'}, status=status.HTTP_400_BAD_REQUEST)
class PasswordResetView(APIView):
def post(self, request):
email = request.data.get('email')
user = CustomUser.objects.filter(email=email).first()
if user:
token = default_token_generator.make_token(user)
uid = urlsafe_base64_encode(force_bytes(user.pk))
reset_link = f"https://yourwebsite.com/reset-password/{uid}/{token}/"
send_mail(
'Password Reset',
f'Click here to reset your password: {reset_link}',
'noreply@yourwebsite.com',
[email],
fail_silently=False,
)
return Response({'message': 'Password reset email sent'}, status=status.HTTP_200_OK)
else:
return Response({'error': 'User not found'}, status=status.HTTP_400_BAD_REQUEST)
class LoginAPI(generics.GenericAPIView): class LoginAPI(generics.GenericAPIView):
serializer_class = LoginUserSerializer serializer_class = LoginUserSerializer
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
logger.info(f"Login attempt for user: {request.data.get('email', 'email not provided')}")
logger.debug(f"Request data: {request.data}")
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True) try:
user = serializer.validated_data serializer.is_valid(raise_exception=True)
return Response({ user = serializer.validated_data
"user": UserSerializer(user, context=self.get_serializer_context()).data, logger.info(f"User {user.email} logged in successfully")
"token": AuthToken.objects.create(user)[1]
}) return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
except serializers.ValidationError as e:
logger.error(f"Login failed for user {request.data.get('email', 'email not provided')}: {str(e)}")
logger.error(f"Serializer errors: {serializer.errors}")
error_msg = serializer.errors.get('non_field_errors', ['ログインに失敗しました。'])[0]
return Response({
"error": error_msg,
"details": serializer.errors
}, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
logger.error(f"Unexpected error during login for user {request.data.get('email', 'email not provided')}: {str(e)}")
logger.error(f"Traceback: {traceback.format_exc()}")
return Response({
"error": "予期せぬエラーが発生しました。",
"details": str(e)
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
class UserUpdateAPI(generics.UpdateAPIView): class UserUpdateAPI(generics.UpdateAPIView):
permission_classes = [permissions.IsAuthenticated] permission_classes = [permissions.IsAuthenticated]
@ -807,7 +904,20 @@ class RegistrationView(APIView):
try: try:
user = serializer.save() user = serializer.save()
logger.info(f"New user registered: {user.email}") logger.info(f"New user registered: {user.email}")
# パスワードを取得
password = serializer.validated_data.pop('password')
# ユーザーを作成するが、まだ保存しない
user = serializer.save(commit=False)
# パスワードを明示的に設定
user.set_password(password)
# ユーザーを保存
user.save()
logger.info(f"New user registered: {user.email}")
return Response({"message": "ユーザー登録が完了しました。"}, status=status.HTTP_201_CREATED) return Response({"message": "ユーザー登録が完了しました。"}, status=status.HTTP_201_CREATED)
except Exception as e: except Exception as e:
logger.error(f"Error during user registration: {str(e)}") logger.error(f"Error during user registration: {str(e)}")
return Response({"error": "ユーザー登録中にエラーが発生しました。"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) return Response({"error": "ユーザー登録中にエラーが発生しました。"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@ -1592,6 +1702,8 @@ class TempUserRegistrationView(APIView):
temp_user = serializer.save() temp_user = serializer.save()
verification_code = uuid.uuid4() verification_code = uuid.uuid4()
temp_user.verification_code = verification_code temp_user.verification_code = verification_code
#password = serializer.validated_data.pop('password')
#temp_user.set_password(password)
temp_user.save() temp_user.save()
verification_url = request.build_absolute_uri( verification_url = request.build_absolute_uri(
reverse('verify-email', kwargs={'verification_code': verification_code}) reverse('verify-email', kwargs={'verification_code': verification_code})
@ -1634,12 +1746,20 @@ class VerifyEmailView(APIView):
'date_of_birth': temp_user.date_of_birth, 'date_of_birth': temp_user.date_of_birth,
'female': temp_user.female, 'female': temp_user.female,
} }
# CustomUserを作成
user = CustomUser.objects.create_user( # パスワードを安全にハッシュ化
email=user_data['email'], #hashed_password = make_password(temp_user.password)
password=temp_user.password,
**{k: v for k, v in user_data.items() if k != 'email'} try:
) # CustomUserを作成
user = CustomUser.objects.create_user(
email=user_data['email'],
password=temp_user.password,
**{k: v for k, v in user_data.items() if k != 'email'}
)
except ValidationError as e:
# パスワードのバリデーションエラーなどの処理
return render(request, 'verification_error.html', {'message': str(e), 'title': 'エラー'})
# チームへの追加処理(もし必要なら) # チームへの追加処理(もし必要なら)
if hasattr(temp_user, 'team_id'): if hasattr(temp_user, 'team_id'):