387 lines
15 KiB
Python
387 lines
15 KiB
Python
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') |