temporary update to debug email

This commit is contained in:
2024-07-26 12:34:54 +00:00
parent 9215ba8f9f
commit bcfcceb068
10 changed files with 383 additions and 73 deletions

View File

@ -176,14 +176,21 @@ REST_FRAMEWORK = {
} }
FRONTEND_URL = 'http://rogainig.intranet.sumasen.net/' # フロントエンドのURLに適宜変更してください
# この設定により、メールは実際には送信されず、代わりにコンソールに出力されます。
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.outlook.com' EMAIL_HOST = 'smtp.outlook.com'
EMAIL_PORT = 587 EMAIL_PORT = 587
EMAIL_USE_TLS = True EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'akira.miyata@gifuai.net' EMAIL_HOST_USER = 'rogaining@gifuai.net'
EMAIL_HOST_PASSWORD = 'SachikoMiyata123' EMAIL_HOST_PASSWORD = 'ctcpy9823"x~'
DEFAULT_FROM_EMAIL = 'info@gifuai.net' DEFAULT_FROM_EMAIL = 'info@gifuai.net'
APP_DOWNLOAD_LINK = 'http://your-app-download-link.com'
SERVICE_NAME = '岐阜ロゲ'
# settings.py # settings.py
DEFAULT_CHARSET = 'utf-8' DEFAULT_CHARSET = 'utf-8'
@ -194,4 +201,43 @@ DEFAULT_CHARSET = 'utf-8'
# 'JSON_UNICODE_ESCAPE': False, # 'JSON_UNICODE_ESCAPE': False,
#} #}
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {message}',
'style': '{',
},
},
'handlers': {
#'file': {
# 'level': 'DEBUG',
# 'class': 'logging.FileHandler',
# 'filename': os.path.join(BASE_DIR, 'logs/debug.log'),
# 'formatter': 'verbose',
#},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'root': {
'handlers': ['console'],
'level': 'DEBUG',
},
'loggers': {
#'django': {
# 'handlers': ['console'],
# 'level': 'INFO',
# 'propagate': False,
#},
'rog': {
#'handlers': ['file','console'],
'handlers': ['console'],
'level': 'DEBUG',
'propagate': True,
},
},
}

View File

@ -0,0 +1,29 @@
# Generated by Django 3.2.9 on 2024-07-26 06:08
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('rog', '0038_alter_entry_category'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='date_joined',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AlterField(
model_name='customuser',
name='email',
field=models.EmailField(max_length=254, unique=True),
),
migrations.AlterField(
model_name='customuser',
name='group',
field=models.CharField(blank=True, max_length=255),
),
]

View File

