-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathaccount.py
More file actions
287 lines (253 loc) · 13.7 KB
/
account.py
File metadata and controls
287 lines (253 loc) · 13.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
"""
CodeCraft PMS Backend Project
파일명 : account.py
생성자 : 김창환
생성일 : 2024/10/16
업데이트 : 2025/04/08
설명 : 계정 생성, 로그인, 세션 관리를 위한 API 엔드포인트 정의
"""
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from logger import logger
import sys, os, random, string, logging
sys.path.append(os.path.abspath('/data/Database Project')) # Database Project와 연동하기 위해 사용
import account_DB
router = APIRouter()
class SignUp_Payload(BaseModel):
name: str
univ_id: int
email: str
id: str
pw: str
department: int
class Signin_Payload(BaseModel):
id: str
pw: str
class SignOut_Payload(BaseModel):
token: str
class DelAcc_Payload(BaseModel):
id: str
# class Usrpm_Payload(BaseModel): 미사용 비활성화 (25.02.11)
# token: str
class Checksession_Payload(BaseModel):
user_id: str
token: str
class AccCheck_Payload(BaseModel):
univ_id: int
name: str
email: str
user_id: str
class PwReset_Payload(BaseModel):
univ_id: int
pw: str
class FineName_Payload(BaseModel):
univ_id: int
class LoadProfPayload(BaseModel):
subj_no: int
class LoadAccountPayload(BaseModel):
univ_id: int
class EditAccountPayload(BaseModel):
univ_id: int
pw: str
dept: int
email: str
def generate_token():
"""랜덤한 15자리 토큰 생성"""
characters = string.ascii_letters + string.digits + string.punctuation
return ''.join(random.choices(characters, k=15))
@router.post("/acc/checksession")
async def check_session(payload: Checksession_Payload):
"""세션 유효성 확인"""
try:
is_valid = account_DB.validate_user_token(payload.user_id, payload.token)
if isinstance(is_valid, Exception):
logger.error(f"Invalid session for user {payload.user_id}: {str(is_valid)}", exc_info=True)
raise HTTPException(status_code=401, detail=f"Invalid session: {str(is_valid)}")
if is_valid:
logger.info(f"Session valid for user {payload.user_id}")
return {"RESULT_CODE": 200, "RESULT_MSG": "Session valid"}
logger.warning(f"Invalid session token for user {payload.user_id}")
raise HTTPException(status_code=401, detail="Invalid session token")
except Exception as e:
#logger.error(f"Unexpected error validating session for user {payload.user_id}: {str(e)}", exc_info=True) # 로그 가시성 하락으로 인한 임시 비활성화 (25.03.25)
raise HTTPException(status_code=500, detail=f"Unexpected error validating session: {str(e)}")
@router.post("/acc/signup")
async def api_acc_signup_post(payload: SignUp_Payload):
"""사용자 가입"""
try:
token = generate_token()
result = account_DB.insert_user(payload, token)
if isinstance(result, tuple) and result[0] == 1062:
logger.warning(f"Duplicate signup attempt: {payload.univ_id} is already registered")
return {"RESULT_CODE": 409, "RESULT_MSG": "Duplicate entry: This univ_id is already registered"}
logger.info(f"User {payload.univ_id} signed up successfully")
return {"RESULT_CODE": 200, "RESULT_MSG": "Signup successful", "Result": result}
except Exception as e:
logger.error(f"Unhandled exception during signup: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unhandled exception during signup: {str(e)}")
@router.post("/acc/signin")
async def api_acc_signin_post(payload: Signin_Payload):
"""사용자 로그인"""
try:
s_no = account_DB.validate_user(payload.id, payload.pw)
if s_no is None:
logger.warning(f"Invalid login attempt: {payload.id}")
raise HTTPException(status_code=401, detail="Invalid credentials")
if isinstance(s_no, Exception):
logger.error(f"Internal error during validation: {str(s_no)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Internal error during validation: {str(s_no)}")
token = generate_token()
save_result = account_DB.save_signin_user_token(payload.id, token)
if isinstance(save_result, Exception):
logger.error(f"Error saving session token for user {payload.id}: {str(save_result)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error saving session token: {str(save_result)}")
logger.info(f"User {payload.id} signed in successfully")
return {
"RESULT_CODE": 200,
"RESULT_MSG": "Login successful",
"PAYLOADS": {
"Result": save_result
}
}
except HTTPException as http_err:
raise http_err
except Exception as e:
logger.error(f"Unhandled exception during login for user {payload.id}: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unhandled exception during login: {str(e)}")
@router.post("/acc/signout")
async def api_acc_signout_post(payload: SignOut_Payload):
"""사용자 로그아웃"""
try:
result = account_DB.signout_user(payload.token)
if isinstance(result, Exception):
logger.error(f"Error during logout: {str(result)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error during logout: {str(result)}")
if result is True:
logger.info("User logged out successfully")
return {"RESULT_CODE": 200, "RESULT_MSG": "Logout successful"}
logger.warning("Logout failed")
raise HTTPException(status_code=500, detail="Logout failed")
except Exception as e:
logger.error(f"Unhandled exception during logout: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unhandled exception during logout: {str(e)}")
@router.post("/acc/delacc")
async def api_acc_delacc_post(payload: DelAcc_Payload):
"""계정 삭제"""
try:
result = account_DB.delete_user(payload.id)
if isinstance(result, Exception):
logger.error(f"Error during account deletion: {str(result)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error during account deletion: {str(result)}")
if result is True:
logger.info(f"Account {payload.id} deleted successfully")
return {"RESULT_CODE": 200, "RESULT_MSG": "Account deleted successfully"}
logger.warning(f"Account deletion failed for {payload.id}")
raise HTTPException(status_code=500, detail="Account deletion failed")
except Exception as e:
logger.error(f"Unhandled exception during account deletion: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unhandled exception during account deletion: {str(e)}")
@router.post("/acc/checkacc")
async def api_acc_check(payload: AccCheck_Payload):
"""
비밀번호 리셋 전 정보 확인 함수
비밀번호 찾기 기능의 경우, 먼저 이 엔드포인트를 통해 Return 값이 200인지 확인 후,
맞다면 api_acc_pwreset 함수 실행
"""
try:
result = account_DB.find_user_pw(
univ_id=payload.univ_id,
name=payload.name,
email=payload.email,
id=payload.user_id
)
if result is True:
logger.info(f"Account validation successful for user {payload.user_id}")
return {"RESULT_CODE": 200, "RESULT_MSG": "OK"}
logger.warning(f"Account validation failed for user {payload.user_id}")
return {"RESULT_CODE": 400, "RESULT_MSG": "Account validation failed"}
except Exception as e:
logger.error(f"Unhandled exception during account validation for user {payload.user_id}: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unhandled exception during account validation: {str(e)}")
@router.post("/acc/resetpw")
async def api_acc_pwreset(payload: PwReset_Payload):
"""비밀번호 리셋(변경) 함수"""
try:
result = account_DB.edit_user_pw(payload.univ_id, payload.pw)
if result is True:
logger.info(f"Password reset successful for user {payload.univ_id}")
return {"RESULT_CODE": 200, "RESULT_MSG": "OK"}
logger.warning(f"Password update failed for user {payload.univ_id}")
return {"RESULT_CODE": 400, "RESULT_MSG": "Password update failed"}
except Exception as e:
logger.error(f"Unhandled exception while updating password for user {payload.univ_id}: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unhandled exception while updating password: {str(e)}")
@router.post("/acc/find_sname")
async def api_acc_find_student_name(payload: FineName_Payload):
"""학번으로 학생 이름을 찾는 기능"""
try:
result = account_DB.fetch_student_name(payload.univ_id)
if isinstance(result, Exception) or result is None:
logger.error(f"Error in find student name operation for univ_id {payload.univ_id}: {str(result)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error in find student name Operation: {str(result)}")
logger.info(f"Student name found for univ_id {payload.univ_id}: {result}")
return {"RESULT_CODE": 200, "RESULT_MSG": "Find Successful.", "PAYLOAD": {"Result": result}}
except Exception as e:
logger.error(f"Unexpected error in find student name operation for univ_id {payload.univ_id}: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unexpected error in find student name Operation: {str(e)}")
@router.post("/acc/load_dept")
async def api_acc_load_department():
"""모든 학과를 조회하는 기능"""
try:
result = account_DB.fetch_dept_list()
if isinstance(result, Exception):
logger.error(f"Error in load dept operation: {str(result)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error in load dept Operation: {str(result)}")
logger.info("Department list retrieved successfully")
return {"RESULT_CODE": 200, "RESULT_MSG": "Load Successful.", "PAYLOAD": {"Result": result}}
except Exception as e:
logger.error(f"Unexpected error in load dept operation: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unexpected error in load dept Operation: {str(e)}")
@router.post("/acc/load_prof")
async def api_acc_load_professor_by_subject(payload: LoadProfPayload):
"""특정 교과목이 속한 학과의 교수 리스트를 불러오는 기능"""
try:
result = account_DB.fetch_professor_list_by_subject(payload.subj_no)
if isinstance(result, Exception):
logger.error(f"Error in load professor operation for subject {payload.subj_no}: {str(result)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error in load professor operation: {str(result)}")
logger.info(f"Professor list retrieved successfully for subject {payload.subj_no}")
return {"RESULT_CODE": 200, "RESULT_MSG": "Load Successful.", "PAYLOAD": {"Result": result}}
except Exception as e:
logger.error(f"Unexpected error in load professor operation for subject {payload.subj_no}: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unexpected error in load professor operation: {str(e)}")
@router.post("/acc/load_acc")
async def api_acc_load_account_info(payload: LoadAccountPayload):
"""학번으로 해당 계정의 모든 정보를 불러오는 기능"""
try:
result = account_DB.fetch_student_info(payload.univ_id)
if isinstance(result, Exception):
logger.error(f"Error in load account operation for univ_id {payload.univ_id}: {str(result)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error in load account operation: {str(result)}")
logger.info(f"Account info retrieved successfully for univ_id: {payload.univ_id}")
return {"RESULT_CODE": 200, "RESULT_MSG": "Load Successful.", "PAYLOAD": {"Result": result}}
except Exception as e:
logger.error(f"Unexpected error in load account operation for univ_id {payload.univ_id}: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unexpected error in load account operation: {str(e)}")
@router.post("/acc/edit_acc")
async def api_acc_edit_account_info(payload: EditAccountPayload):
"""학번으로 해당 계정의 특정 정보를 수정하는 기능"""
try:
result = account_DB.edit_student_info(
pw = payload.pw,
email = payload.email,
dno = payload.dept,
univ_id = payload.univ_id
)
if isinstance(result, Exception):
logger.error(f"Error in edit account operation for univ_id {payload.univ_id}: {str(result)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error in edit account operation: {str(result)}")
logger.info(f"Account edited successfully for univ_id: {payload.univ_id}")
return {"RESULT_CODE": 200, "RESULT_MSG": "Edit Successful.", "PAYLOAD": {"Result": result}}
except Exception as e:
logger.error(f"Unexpected error in edit account operation for univ_id {payload.univ_id}: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Unexpected error in edit account operation: {str(e)}")