from django.shortcuts import render, redirect from django.http import HttpResponse, JsonResponse from urllib.parse import unquote from .models import Person from django.db import models from django.contrib.auth.decorators import login_required from .forms import PersonForm, Step1PhoneForm, Step2AccountForm from .models import Person from django.shortcuts import get_object_or_404 from django.db.models import Q, Case, When, Value, IntegerField from django.contrib.auth import login, logout import random import json def password_required(request): PASSWORD = '1110' # 실제 비밀번호 # 디버깅을 위한 로그 print(f"[DEBUG] password_required - user.is_authenticated: {request.user.is_authenticated}") print(f"[DEBUG] password_required - user: {request.user}") # 로그인이 된 사용자는 바로 메인 페이지로 리다이렉트 if request.user.is_authenticated: next_url = request.GET.get("next", "/") if not next_url: next_url = "/" print(f"[DEBUG] User is authenticated, redirecting to: {next_url}") return redirect(next_url) if request.method == "POST": entered_password = request.POST.get("password") if entered_password == PASSWORD: request.session["authenticated"] = True next_url = request.POST.get("next", "/") if not next_url: next_url = "/" return redirect(next_url) else: return render(request, "B_main/password.htm", {"error": "Incorrect password. Please try again."}) # GET 요청 시 비밀번호 입력 폼 렌더링 next_url = request.GET.get("next", "/") return render(request, "B_main/password.htm", {"next": next_url}) # 인증 검사 함수 def check_authentication(request): # 디버깅을 위한 로그 print(f"[DEBUG] check_authentication - user.is_authenticated: {request.user.is_authenticated}") print(f"[DEBUG] check_authentication - session.authenticated: {request.session.get('authenticated')}") print(f"[DEBUG] check_authentication - user: {request.user}") # 로그인이 된 사용자는 인증 통과 if request.user.is_authenticated: print(f"[DEBUG] User is authenticated, allowing access") return None # 세션 인증이 된 사용자도 통과 if request.session.get("authenticated"): print(f"[DEBUG] Session is authenticated, allowing access") return None # 둘 다 안 된 경우에만 비밀번호 페이지로 리다이렉트 print(f"[DEBUG] No authentication found, redirecting to password page") return redirect(f"/accounts/login/?next={request.path}") def main(request): print('def main(request):') auth_check = check_authentication(request) if auth_check: return auth_check # 현재 사용자의 Person 정보 가져오기 current_user_person = None if request.user.is_authenticated: try: current_user_person = Person.objects.get(user=request.user) except Person.DoesNotExist: pass # 기본 필터: 이름이 있는 사람들 base_filter = Person.objects.filter( 이름__isnull=False ).exclude( 이름__exact='' ) # 현재 사용자의 권한에 따라 추가 필터 적용 print(f"[DEBUG] 사용자: {request.user.username}, 슈퍼유저: {request.user.is_superuser}") print(f"[DEBUG] current_user_person: {current_user_person}") # 슈퍼유저이거나 Person 객체가 없는 경우 모든 사람 표시 if request.user.is_superuser or current_user_person is None: print(f"[DEBUG] 슈퍼유저 또는 Person 객체 없음 - 모든 사람 표시 모드") # 모든 사람 표시 (필터 추가 없음) elif current_user_person and not current_user_person.모든사람보기권한: # 모든사람보기권한이 False인 경우 회원가입한 사람만 표시 base_filter = base_filter.filter(user__isnull=False) print(f"[DEBUG] 회원가입자만 표시 모드: {current_user_person.이름}") else: print(f"[DEBUG] 모든 사람 표시 모드 (모든사람보기권한: {current_user_person.모든사람보기권한})") # 순서가 있는 항목을 먼저 보여주고, 나머지는 가나다순으로 정렬 people = base_filter.annotate( sequence_order=Case( When(SEQUENCE__isnull=True, then=Value(1)), default=Value(0), output_field=IntegerField(), ) ).order_by('sequence_order', 'SEQUENCE', '이름') print(f"[DEBUG] 메인 페이지 표시: {people.count()}명") print(f"[DEBUG] === 표시되는 사람들 ===") for person in people: status = "회원가입" if person.user else "미가입" print(f"[DEBUG] - {person.이름} (상태: {status}, 소속: {person.소속})") print(f"[DEBUG] === 표시 끝 ===") return render(request, 'B_main/main.htm', {'people': people}) def search_people(request): auth_check = check_authentication(request) if auth_check: return auth_check query = request.GET.get('q', '') print(f"[DEBUG] 검색 쿼리: '{query}'") # 현재 사용자의 Person 정보 가져오기 current_user_person = None if request.user.is_authenticated: try: current_user_person = Person.objects.get(user=request.user) except Person.DoesNotExist: pass # 기본 필터: 모든 사람 base_filter = Person.objects.all() # 현재 사용자의 권한에 따라 추가 필터 적용 if current_user_person and not current_user_person.모든사람보기권한: # 모든사람보기권한이 False인 경우 회원가입한 사람만 표시 (user가 있는 사람들) base_filter = base_filter.filter(user__isnull=False) print(f"[DEBUG] 검색 - 회원가입자만 표시 모드: {current_user_person.이름}") else: print(f"[DEBUG] 검색 - 모든 사람 표시 모드") if query: # 이름, 소속, 직책, 키워드로 검색 # 순서가 있는 항목을 먼저 보여주고, 나머지는 가나다순으로 정렬 people = base_filter.filter( Q(이름__icontains=query) | Q(소속__icontains=query) | Q(TITLE__icontains=query) | Q(직책__icontains=query) | Q(keyword1__icontains=query) | Q(생년월일__icontains=query) ).filter( 이름__isnull=False ).exclude( 이름__exact='' ).annotate( sequence_order=Case( When(SEQUENCE__isnull=True, then=Value(1)), default=Value(0), output_field=IntegerField(), ) ).order_by('sequence_order', 'SEQUENCE', '이름') print(f"[DEBUG] 검색 결과: {people.count()}명") for person in people: print(f"[DEBUG] - {person.이름} (소속: {person.소속}, 직책: {person.직책})") else: # 순서가 있는 항목을 먼저 보여주고, 나머지는 가나다순으로 정렬 people = base_filter.filter( 이름__isnull=False ).exclude( 이름__exact='' ).annotate( sequence_order=Case( When(SEQUENCE__isnull=True, then=Value(1)), default=Value(0), output_field=IntegerField(), ) ).order_by('sequence_order', 'SEQUENCE', '이름') print(f"[DEBUG] 전체 목록: {people.count()}명") return render(request, 'B_main/partials/card_list.htm', {'people': people}) def vcard_download(request, name): auth_check = check_authentication(request) if auth_check: return auth_check name = unquote(name) if not name: return HttpResponse("Invalid name", status=400) person = get_object_or_404(Person, 이름=name) vcard_content = f"""BEGIN:VCARD VERSION:3.0 N:{person.이름};;;; FN:{person.이름} ORG:{person.소속} TITLE:{person.직책} TEL;CELL:{person.연락처} ADR:;;{person.주소} END:VCARD """ response = HttpResponse(vcard_content, content_type='text/vcard') response['Content-Disposition'] = f'attachment; filename="{person.이름}.vcf"' return response def logout_view(request): request.session.flush() return redirect('/password/') @login_required def my_profile(request): try: person = Person.objects.get(user=request.user) except Person.DoesNotExist: person = None if request.method == 'POST': form = PersonForm(request.POST, instance=person) if form.is_valid(): person = form.save(commit=False) person.user = request.user person.save() return redirect('main') # or any success page else: form = PersonForm(instance=person) return render(request, 'B_main/profile_form.htm', {'form': form}) from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods @login_required @csrf_exempt @require_http_methods(["POST"]) def withdraw(request): """회원탈퇴 뷰""" try: # 현재 사용자의 Person 정보 가져오기 person = Person.objects.get(user=request.user) # User 연결 해제 person.user = None person.save() # User 객체 삭제 (전화번호 계정 삭제) user_phone = request.user.username request.user.delete() # 로그아웃 logout(request) print(f"[DEBUG] 회원탈퇴 완료: {user_phone} (User 삭제, Person 연결 해제)") return JsonResponse({'success': True}) except Person.DoesNotExist: return JsonResponse({'success': False, 'error': 'Person 정보를 찾을 수 없습니다.'}) except Exception as e: return JsonResponse({'success': False, 'error': str(e)}) def session_logout(request): try: del request.session['authenticated'] except KeyError: pass return redirect('/') def signup_view(request): import random from .forms import is_allowed_person from django.contrib.auth import login # GET 요청 시 세션 초기화 (새로운 회원가입 시작) # 단, 인증번호 확인 후 리다이렉트된 경우는 세션 유지 if request.method == 'GET' and not request.session.get('signup_verified'): for key in ['signup_code', 'signup_name', 'signup_phone', 'signup_verified', 'signup_step']: request.session.pop(key, None) request.session['signup_step'] = 1 request.session['signup_verified'] = False step = request.session.get('signup_step', 1) name = request.session.get('signup_name') phone = request.session.get('signup_phone') code_sent = bool(request.session.get('signup_code')) verified = request.session.get('signup_verified', False) # 1단계: 이름, 전화번호, 인증번호 if step == 1: if request.method == 'POST': form = Step1PhoneForm(request.POST) action = request.POST.get('action') if action == 'send_code': if form.is_valid(): name = form.cleaned_data['name'] phone = form.cleaned_data['phone'] # 폼 검증에서 이미 허가되지 않은 사용자 체크를 했으므로 여기서는 제거 code = str(random.randint(100000, 999999)) request.session['signup_code'] = code request.session['signup_name'] = name request.session['signup_phone'] = phone request.session['signup_verified'] = False print(f"[DEBUG] 인증번호 발송: {name} ({phone}) - {code}") return render(request, 'B_main/signup.html', { 'step': 1, 'form1': form, 'code_sent': True, 'message': '인증번호가 발송되었습니다.' }) else: # 폼 에러 메시지 확인 error_message = '입력 정보를 확인해주세요.' if form.errors: # 첫 번째 에러 메시지 사용 for field_errors in form.errors.values(): if field_errors: error_message = field_errors[0] break return render(request, 'B_main/signup.html', { 'step': 1, 'form1': form, 'code_sent': False, 'error': error_message }) elif action == 'verify_code': if form.is_valid(): verification_code = form.cleaned_data['verification_code'] session_code = request.session.get('signup_code') if verification_code and verification_code == session_code: # 인증 성공 request.session['signup_verified'] = True request.session['signup_step'] = 2 return redirect('signup') else: return render(request, 'B_main/signup.html', { 'step': 1, 'form1': form, 'code_sent': True, 'error': '인증번호가 올바르지 않습니다.' }) else: return render(request, 'B_main/signup.html', {'step': 1, 'form1': form, 'code_sent': code_sent}) else: form = Step1PhoneForm() return render(request, 'B_main/signup.html', {'step': 1, 'form1': form, 'code_sent': False}) # 2단계: 이메일, 비밀번호, 비밀번호 확인 if step == 2 and verified and name and phone: if request.method == 'POST': form2 = Step2AccountForm(request.POST) if form2.is_valid(): user = form2.save(name, phone, request) login(request, user, backend='django.contrib.auth.backends.ModelBackend') # 세션 정리 for key in ['signup_code', 'signup_name', 'signup_phone', 'signup_verified', 'signup_step']: request.session.pop(key, None) return redirect('main') else: return render(request, 'B_main/signup.html', {'step': 2, 'form2': form2, 'name': name, 'phone': phone}) else: form2 = Step2AccountForm() return render(request, 'B_main/signup.html', {'step': 2, 'form2': form2, 'name': name, 'phone': phone}) # 기본: 1단계로 초기화 request.session['signup_step'] = 1 request.session['signup_verified'] = False return redirect('signup') def privacy_policy(request): """개인정보처리방침 페이지""" return render(request, 'privacy_policy.html')