@ -208,26 +208,24 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
GB2 = '大垣-3時間', '大垣-3時間' GB2 = '大垣-3時間', '大垣-3時間'
GB3 = '大垣-5時間', '大垣-5時間' GB3 = '大垣-5時間', '大垣-5時間'
email = models.CharField(_("Email"), max_length=255, unique=True) email = models.EmailField(unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_rogaining = models.BooleanField(default=False)
zekken_number = models.CharField(_("Zekken Number"), max_length=255, blank=True, null=True)
event_code = models.CharField(_("Event Code"), max_length=255, blank=True, null=True)
team_name = models.CharField(_("Team Name"), max_length=255, blank=True, null=True)
group = models.CharField(max_length=255,
choices=Groups.choices,
default=Groups.GB1)
# Akira
firstname = models.CharField(max_length=255,blank=True, null=True) firstname = models.CharField(max_length=255,blank=True, null=True)
lastname = models.CharField(max_length=255, blank=True, null=True) lastname = models.CharField(max_length=255, blank=True, null=True)
date_of_birth = models.DateField(blank=True, null=True) date_of_birth = models.DateField(blank=True, null=True)
female = models.BooleanField(default=False) female = models.BooleanField(default=False)
# Akira group = models.CharField(max_length=255,blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
is_rogaining = models.BooleanField(default=False)
zekken_number = models.CharField(_("Zekken Number"), max_length=255, blank=True, null=True)
event_code = models.CharField(_("Event Code"), max_length=255, blank=True, null=True)
team_name = models.CharField(_("Team Name"), max_length=255, blank=True, null=True)
USERNAME_FIELD = 'email' USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['group',] REQUIRED_FIELDS = []
objects = CustomUserManager() objects = CustomUserManager()

View File

@ -1,8 +1,8 @@
import uuid import uuid
from django.db import IntegrityError from django.db import IntegrityError
from django.core.mail import send_mail
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.db import transaction from django.db import transaction
from rest_framework import serializers from rest_framework import serializers
@ -14,7 +14,6 @@ from drf_extra_fields.fields import Base64ImageField
#from django.contrib.auth.models import User #from django.contrib.auth.models import User
from .models import CustomUser from .models import CustomUser
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from .utils import send_activation_email
from .models import TestModel from .models import TestModel
import logging import logging
@ -72,8 +71,41 @@ class GifuAreaSerializer(serializers.ModelSerializer):
model= GifuAreas model= GifuAreas
fields=['id', 'adm0_ja', 'adm0_pcode', 'adm1_en', 'adm1_ja', 'adm1_pcode', 'adm2_ja', 'adm2_en', 'adm2_pcode', 'area_nm'] fields=['id', 'adm0_ja', 'adm0_pcode', 'adm1_en', 'adm1_ja', 'adm1_pcode', 'adm2_ja', 'adm2_en', 'adm2_pcode', 'area_nm']
class UserRegistrationSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
class Meta:
model = CustomUser
fields = ('email', 'password', 'firstname', 'lastname', 'date_of_birth', 'female')
extra_kwargs = {
'email': {'required': True},
'firstname': {'required': True},
'lastname': {'required': True},
'date_of_birth': {'required': True},
}
def validate_email(self, value):
if CustomUser.objects.filter(email=value).exists() or TempUser.objects.filter(email=value).exists():
raise serializers.ValidationError("この電子メールアドレスは既に使用されています。")
return value
def create(self, validated_data):
try:
user = CustomUser.objects.create_user(
email=validated_data['email'],
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='' # この値は必要に応じて変更してください
)
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
@ -83,6 +115,17 @@ class CreateUserSerializer(serializers.ModelSerializer):
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 Meta:
model = TempUser
fields = ('email', 'firstname', 'lastname', 'date_of_birth', 'female')
def create(self, validated_data):
validated_data['verification_code'] = str(uuid.uuid4())
return TempUser.objects.create(**validated_data)
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
@ -385,10 +428,16 @@ class EntrySerializer(serializers.ModelSerializer):
def to_representation(self, instance): def to_representation(self, instance):
ret = super().to_representation(instance) ret = super().to_representation(instance)
if isinstance(ret['date'], datetime): ret['team'] = TeamSerializer(instance.team).data
ret['date'] = ret['date'].date().isoformat() ret['event'] = NewEvent2Serializer(instance.event).data
ret['category'] = NewCategorySerializer(instance.category).data
ret['owner'] = CustomUserSerializer(instance.owner).data
return ret return ret
#if isinstance(ret['date'], datetime):
# ret['date'] = ret['date'].date().isoformat()
#return ret
#def to_representation(self, instance): #def to_representation(self, instance):
# ret = super().to_representation(instance) # ret = super().to_representation(instance)
# ret['team'] = instance.team.team_name # ret['team'] = instance.team.team_name
@ -400,9 +449,8 @@ class EntrySerializer(serializers.ModelSerializer):
class CustomUserSerializer(serializers.ModelSerializer): class CustomUserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = CustomUser model = CustomUser
#fields = ['email', 'is_staff', 'is_active', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'firstname', 'lastname', 'date_of_birth', 'female']
fields = ['id','email', 'firstname', 'lastname', 'date_of_birth', 'female'] fields = ['id','email', 'firstname', 'lastname', 'date_of_birth', 'female']
read_only_fields = ['email'] read_only_fields = ['id','email']
class TeamDetailSerializer(serializers.ModelSerializer): class TeamDetailSerializer(serializers.ModelSerializer):
category = NewCategorySerializer(read_only=True) category = NewCategorySerializer(read_only=True)
@ -448,7 +496,7 @@ class MemberWithUserSerializer(serializers.ModelSerializer):
class MemberSerializer(serializers.ModelSerializer): class MemberSerializer(serializers.ModelSerializer):
user = CustomUserSerializer(read_only=True) user = CustomUserSerializer(read_only=True)
team = TeamDetailSerializer(read_only=True) #team = TeamDetailSerializer(read_only=True)
#email = serializers.EmailField(write_only=True, required=False) #email = serializers.EmailField(write_only=True, required=False)
#firstname = serializers.CharField(write_only=True, required=False) #firstname = serializers.CharField(write_only=True, required=False)
@ -487,16 +535,35 @@ class MemberSerializer(serializers.ModelSerializer):
user_data = validated_data.pop('user', {}) user_data = validated_data.pop('user', {})
user = instance.user user = instance.user
if user.email.startswith('dummy_'): # dummy_ で始まるメールアドレスの場合のみ更新 for attr, value in user_data.items():
for attr, value in user_data.items(): setattr(user, attr, value)
setattr(user, attr, value) user.save()
user.save()
else:
raise serializers.ValidationError("このユーザーの情報は更新できません。")
return super().update(instance, validated_data) return super().update(instance, validated_data)
#if user.email.startswith('dummy_'): # dummy_ で始まるメールアドレスの場合のみ更新
# for attr, value in user_data.items():
# setattr(user, attr, value)
# user.save()
#else:
# raise serializers.ValidationError("このユーザーの情報は更新できません。")
#return super().update(instance, validated_data)
def to_representation(self, instance):
representation = super().to_representation(instance)
user_data = representation['user']
return {
'id': representation['id'],
'email': user_data['email'],
'firstname': user_data['firstname'],
'lastname': user_data['lastname'],
'date_of_birth': user_data['date_of_birth'],
'female': user_data['female'],
'team': representation['team']
}
class EntryMemberSerializer(serializers.ModelSerializer): class EntryMemberSerializer(serializers.ModelSerializer):
class Meta: class Meta:
@ -507,7 +574,8 @@ class EntryMemberSerializer(serializers.ModelSerializer):
class TempUserSerializer(serializers.ModelSerializer): class TempUserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = TempUser model = TempUser
fields = ['id','email', 'password', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'firstname', 'lastname', 'date_of_birth', 'female', 'verification_code', 'created_at', 'expires_at'] #fields = ['id','email', 'password', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'firstname', 'lastname', 'date_of_birth', 'female', 'verification_code', 'created_at', 'expires_at']
fields = ['email', 'password', 'firstname', 'lastname', 'date_of_birth', 'female', 'verification_code']
class EntryCreationSerializer(serializers.Serializer): class EntryCreationSerializer(serializers.Serializer):
owner_email = serializers.EmailField() owner_email = serializers.EmailField()

View File

@ -0,0 +1,16 @@
件名: アカウントのアクティベーション
{name} 様
この度は、サービスにご登録いただき、ありがとうございます。
以下のリンクをクリックしてアカウントをアクティベートしてください:
{activation_link}
また、アプリをダウンロードしてください:
{app_download_link}
このメールに心当たりがない場合は、お手数ですが破棄してください。
よろしくお願いいたします。
{service_name} チーム

View File

@ -1,7 +1,7 @@
from sys import prefix from sys import prefix
from rest_framework import urlpatterns from rest_framework import urlpatterns
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from .views import LocationViewSet, Location_lineViewSet, Location_polygonViewSet, Jpn_Main_PerfViewSet, LocationsInPerf, ExtentForSubPerf, SubPerfInMainPerf, ExtentForMainPerf, LocationsInSubPerf, CatView, RegistrationAPI, LoginAPI, UserAPI, UserActionViewset, UserMakeActionViewset, UserDestinations, UpdateOrder, LocationInBound, DeleteDestination, CustomAreaLocations, GetAllGifuAreas, CustomAreaNames, userDetials, UserTracksViewSet, CatByCity, ChangePasswordView, GoalImageViewSet, CheckinImageViewSet, ExtentForLocations, DeleteAccount, PrivacyView, RegistrationView, TeamViewSet,MemberViewSet,EntryViewSet,RegisterView, VerifyEmailView, NewEventListView,NewEvent2ListView,NewCategoryListView,CategoryListView, MemberUserDetailView, TeamMembersWithUserView,MemberAddView,UserActivationView from .views import LocationViewSet, Location_lineViewSet, Location_polygonViewSet, Jpn_Main_PerfViewSet, LocationsInPerf, ExtentForSubPerf, SubPerfInMainPerf, ExtentForMainPerf, LocationsInSubPerf, CatView, RegistrationAPI, LoginAPI, UserAPI, UserActionViewset, UserMakeActionViewset, UserDestinations, UpdateOrder, LocationInBound, DeleteDestination, CustomAreaLocations, GetAllGifuAreas, CustomAreaNames, userDetials, UserTracksViewSet, CatByCity, ChangePasswordView, GoalImageViewSet, CheckinImageViewSet, ExtentForLocations, DeleteAccount, PrivacyView, RegistrationView, TeamViewSet,MemberViewSet,EntryViewSet,RegisterView, VerifyEmailView, NewEventListView,NewEvent2ListView,NewCategoryListView,CategoryListView, MemberUserDetailView, TeamMembersWithUserView,MemberAddView,UserActivationView,RegistrationView,TempUserRegistrationView
from django.urls import path, include from django.urls import path, include
from knox import views as knox_views from knox import views as knox_views
@ -57,7 +57,7 @@ urlpatterns += [
path('mainperfext/', ExtentForMainPerf, name="main_perf_ext"), path('mainperfext/', ExtentForMainPerf, name="main_perf_ext"),
path('cats/', CatView, name='cats'), path('cats/', CatView, name='cats'),
path('catbycity/', CatByCity, name='cat_by_city'), path('catbycity/', CatByCity, name='cat_by_city'),
path('register/', RegistrationAPI.as_view()), #path('register/', RegistrationAPI.as_view()),
path('login/', LoginAPI.as_view()), path('login/', LoginAPI.as_view()),
path('user/', UserAPI.as_view()), path('user/', UserAPI.as_view()),
path('logout/', knox_views.LogoutView.as_view(), name='knox_logout'), path('logout/', knox_views.LogoutView.as_view(), name='knox_logout'),
@ -71,9 +71,7 @@ urlpatterns += [
path('change-password/', ChangePasswordView.as_view(), name='change-password'), path('change-password/', ChangePasswordView.as_view(), name='change-password'),
path('delete-account/', DeleteAccount, name="delete-account"), path('delete-account/', DeleteAccount, name="delete-account"),
path('privacy/', PrivacyView, name='privacy-view'), path('privacy/', PrivacyView, name='privacy-view'),
path('register', RegistrationView.as_view(), name='register'),
# path('goal-image/', GoalImageViewSet.as_view(), name='goal-image') # path('goal-image/', GoalImageViewSet.as_view(), name='goal-image')
path('register/', RegisterView.as_view(), name='register'),
path('verify-email/<uuid:verification_code>/', VerifyEmailView.as_view(), name='verify-email'), path('verify-email/<uuid:verification_code>/', VerifyEmailView.as_view(), name='verify-email'),
path('categories/', NewCategoryListView.as_view(), name='category-list'), path('categories/', NewCategoryListView.as_view(), name='category-list'),
path('new-events/', NewEvent2ListView.as_view(), name='new-event-list'), path('new-events/', NewEvent2ListView.as_view(), name='new-event-list'),
@ -83,5 +81,8 @@ urlpatterns += [
path('teams/<int:team_id>/members/', MemberViewSet.as_view({'get': 'list', 'post': 'create'}), name='team-members'), path('teams/<int:team_id>/members/', MemberViewSet.as_view({'get': 'list', 'post': 'create'}), name='team-members'),
path('teams/<int:team_id>/members/<int:pk>/', MemberViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}), name='team-member-detail'), path('teams/<int:team_id>/members/<int:pk>/', MemberViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}), name='team-member-detail'),
path('activate/<str:activation_token>/', UserActivationView.as_view(), name='user-activation'), path('activate/<str:activation_token>/', UserActivationView.as_view(), name='user-activation'),
#path('register/', RegistrationView.as_view(), name='register'), #直接の登録はしない。
path('register/', TempUserRegistrationView.as_view(), name='temp-register'), # 仮登録
#path('register/temp/', RegisterView.as_view(), name='register'), # 古い仮登録
] ]

View File

@ -16,7 +16,9 @@ def load_email_template(template_name, context):
return subject, body return subject, body
def send_activation_email(user, activation_link): # 既にユーザーになっている人にチームへの参加要請メールを出す。
#
def send_team_join_email(sender,user,team,entry,activation_link):
context = { context = {
'name': user.firstname or user.email, 'name': user.firstname or user.email,
'activation_link': activation_link, 'activation_link': activation_link,
@ -26,9 +28,73 @@ def send_activation_email(user, activation_link):
subject, body = load_email_template('activation_email.txt', context) subject, body = load_email_template('activation_email.txt', context)
try:
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [user.email], fail_silently=False)
logger.info(f"チームへの参加承認メールを送信しました。 受信者: {user.email}")
except Exception as e:
logger.error(f"チームへの参加承認メールの送信に失敗しました。 受信者: {user.email}, エラー: {str(e)}")
raise # エラーを再度発生させて、呼び出し元で処理できるようにします
# 自らユーザー登録した際に、メールの確認メールを送る。
#
def send_verification_email(user, activation_link):
context = {
'name': user.firstname or user.email,
'activation_link': activation_link,
'app_download_link': settings.APP_DOWNLOAD_LINK,
'service_name': settings.SERVICE_NAME,
}
subject, body = load_email_template('verification_email.txt', context)
logger.info(f"subject: {subject}")
logger.info(f"body: {body}")
try: try:
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [user.email], fail_silently=False) send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [user.email], fail_silently=False)
logger.info(f"アクティベーションメールを送信しました。 受信者: {user.email}") logger.info(f"アクティベーションメールを送信しました。 受信者: {user.email}")
except Exception as e: except Exception as e:
logger.error(f"アクティベーションメールの送信に失敗しました。 受信者: {user.email}, エラー: {str(e)}") logger.error(f"アクティベーションメールの送信に失敗しました。 受信者: {user.email}, エラー: {str(e)}")
raise # エラーを再度発生させて、呼び出し元で処理できるようにします raise # エラーを再度発生させて、呼び出し元で処理できるようにします
# まだユーザーでない人にチームメンバー招待メールを送る
# その人がユーザー登録して、ユーザー登録されるとメンバーになる。
# アプリからユーザー登録するため、アプリのダウンロードリンクも送る。
#
def send_invitation_email(sender,user,team,entry,activation_link):
context = {
'name': user.firstname or user.email,
'invitaion_link': activation_link,
'app_download_link': settings.APP_DOWNLOAD_LINK,
'service_name': settings.SERVICE_NAME,
}
subject, body = load_email_template('invitaion_email.txt', context)
try:
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [user.email], fail_silently=False)
logger.info(f"招待メールを送信しました。 受信者: {user.email}")
except Exception as e:
logger.error(f"招待メールの送信に失敗しました。 受信者: {user.email}, エラー: {str(e)}")
raise # エラーを再度発生させて、呼び出し元で処理できるようにします
# エントリーしたら、その内容をメンバーに送信する。
#
def send_entry_email(sender,user,team,entry,activation_link):
context = {
'name': user.firstname or user.email,
'invitaion_link': activation_link,
'app_download_link': settings.APP_DOWNLOAD_LINK,
'service_name': settings.SERVICE_NAME,
}
subject, body = load_email_template('invitaion_email.txt', context)
try:
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [user.email], fail_silently=False)
logger.info(f"エントリーメールを送信しました。 受信者: {user.email}")
except Exception as e:
logger.error(f"エントリーメールの送信に失敗しました。 受信者: {user.email}, エラー: {str(e)}")
raise # エラーを再度発生させて、呼び出し元で処理できるようにします

View File

@ -1,7 +1,8 @@
from rest_framework import serializers from rest_framework import serializers
from django.db import IntegrityError from django.db import IntegrityError
from django.urls import reverse from django.urls import reverse
from .utils import send_activation_email from .utils import send_verification_email,send_invitation_email,send_team_join_email,send_entry_email
from django.conf import settings
import uuid import uuid
from rest_framework.exceptions import ValidationError as DRFValidationError from rest_framework.exceptions import ValidationError as DRFValidationError
@ -12,14 +13,14 @@ from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from .models import Team, Member, CustomUser, NewCategory from .models import Team, Member, CustomUser, NewCategory
from .serializers import TeamSerializer, MemberSerializer, CustomUserSerializer, TeamDetailSerializer,UserUpdateSerializer from .serializers import TeamSerializer, MemberSerializer, CustomUserSerializer, TeamDetailSerializer,UserUpdateSerializer,UserRegistrationSerializer
from .permissions import IsTeamOwner from .permissions import IsTeamOwner
from curses.ascii import NUL from curses.ascii import NUL
from django.core.serializers import serialize from django.core.serializers import serialize
from .models import GoalImages, Location, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, GifuAreas, RogUser, CustomUser, UserTracks, GoalImages, CheckinImages, NewEvent,NewEvent2, Team, Category, NewCategory,Entry, Member, TempUser,EntryMember from .models import GoalImages, Location, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, GifuAreas, RogUser, CustomUser, UserTracks, GoalImages, CheckinImages, NewEvent,NewEvent2, Team, Category, NewCategory,Entry, Member, TempUser,EntryMember
from rest_framework import viewsets from rest_framework import viewsets
from .serializers import LocationSerializer, Location_lineSerializer, Location_polygonSerializer, JPN_main_perfSerializer, LocationCatSerializer, CreateUserSerializer, UserSerializer, LoginUserSerializer, UseractionsSerializer, UserDestinationSerializer, GifuAreaSerializer, LocationEventNameSerializer, RogUserSerializer, UserTracksSerializer, ChangePasswordSerializer, GolaImageSerializer, CheckinImageSerializer, RegistrationSerializer, MemberWithUserSerializer from .serializers import LocationSerializer, Location_lineSerializer, Location_polygonSerializer, JPN_main_perfSerializer, LocationCatSerializer, UserSerializer, LoginUserSerializer, UseractionsSerializer, UserDestinationSerializer, GifuAreaSerializer, LocationEventNameSerializer, RogUserSerializer, UserTracksSerializer, ChangePasswordSerializer, GolaImageSerializer, CheckinImageSerializer, RegistrationSerializer, MemberWithUserSerializer,TempUserRegistrationSerializer
from knox.models import AuthToken from knox.models import AuthToken
from rest_framework import viewsets, generics, status from rest_framework import viewsets, generics, status
@ -50,6 +51,9 @@ from django.utils.decorators import method_decorator
from django.utils.encoding import force_str from django.utils.encoding import force_str
import logging import logging
from datetime import datetime
from django.utils.dateparse import parse_date
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -284,7 +288,8 @@ def CatByCity(request):
class RegistrationAPI(generics.GenericAPIView): class RegistrationAPI(generics.GenericAPIView):
serializer_class = CreateUserSerializer #serializer_class = CreateUserSerializer
serializer_class = UserRegistrationSerializer
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
@ -410,6 +415,20 @@ def DeleteAccount(request):
return Response({"result":"user deleted"}) return Response({"result":"user deleted"})
return Response({"result":"user not found"}) return Response({"result":"user not found"})
'''
def send_verification_email(self, temp_user):
subject = '仮登録の確認'
message = f'以下のリンクをクリックして登録を完了してください:\n{settings.FRONTEND_URL}/verify/{temp_user.verification_code}'
from_email = settings.DEFAULT_FROM_EMAIL
recipient_list = [temp_user.email]
try:
send_mail(subject, message, from_email, recipient_list)
logger.info(f"Verification email sent to {temp_user.email}")
except Exception as e:
logger.error(f"Failed to send verification email to {temp_user.email}. Error: {str(e)}")
'''
def UserActionViewset(request): def UserActionViewset(request):
user_id = request.GET.get('user_id') user_id = request.GET.get('user_id')
@ -622,13 +641,25 @@ class TestActionViewSet(viewsets.ModelViewSet):
def PrivacyView(request): def PrivacyView(request):
return render(request, "rog/privacy.html") return render(request, "rog/privacy.html")
class RegistrationView(APIView): class RegistrationView(APIView):
@transaction.atomic
def post(self, request): def post(self, request):
serializer = RegistrationSerializer(data=request.data) serializer = UserRegistrationSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() try:
return Response(serializer.data, status=status.HTTP_201_CREATED) user = serializer.save()
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) logger.info(f"New user registered: {user.email}")
return Response({"message": "ユーザー登録が完了しました。"}, status=status.HTTP_201_CREATED)
except Exception as e:
logger.error(f"Error during user registration: {str(e)}")
return Response({"error": "ユーザー登録中にエラーが発生しました。"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
else:
logger.warning(f"Invalid registration data: {serializer.errors}")
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# Akira # Akira
@ -751,10 +782,13 @@ class EntryViewSet(viewsets.ModelViewSet):
def get_queryset(self): def get_queryset(self):
user = self.request.user user = self.request.user
# ユーザーが所するチームのIDを取得 # ユーザーが所するチームのIDを取得
team_ids = Member.objects.filter(user=user).values_list('team_id', flat=True) owned_team_ids = Team.objects.filter(owner=user).values_list('id', flat=True)
# そのチームに関連するエントリーを取得 # ユーザーがメンバーとして所属するチームのIDを取得
return Entry.objects.filter(team__id__in=team_ids) member_team_ids = Member.objects.filter(user=user).values_list('team_id', flat=True)
# 両方のチームに関連するエントリーを取得
return Entry.objects.filter(Q(team__id__in=owned_team_ids) | Q(team__id__in=member_team_ids))
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
@ -831,7 +865,6 @@ class MemberViewSet(viewsets.ModelViewSet):
'lastname': serializer.validated_data.get('lastname', ''), 'lastname': serializer.validated_data.get('lastname', ''),
'date_of_birth': serializer.validated_data.get('date_of_birth'), 'date_of_birth': serializer.validated_data.get('date_of_birth'),
'female': serializer.validated_data.get('female', False), 'female': serializer.validated_data.get('female', False),
'is_active': True
} }
if not email or email.startswith('dummy_'): if not email or email.startswith('dummy_'):
@ -839,7 +872,7 @@ class MemberViewSet(viewsets.ModelViewSet):
if email: if email:
user, created = CustomUser.objects.get_or_create( user, created = CustomUser.objects.get_or_create(
email=email, email=email,
defaults=user_data defaults={**user_data, 'is_active':True}
) )
else: else:
# emailが空の場合、一意のダミーメールアドレスを生成 # emailが空の場合、一意のダミーメールアドレスを生成
@ -856,18 +889,17 @@ class MemberViewSet(viewsets.ModelViewSet):
existing_user = CustomUser.objects.filter(email=email).first() existing_user = CustomUser.objects.filter(email=email).first()
if existing_user: if existing_user:
# 既存ユーザーの場合、チーム招待メールを送信 # 既存ユーザーの場合、チーム招待メールを送信
self.send_invitation_email(existing_user, team) send_team_join_email(existing_user, team)
return Response({"message": "Invitation sent to existing user."}, status=status.HTTP_200_OK) return Response({"message": "Invitation for your team sent to existing user."}, status=status.HTTP_200_OK)
else: else:
print("新規ユーザー") print("新規ユーザー")
# 新規ユーザーの場合、TempUserを作成してアクティベーションメールを送信
temp_user = TempUser.objects.create( temp_user = TempUser.objects.create(
email=email, email=email,
**user_data, **user_data,
verification_code=str(uuid.uuid4()) verification_code=str(uuid.uuid4())
) )
self.send_activation_email(temp_user, team) send_invitation_email(temp_user, team)
return Response({"message": "Verification email sent to the user."}, status=status.HTTP_201_CREATED) return Response({"message": "Invitation email sent to the user."}, status=status.HTTP_201_CREATED)
''' '''
@ -888,6 +920,7 @@ class MemberViewSet(viewsets.ModelViewSet):
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
''' '''
'''
def send_activation_email(self, temp_user, team): def send_activation_email(self, temp_user, team):
# アクティベーションメール送信のロジックをここに実装 # アクティベーションメール送信のロジックをここに実装
# 注意: 'user-activation' URLパターンが存在しない場合は、適切なURLを生成する方法を検討する必要があります # 注意: 'user-activation' URLパターンが存在しない場合は、適切なURLを生成する方法を検討する必要があります
@ -897,7 +930,6 @@ class MemberViewSet(viewsets.ModelViewSet):
# ここでemailを送信するロジックを実装 # ここでemailを送信するロジックを実装
print(f"Activation email would be sent to {temp_user.email} with URL: {activation_url}") print(f"Activation email would be sent to {temp_user.email} with URL: {activation_url}")
def send_invitation_email(self, user, team): def send_invitation_email(self, user, team):
# チーム招待メール送信のロジック # チーム招待メール送信のロジック
#invitation_url = self.request.build_absolute_uri( #invitation_url = self.request.build_absolute_uri(
@ -916,6 +948,7 @@ class MemberViewSet(viewsets.ModelViewSet):
invitation_url = "dummy url" #f"{settings.FRONTEND_URL}/team/{team.id}/invite" invitation_url = "dummy url" #f"{settings.FRONTEND_URL}/team/{team.id}/invite"
# ここでemailを送信するロジックを実装 # ここでemailを送信するロジックを実装
print(f"Invitation email would be sent to {user.email} with URL: {invitation_url}") print(f"Invitation email would be sent to {user.email} with URL: {invitation_url}")
'''
@ -923,25 +956,60 @@ class MemberViewSet(viewsets.ModelViewSet):
team = Team.objects.get(id=self.kwargs['team_id']) team = Team.objects.get(id=self.kwargs['team_id'])
serializer.save(team=team) serializer.save(team=team)
@transaction.atomic
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False) #partial = kwargs.pop('partial', False)
instance = self.get_object() instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial) user = instance.user
serializer.is_valid(raise_exception=True) logger.debug(f"Updating user: {user.email}")
logger.debug(f"Received data: {request.data}")
if not instance.user.email.startswith('dummy_'): if user.email.startswith('dummy_'):
return Response({"error": "このユーザーの情報は更新できません。"}, status=status.HTTP_400_BAD_REQUEST) logger.debug("User has dummy email, proceeding with update")
# 直接データを更新
user.firstname = request.data.get('firstname', user.firstname)
user.lastname = request.data.get('lastname', user.lastname)
# 日付の処理
date_of_birth = request.data.get('date_of_birth')
if date_of_birth:
try:
date_of_birth = date_of_birth.translate(str.maketrans("", "0123456789"))
parsed_date = parse_date(date_of_birth)
if parsed_date:
user.date_of_birth = parsed_date
else:
raise ValueError("Invalid date format")
except ValueError:
logger.error(f"Invalid date format: {date_of_birth}")
return Response({"error": "Invalid date format. Use YYYY-MM-DD."}, status=status.HTTP_400_BAD_REQUEST)
self.perform_update(serializer) user.female = request.data.get('female', user.female)
user.save()
logger.debug(f"User updated: firstname={user.firstname}, lastname={user.lastname}, date_of_birth={user.date_of_birth}, female={user.female}")
# Memberインスタンスも更新
serializer = self.get_serializer(instance, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
# 更新後のデータを取得
updated_instance = self.get_object()
updated_serializer = self.get_serializer(updated_instance)
logger.debug(f"Updated user data: {updated_serializer.data}")
return Response(updated_serializer.data)
else:
logger.debug("User does not have dummy email, update not allowed")
return Response({"error": "このユーザーの情報は更新できません。"}, status=status.HTTP_403_FORBIDDEN)
if getattr(instance, '_prefetched_objects_cache', None):
instance._prefetched_objects_cache = {}
return Response(serializer.data)
def perform_update(self, serializer): def perform_update(self, serializer):
serializer.save() serializer.save()
logger.debug("perform_update called")
def get_object(self): def get_object(self):
queryset = self.get_queryset() queryset = self.get_queryset()
@ -1041,6 +1109,7 @@ class EventCategoriesView(generics.ListAPIView):
event_id = self.kwargs['event_id'] event_id = self.kwargs['event_id']
return NewCategory.objects.filter(entry__event_id=event_id).distinct() return NewCategory.objects.filter(entry__event_id=event_id).distinct()
# ユーザー仮登録
class RegisterView(APIView): class RegisterView(APIView):
def post(self, request): def post(self, request):
serializer = TempUserSerializer(data=request.data) serializer = TempUserSerializer(data=request.data)
@ -1053,16 +1122,33 @@ class RegisterView(APIView):
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})
) )
send_mail( send_verification_email(temp_user,verifiction_url)
'Verify your email', #send_mail(
f'Click the link to verify your email: {verification_url}', # 'Verify your email',
settings.DEFAULT_FROM_EMAIL, # f'Click the link to verify your email: {verification_url}',
[temp_user.email], # settings.DEFAULT_FROM_EMAIL,
fail_silently=False, # [temp_user.email],
) # fail_silently=False,
#)
return Response({'message': 'Verification email sent'}, status=status.HTTP_201_CREATED) return Response({'message': 'Verification email sent'}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class TempUserRegistrationView(APIView):
def post(self, request):
serializer = TempUserRegistrationSerializer(data=request.data)
if serializer.is_valid():
temp_user = serializer.save()
verification_code = uuid.uuid4()
temp_user.verification_code = verification_code
temp_user.save()
verification_url = request.build_absolute_uri(
reverse('verify-email', kwargs={'verification_code': verification_code})
)
send_verification_email(temp_user,verification_url) #招待メールを送る。
return Response({"message": "仮登録が完了しました。招待メールを送信しました。"}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# アクティベーション
class VerifyEmailView(APIView): class VerifyEmailView(APIView):
def get(self, request, verification_code): def get(self, request, verification_code):
try: try: