From 47c6a476a5c9567839da2fbe2989f3be7a0b8a58 Mon Sep 17 00:00:00 2001 From: eld_master Date: Mon, 20 Jan 2025 14:46:25 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BD=94=EB=93=9C=201=EC=B0=A8=20=EC=B5=9C?= =?UTF-8?q?=EC=A2=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...df-firebase-adminsdk-fv5tf-0c2be71530.json | 13 + ...c2-firebase-adminsdk-4ysfn-6585b694d2.json | 13 - fastapi/app/common/config.py | 6 +- fastapi/app/db/crud_inquiry.py | 44 ++ fastapi/app/db/crud_room_score.py | 584 ++++++++++++++---- fastapi/app/db/crud_survey.py | 55 ++ fastapi/app/db/crud_user.py | 273 +++++--- fastapi/app/main.py | 8 + fastapi/app/process/firebase/firebase_app.py | 4 +- .../app/process/firebase/firebase_process.py | 159 ++++- fastapi/app/process/inquiry/manage_inquiry.py | 26 + .../app/process/room/connect_kafka_process.py | 73 +++ fastapi/app/process/room/room_score.py | 183 +++++- fastapi/app/process/survey/manage_survey.py | 26 + fastapi/app/process/user/manage_user.py | 93 ++- .../app/process/user/manage_user_pattern.py | 2 +- fastapi/app/router/inquiry_api.py | 99 +++ fastapi/app/router/manage_user_api.py | 191 +++++- fastapi/app/router/room_score_api.py | 266 +++++++- fastapi/app/router/survey_api.py | 107 ++++ 20 files changed, 1899 insertions(+), 326 deletions(-) create mode 100644 fastapi/app/allscore-29edf-firebase-adminsdk-fv5tf-0c2be71530.json delete mode 100644 fastapi/app/allscore-344c2-firebase-adminsdk-4ysfn-6585b694d2.json create mode 100644 fastapi/app/db/crud_inquiry.py create mode 100644 fastapi/app/db/crud_survey.py create mode 100644 fastapi/app/process/inquiry/manage_inquiry.py create mode 100644 fastapi/app/process/room/connect_kafka_process.py create mode 100644 fastapi/app/process/survey/manage_survey.py create mode 100644 fastapi/app/router/inquiry_api.py create mode 100644 fastapi/app/router/survey_api.py diff --git a/fastapi/app/allscore-29edf-firebase-adminsdk-fv5tf-0c2be71530.json b/fastapi/app/allscore-29edf-firebase-adminsdk-fv5tf-0c2be71530.json new file mode 100644 index 0000000..65f1b79 --- /dev/null +++ b/fastapi/app/allscore-29edf-firebase-adminsdk-fv5tf-0c2be71530.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "allscore-29edf", + "private_key_id": "0c2be71530584244a0595233db85e7bd120985b3", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDOQgt7aMLc6u3u\nHarh0MMpCL4lh5JZWIYKgd9CvP6DWdunXu0HJFPiY3wK4qhfZ9UQ7az36jKbOox1\nhyAS6k/2cl++Wr0KlJX1c7YODYsyG/tGoucF9AOPKW8yDqvTBLati53PRSOvt/L3\nt6SXEW2oUL2Z+ZxrfU8scbl6yvxvapSTqKifBi9fFiAaJriF03KeALozG1zoVTIy\nL+H3/oLr1RL5K1a8CMKfPZlBMnwAqSeH+Mwm6QMmphzjZ4FUfXfstEaENoxzZ6HK\nq5EFbLzr6X4jCTzXrKXciaAGVf1NheWVZ/tEizj18HHhvfNgZYCphsCEOX0Pimim\np8xpfnA7AgMBAAECggEAFU9HhmmNcGupR2ezRv9dmni3xILcQPTfbGh8m5WRKhr3\nkbRCAvHi5Mnof+to/+pnXgdgToDY16bV6jKawrmIp2qrr6wKSfSOBbz9uzf1AKlZ\nbbPY8ImEcJ8USPSxFe0vvoBlPovjIv17UdKcY6s+TByDakwauBRLQMlDI4ejSxNl\nYN+/f/5lrPQUYiEa+qtNDnOFYNkiVJGDNdfG1hQju/zVyUcTUBf8wGeRZv9pwoV4\naK0U8acnXrvVFM5YkMEAJMOkUJjc6Xp+vhBasJhSs5Qz6x9Le+89/vljFCGKiPkG\nNxzvN0LojO7idbQy0YyCQj2tK/E7v8meOFc1I28/kQKBgQDuVG4HQn3diYuXqbfV\nAozKyRJz9deGPAkG4DDxJi3YV2WqqWWjRl/kw8yAq9+P0ADIVkIdDgpVgd4qKMre\n2d8ug6K6/xE0jwPRUCB46BPwn/Df/hJ6qXjzfRu9emK5CMoLKmAAX5qMg6GcOMLm\n/wi2AGGwEgG6hBf0BbKZ4KUDMwKBgQDdjOHq++X7uzxe15fxxmm22dyf1L5UqVq7\n2RXdWpGSQ6e2a1b52i447C3ESYZ26URVbyIv9TaBkD5VO7YHHvMYOxBetU6Sq9Az\n0Vj4PoEXKTDu7a4bGNATFAZm0X59TUHgYvjrf7j9NgZqt0j9RDzZ1NDZfMBCcwv+\nqxywX8Ze2QKBgHc6gbjcCL+VmeILo83KcsjYAoVEjce3rQRlj9Z0NScvwcq46AHg\nqQR2942/bh4x/tI6ZOTIK19PkucgdS07ba2FaRmHlQHoMg66uSQDZkZQnV5Rask2\nky2sfv4xhcXvobQoRNKrAVQeXfEbbFXHbIIweq5ss7StdJY9a3YTrjmFAoGAJKwN\nOTg4+VIkzA4juIF/PiURv+MXHixqOG3WkK1NK0jHmgpqezECNaniaXtCJqy2Au5C\nWm3cd9XIe5NGricRVhFwxDx+pQiLjgg5Ed5Gv+6xitsM1q9kwcOuy5Yhudvv65R2\nX4TkugUXStLL4iBJckUnzNg5esZQVfc86HTyAQECgYA0eKWuxucoiiM5midcbxBA\nJaDAv0jgxun5uINY8m1/wpUr69xa46KhNXx4CGVKj3EDi/vZIcRitb6UqNvASCA5\nIq1JOyc++bzycEaXPsOBRv+euv4g5LjnApADjLwqHQ9zUzgCK6HYUu50afNxRv3y\n3ldCiMZ8eFue0MJ5YOZqeQ==\n-----END PRIVATE KEY-----\n", + "client_email": "firebase-adminsdk-fv5tf@allscore-29edf.iam.gserviceaccount.com", + "client_id": "114174349196452622474", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fv5tf%40allscore-29edf.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" +} diff --git a/fastapi/app/allscore-344c2-firebase-adminsdk-4ysfn-6585b694d2.json b/fastapi/app/allscore-344c2-firebase-adminsdk-4ysfn-6585b694d2.json deleted file mode 100644 index 61dfd02..0000000 --- a/fastapi/app/allscore-344c2-firebase-adminsdk-4ysfn-6585b694d2.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "service_account", - "project_id": "allscore-344c2", - "private_key_id": "6585b694d2d1bdc2fa55093a63c576de8f8d7b66", - "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6ZBIiruCz51cq\nUOtsVOLyrxD1xkYQLQFI7Xml3BpI3+cxM0DF6ZShbndNB978pFoLxH7tKZgwUvhT\nxYGvpJeYu4LIbZtSq03FaqarRkGF9J1zmiHOJs2RcI+NNL6+ltQUkBCa0zyr2BUN\nfSIP5Y11D/sW5fvqDaLOGdzY8jwMTtI1yRlLXC/ILiMQvqnhNKBRE1cHB1r+DXS/\nIZ918LXsq38xQKYQhbV43s+9y+uoVtmucMwHbpEyZY2CE2k+XPoxgfJzsmRcQsMH\nn0QCscXFfMn7MoKp31YmCTAl2offh+P2NYf2RLmwr3fZIgNAPcjbefxGrXtF5ELb\nPa4g2BQnAgMBAAECggEAF6UALp7T6cksDosrV5fBHnDE4a4K+fGrmw5nrc7+apuK\nCXzAom/00dxgjUi1VIPzhFCjRVSkdg+LFEgWy9WWVuKv6YW1/Bu3sZZ2RCiVFqLR\nonY9WZh54BGmXuRVBM+/YZ27mC25zEGMvM77QNxUQIhhctCD+iH2stcnDpepXxTH\n01ebvk2CBTaL3Zk0YZeA0tSaf1qx+BSQsXUPzrxNwwkVvjVIF+wXkm2t0WRI1yJ8\nBJTB++xWmUjA5Uj57MV0u10Y1HA0sBcebUOudf/X3ayMIMTkuHGf5IUju0rWzO5H\nDyKHF43z9a1p4J5MFgRfzLHfegzkq4m/dofNRgRaoQKBgQDmKHGkFLV9fC5GoTvV\n1SyfLf9QC7uj1ju5zfhdCp05QGOJiEMGRfzHtmtaOk8JCfKAZpkIbeJ0KpT4NiOa\nnUseELEWjtKDDdeuwGUic8PxMxeQ9sLuaUh8RhWMk0CoGUiabZSuIh8+yOTkNSX7\nAa+fjf4uXOEn570LEgpr3MVctwKBgQDPUZsbUnhATPznDfpte54A1t+uDb6yEkda\n3kMTehfJBKFGgzz3Ny0MeYF2TUI/s8sMQYGmfXG34MJCUcfx1952MIE+YiC0fm4U\nunMthqWNyLtTO5B4nFH9AToyn0KDMBwp0ziMk97WDYgZSj/Q49YRX+hfv+3jVK08\n45I1fhZ0EQKBgGgMyLNhGVuNlG4h3ichpHaiGNZbN40uAPpS/4EwlzuWvGkkzQg9\nA7ZV5dp4mdqAQL2DpJOG+eWCiq5b62Suz5LcAPMtxkWxMFy0ZgRZSa/1ZSYIKMAX\noMlt9bgDqitUotoNyDWg/3cm4zO4Q19it77uNodHPhMIVRJ4KXXx7NepAoGASkko\nddrQIeI0QKp+kFpaHFziG2Drcq0gCkxX5pO6EBprm3ONFdwcdTrYi8ZVNbQ7znFu\nfnS2mbecg9z/8wVxvhHVTcAljec7lIvWl3qGuc4yaTmPo9gHfMvCyb7NO2qyvL3l\npmGZ2ENTABTd1wC8hM9D2YNRP0LpLEcy7Z33d7ECgYEAyIJAv4BCBtNAtmzMI6i3\neYGYqAEd3N5KNwhgLF0mXbMtUOXSEFFz+GTziD298+WfBs8BF+kWYsZq0+kzHiLQ\n2+eLI7MMRDDpc9l6tHb0NvSAkXJLKJMqqVOCcs3Z+2QWciJAlBYuabMN9CENI2Y3\nSfXa16nIAK5PzY/pi8lzGiA=\n-----END PRIVATE KEY-----\n", - "client_email": "firebase-adminsdk-4ysfn@allscore-344c2.iam.gserviceaccount.com", - "client_id": "111803986360921277629", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-4ysfn%40allscore-344c2.iam.gserviceaccount.com", - "universe_domain": "googleapis.com" -} diff --git a/fastapi/app/common/config.py b/fastapi/app/common/config.py index 6cf4076..1e0ce1c 100644 --- a/fastapi/app/common/config.py +++ b/fastapi/app/common/config.py @@ -8,4 +8,8 @@ SECRET_KEY = 'ALLSCORE' SMTP_USERNAME = 'aofhd0003@gmail.com' SMTP_PASSWORD = 'jueyodpzlvisrtto' SMTP_SERVER = 'smtp.gmail.com' -SMTP_PORT = 587 \ No newline at end of file +SMTP_PORT = 587 + +# 구글 클라이언트 ID +GOOGLE_CLIENT_ID = '19981745655-3dadv7n64jqcada6mtc1ao25k1m90gp3.apps.googleusercontent.com' + diff --git a/fastapi/app/db/crud_inquiry.py b/fastapi/app/db/crud_inquiry.py new file mode 100644 index 0000000..41b4090 --- /dev/null +++ b/fastapi/app/db/crud_inquiry.py @@ -0,0 +1,44 @@ +from sqlalchemy.orm import Session +from sqlalchemy import text +from db import models, schemas +from process.logger import logger +from db.base import get_db + + +#================================================================================================== +# 문의 관련 +#================================================================================================== + +# 문의 저장 +async def insert_inquiry(inquiry, db): + try: + query = text(""" + INSERT INTO inquiry ( + user_seq, + user_email, + nickname, + title, + contents + ) + VALUES ( + :user_seq, + (select user_email from manage_user where user_seq = :user_seq), + (select nickname from manage_user where user_seq = :user_seq), + :title, + :contents + ) + """) + params = { + "user_seq": inquiry['user_seq'], + "title": inquiry['title'], + "contents": inquiry['contents'] + } + + db.execute(query, params) + + db.commit() + return True + except Exception as e: + logger.error(f"sql error: {e}") + return False + diff --git a/fastapi/app/db/crud_room_score.py b/fastapi/app/db/crud_room_score.py index d9ed914..e212e90 100644 --- a/fastapi/app/db/crud_room_score.py +++ b/fastapi/app/db/crud_room_score.py @@ -10,31 +10,49 @@ from db.base import get_db # ================================================================ # 방 생성 -def create_room(data, db): +async def create_room(data, db): query = text(f""" insert into room_main(room_type_seq, master_user_seq, room_title, room_intro, open_yn, room_pw, running_time, number_of_people, number_of_teams, score_open_range, room_status, create_dt, update_dt, start_dt, end_dt, delete_dt, delete_yn) values( - (select room_type_seq from room_type where room_type_name = '{str(data['room_type']).upper()}'), - {data['user_seq']}, - '{data['room_title']}', - '{data['room_intro']}', - '{data['open_yn']}', - '{data['room_pw']}', - {data['running_time']}, - {data['number_of_people']}, - {data['number_of_teams']}, - '{data['score_open_range']}', - (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = '{data['room_status']}'), - '{data['create_dt']}', - '{data['update_dt']}', - {data['start_dt']}, - {data['end_dt']}, - {data['delete_dt']}, + (select room_type_seq from room_type where room_type_name = :room_type), + :master_user_seq, + :room_title, + :room_intro, + :open_yn, + :room_pw, + :running_time, + :number_of_people, + :number_of_teams, + :score_open_range, + (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = :room_status), + :create_dt, + :update_dt, + :start_dt, + :end_dt, + :delete_dt, 'N' ) """) + params = { + "room_type": data['room_type'].upper(), + "master_user_seq": data['user_seq'], + "room_title": data['room_title'], + "room_intro": data['room_intro'], + "open_yn": data['open_yn'], + "room_pw": data['room_pw'], + "running_time": data['running_time'], + "number_of_people": data['number_of_people'], + "number_of_teams": data['number_of_teams'], + "score_open_range": data['score_open_range'], + "room_status": data['room_status'].upper(), + "create_dt": None if data['create_dt'] == 'null' else data['create_dt'], + "update_dt": None if data['update_dt'] == 'null' else data['update_dt'], + "start_dt": None if data['start_dt'] == 'null' else data['start_dt'], + "end_dt": None if data['end_dt'] == 'null' else data['end_dt'], + "delete_dt": None if data['delete_dt'] == 'null' else data['delete_dt'], + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -48,9 +66,12 @@ async def verify_room_type(room_type, db): select count(room_type_seq) from room_type - where room_type_name = '{str(room_type).upper()}' + where room_type_name = :room_type """) - return db.execute(query).fetchall() + params = { + "room_type": room_type.upper(), + } + return db.execute(query, params).fetchall() # room_status 검증 @@ -60,9 +81,12 @@ async def verify_room_status(room_status, db): count(reserve_code) from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' - and reserve_code = '{room_status}' + and reserve_code = :room_status """) - return db.execute(query).fetchall() + params = { + "room_status": room_status.upper(), + } + return db.execute(query, params).fetchall() # room_seq 조회 @@ -71,14 +95,21 @@ async def select_room_seq_by_data(data, db): select room_seq from room_main - where room_type_seq = (select room_type_seq from room_type where room_type_name = '{str(data['room_type']).upper()}') - and master_user_seq = {data['user_seq']} - and room_title = '{data['room_title']}' - and room_intro = '{data['room_intro']}' - and create_dt = '{data['create_dt']}' + where room_type_seq = (select room_type_seq from room_type where room_type_name = :room_type) + and master_user_seq = :user_seq + and room_title = :room_title + and room_intro = :room_intro + and create_dt = :create_dt order by room_seq desc """) - return db.execute(query).fetchall() + params = { + "room_type": data['room_type'].upper(), + "user_seq": data['user_seq'], + "room_title": data['room_title'], + "room_intro": data['room_intro'], + "create_dt": None if data['create_dt'] == 'null' else data['create_dt'], + } + return db.execute(query, params).fetchall() # 팀전일 경우 팀 이름 입력 @@ -102,30 +133,41 @@ async def insert_team_name(data, db): async def insert_creater_user_participant(data, db): if data['room_type'] == 'private': query = text(f""" - insert into room_score_participant(room_seq, participant_type, user_seq, nickname, team_name, score) + insert into room_score_participant(room_seq, participant_type, user_seq, nickname, team_name, score, department, introduce_myself, profile_img) values( - {data['room_seq']}, + :room_seq, (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TYPE' and reserve_code = 'ADMIN'), - {data['user_seq']}, - (select nickname from manage_user where user_seq = {data['user_seq']}), + :user_seq, + (select nickname from manage_user where user_seq = :user_seq), 'PRIVATE', - 0 + 0, + (select department from manage_user where user_seq = :user_seq), + (select introduce_myself from manage_user where user_seq = :user_seq), + (select profile_img from manage_user where user_seq = :user_seq) ) """) elif data['room_type'] == 'team': query = text(f""" - insert into room_score_participant(room_seq, participant_type, user_seq, nickname, team_name, score) + insert into room_score_participant(room_seq, participant_type, user_seq, nickname, team_name, score, department, introduce_myself, profile_img) values( - {data['room_seq']}, + :room_seq, (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TYPE' and reserve_code = 'ADMIN'), - {data['user_seq']}, - (select nickname from manage_user where user_seq = {data['user_seq']}), + :user_seq, + (select nickname from manage_user where user_seq = :user_seq), (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TEAM_NAME' and reserve_code = 'WAIT'), - 0 + 0, + (select department from manage_user where user_seq = :user_seq), + (select introduce_myself from manage_user where user_seq = :user_seq), + (select profile_img from manage_user where user_seq = :user_seq) ) """) + + params = { + 'room_seq': data['room_seq'], + 'user_seq': data['user_seq'], + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -143,21 +185,28 @@ async def select_user_info_by_user_seq(user_seq, db): department, introduce_myself from manage_user - where user_seq = {user_seq} + where user_seq = :user_seq """) - return db.execute(query).fetchall() + params = { + "user_seq": user_seq, + } + return db.execute(query, params).fetchall() # 방 참여자 조회 권한 확인 -async def check_auth_user(user_seq, room_type, room_seq, db): +async def check_auth_user(user_seq, room_seq, db): query = text(f""" select user_seq from room_score_participant - where room_seq = {room_seq} - and user_seq = {user_seq} + where room_seq = :room_seq + and user_seq = :user_seq """) - return db.execute(query).fetchall() + params = { + "room_seq": room_seq, + "user_seq": user_seq, + } + return db.execute(query, params).fetchall() # 참가자 정보 가져오기 @@ -175,7 +224,7 @@ async def participant_user_list(room_type, room_seq, db): from room_score_private_participant a left join manage_user b on a.user_seq = b.user_seq - where a.room_seq = {room_seq} + where a.room_seq = :room_seq """) elif room_type == 'team' or room_type == 'TEAM': query = text(f""" @@ -191,11 +240,14 @@ async def participant_user_list(room_type, room_seq, db): from room_score_team_participant a left join manage_user b on a.user_seq = b.user_seq - where a.room_seq = {room_seq} + where a.room_seq = :room_seq """) else: return [[]] - return db.execute(query).fetchall() + params = { + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 요청자가 방장인지 확인 @@ -204,9 +256,12 @@ async def check_requester_room_master_auth(room_seq, db): select master_user_seq from room_main - where room_seq = {room_seq} + where room_seq = :room_seq """) - return db.execute(query).fetchall() + params = { + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 팀전일 경우 team_name이 WAIT상태가 없는지 확인 @@ -215,23 +270,94 @@ async def check_granted_team_name(room_seq, db): select count(team_name) from room_score_participant - where room_seq = {room_seq} + where room_seq = :room_seq and participant_type = 'PLAYER' and team_name = (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TEAM_NAME' and reserve_code = 'WAIT') """) - return db.execute(query).fetchall() + params = { + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 요청자가 방장인지 확인 -async def update_room_status(room_seq, room_status, before_status, db): +async def update_room_status_start_dt_end_dt(room_seq, room_status, before_status, start_dt, end_dt, db): + start_dt_str = '' if start_dt == '' else f", start_dt = '{start_dt}'" + end_dt_str = '' if end_dt == '' else f", end_dt = '{end_dt}'" query = text(f""" update room_main - set room_status = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = '{room_status}') - where room_seq = {room_seq} - and room_status = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = '{before_status}') + set room_status = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = :room_status){start_dt_str} {end_dt_str} + where room_seq = :room_seq + and room_status = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = :before_status) """) + params = { + "room_seq": room_seq, + "room_status": room_status, + "before_status": before_status, + } try: - db.execute(query) + db.execute(query, params) + db.commit() + return True + except Exception as e: + logger.error(f"sql error: {e}") + return False + + +# 참여자 게임 참여 여부 업데이트 +async def update_participant_join_game_yn(room_seq, db): + query = text(f""" + update manage_user + set join_game_yn = 'Y' + where user_seq in (select user_seq from room_score_participant where room_seq = :room_seq) + """) + params = { + "room_seq": room_seq, + } + try: + db.execute(query, params) + db.commit() + return True + except Exception as e: + logger.error(f"sql error: {e}") + return False + + +# 시작시간 업데이트 +async def update_start_dt(room_seq, start_dt, db): + query = text(f""" + update room_main + set start_dt = :start_dt, + update_dt = :start_dt + where room_seq = :room_seq + """) + params = { + "room_seq": room_seq, + "start_dt": start_dt, + } + try: + db.execute(query, params) + db.commit() + return True + except Exception as e: + logger.error(f"sql error: {e}") + return False + + +# 종료시간 업데이트 +async def update_end_dt(room_seq, end_dt, db): + query = text(f""" + update room_main + set end_dt = :end_dt, + update_dt = :end_dt + where room_seq = :room_seq + """) + params = { + "room_seq": room_seq, + "end_dt": end_dt, + } + try: + db.execute(query, params) db.commit() return True except Exception as e: @@ -260,10 +386,12 @@ async def select_room_setting_info(room_seq, db): start_dt, update_dt from room_main - where room_seq = {room_seq} + where room_seq = :room_seq """) - - return db.execute(query).fetchall() + params = { + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 방 설정정보 수정하기 @@ -271,19 +399,31 @@ async def update_room_setting_info_room_main(data, db): query = text(f""" update room_main set - room_title = '{data['room_title']}', - room_intro = '{data['room_intro']}', - open_yn = '{data['open_yn']}', - room_pw = '{data['room_pw']}', - running_time = '{data['running_time']}', - number_of_people = '{data['number_of_people']}', - score_open_range = '{data['score_open_range']}', - room_status = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = '{data['room_status']}'), - update_dt = '{data['update_dt']}' - where room_seq = {data['room_seq']} + room_title = :room_title, + room_intro = :room_intro, + open_yn = :open_yn, + room_pw = :room_pw, + running_time = :running_time, + number_of_people = :number_of_people, + score_open_range = :score_open_range, + room_status = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = :room_status), + update_dt = :update_dt + where room_seq = :room_seq """) + params = { + "room_seq": data['room_seq'], + "room_title": data['room_title'], + "room_intro": data['room_intro'], + "open_yn": data['open_yn'], + "room_pw": data['room_pw'], + "running_time": data['running_time'], + "number_of_people": data['number_of_people'], + "score_open_range": data['score_open_range'], + "room_status": data['room_status'], + "update_dt": data['update_dt'], + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -295,11 +435,15 @@ async def update_room_setting_info_room_main(data, db): async def update_room_setting_info_room_score_private(data, db): query = text(f""" update room_score_private - set score_open_range = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_{str(data['room_type']).upper()}' and reserve_code = '{data['score_open_range']}') - where room_seq = {data['room_seq']} + set score_open_range = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_{str(data['room_type']).upper()}' and reserve_code = :score_open_range) + where room_seq = :room_seq """) + params = { + "room_seq": data['room_seq'], + "score_open_range": data['score_open_range'], + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -311,11 +455,15 @@ async def update_room_setting_info_room_score_private(data, db): async def update_room_setting_info_room_score_team(data, db): query = text(f""" update room_score_team - set score_open_range = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_{str(data['room_type']).upper()}' and reserve_code = '{data['score_open_range']}') - where room_seq = {data['room_seq']} + set score_open_range = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_{str(data['room_type']).upper()}' and reserve_code = :score_open_range) + where room_seq = :room_seq """) + params = { + "room_seq": data['room_seq'], + "score_open_range": data['score_open_range'], + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -329,22 +477,31 @@ async def select_master_user_seq_by_user_seq_and_room_seq(user_seq, room_seq, db select master_user_seq from room_main - where master_user_seq = {user_seq} - and room_seq = {room_seq} + where master_user_seq = :user_seq + and room_seq = :room_seq """) - return db.execute(query).fetchall() + params = { + "user_seq": user_seq, + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 팀명 수정하기 async def update_team_name(data, db): query = text(f""" update room_score_team_name - set team_name = '{data['after_team_name']}' - where room_seq = {data['room_seq']} - and team_name = '{data['before_team_name']}' + set team_name = :after_team_name + where room_seq = :room_seq + and team_name = :before_team_name """) + params = { + "room_seq": data['room_seq'], + "after_team_name": data['after_team_name'], + "before_team_name": data['before_team_name'], + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -356,12 +513,17 @@ async def update_team_name(data, db): async def update_team_name_participant(data, db): query = text(f""" update room_score_participant - set team_name = '{data['after_team_name']}' - where room_seq = {data['room_seq']} - and team_name = '{data['before_team_name']}' + set team_name = :after_team_name + where room_seq = :room_seq + and team_name = :before_team_name """) + params = { + "room_seq": data['room_seq'], + "after_team_name": data['after_team_name'], + "before_team_name": data['before_team_name'], + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -374,24 +536,30 @@ async def update_participant_role(data, db): if data['room_type_name'] == 'private' or data['room_type_name'] == 'PRIVATE': query = text(f""" update room_score_participant - set participant_type = (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TYPE' and reserve_code = '{data['participant_type']}'), + set participant_type = (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TYPE' and reserve_code = :participant_type), team_name = 'PRIVATE' - where room_seq = {data['room_seq']} - and user_seq = {data['target_user_seq']} + where room_seq = :room_seq + and user_seq = :target_user_seq """) elif data['room_type_name'] == 'team' or data['room_type_name'] == 'TEAM': team_name_str = f"'WAIT'" if data['team_name'] == 'WAIT' else f"(select team_name from room_score_team_name where room_seq = {data['room_seq']} and team_name = '{data['team_name']}')" query = text(f""" update room_score_participant - set participant_type = (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TYPE' and reserve_code = '{data['participant_type']}'), + set participant_type = (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TYPE' and reserve_code = :participant_type), team_name = {team_name_str} - where room_seq = {data['room_seq']} - and user_seq = {data['target_user_seq']} + where room_seq = :room_seq + and user_seq = :target_user_seq """) else: return False + params = { + "room_seq": data['room_seq'], + "participant_type": data['participant_type'], + "target_user_seq": data['target_user_seq'], + "team_name": data['team_name'], + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -421,14 +589,33 @@ async def select_room_seq_list(search_type, search_value, search_page, db): on a.room_seq = c.room_seq left join room_type d on a.room_type_seq = d.room_type_seq - where a.room_status = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = '{str(search_type).upper()}') - and a.room_title like '%{search_value}%' + where a.room_status = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = :search_type) + and a.room_title like :search_value and a.delete_yn = 'N' group by a.room_seq, b.nickname, a.room_status, a.open_yn, d.room_type_name, a.number_of_people, a.start_dt, a.end_dt, a.room_title, a.room_intro order by a.create_dt desc limit {int(search_page) * 10} offset {(int(search_page) - 1) * 10} """) - return db.execute(query).fetchall() + params = { + "search_type": str(search_type).upper(), + "search_value": f"%{search_value}%", + } + return db.execute(query, params).fetchall() + + +# 방 사회자 권한 확인 +async def select_mc_user_seq_by_room_seq(room_seq, db): + query = text(f""" + select + user_seq + from room_score_participant + where room_seq = :room_seq + and participant_type = (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TYPE' and reserve_code = 'ADMIN') + """) + params = { + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 방번호로 방 상태 체크 @@ -437,9 +624,12 @@ async def select_room_status_by_room_seq(room_seq, db): select room_status from room_main - where room_seq = {room_seq} + where room_seq = :room_seq """) - return db.execute(query).fetchall() + params = { + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 방번호와 방타입이 맞는지 확인 및 방 비밀번호 확인 @@ -450,10 +640,33 @@ async def check_room_seq_and_room_type_and_room_pw(room_seq, room_type, db): open_yn, room_pw from room_main - where room_seq = {room_seq} - and room_type_seq = (select room_type_seq from room_type where room_type_name = '{str(room_type).upper()}') + where room_seq = :room_seq + and room_type_seq = (select room_type_seq from room_type where room_type_name = :room_type) """) - return db.execute(query).fetchall() + params = { + "room_seq": room_seq, + "room_type": str(room_type).upper(), + } + return db.execute(query, params).fetchall() + + +# 이미 입장되어 있는 대기중인 방이 있는지 확인 +async def check_already_enter_room(user_seq, room_seq, db): + query = text(f""" + select + b.room_title + from room_score_participant a + left join room_main b on a.room_seq = b.room_seq + where b.room_status = (select reserve_code from reserve_code where reserve_code_group = 'ROOM_SCORE_STATUS' and reserve_code = 'WAIT') + and a.user_seq = :user_seq + and a.room_seq != :room_seq + and b.delete_yn = 'N' + """) + params = { + "user_seq": user_seq, + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 방번호로 방 상태 체크 @@ -462,10 +675,14 @@ async def check_already_enter_user(room_seq, user_seq, db): select count(user_seq) from room_score_participant - where user_seq = {user_seq} - and room_seq = {room_seq} + where user_seq = :user_seq + and room_seq = :room_seq """) - return db.execute(query).fetchall() + params = { + "user_seq": user_seq, + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 방번호, 방종류로 현재 인원수 체크 후 입장 가능여부 확인 @@ -477,27 +694,37 @@ async def select_now_number_of_people(room_seq, db): from room_main a left join room_score_participant b on a.room_seq = b.room_seq - where a.room_seq = {room_seq} + where a.room_seq = :room_seq group by a.room_seq """) - return db.execute(query).fetchall() + params = { + "room_seq": room_seq, + } + return db.execute(query, params).fetchall() # 방 입장하기 async def enter_room_user(room_seq, user_seq, room_type, db): query = text(f""" - insert into room_score_participant(room_seq, participant_type, user_seq, nickname, team_name, score) + insert into room_score_participant(room_seq, participant_type, user_seq, nickname, team_name, score, department, introduce_myself, profile_img) values( - {room_seq}, + :room_seq, (select reserve_code from reserve_code where reserve_code_group = 'PARTICIPANT_TYPE' and reserve_code = 'PLAYER'), - {user_seq}, - (select nickname from manage_user where user_seq = {user_seq}), + :user_seq, + (select nickname from manage_user where user_seq = :user_seq), '{'WAIT' if room_type == 'team' or room_type == 'TEAM' else 'PRIVATE'}', - 0 + 0, + (select department from manage_user where user_seq = :user_seq), + (select introduce_myself from manage_user where user_seq = :user_seq), + (select profile_img from manage_user where user_seq = :user_seq) ) """) + params = { + "room_seq": room_seq, + "user_seq": user_seq, + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -506,25 +733,20 @@ async def enter_room_user(room_seq, user_seq, room_type, db): # 점수 수정하기 -async def update_user_score(target_user_seq, after_score, room_type, room_seq, db): - if room_type == 'private' or room_type == 'PRIVATE': - query = text(f""" - update room_score_private_participant - set score = {after_score} - where room_seq = {room_seq} - and user_seq = {target_user_seq} - """) - elif room_type == 'team' or room_type == 'TEAM': - query = text(f""" - update room_score_team_participant - set score = {after_score} - where room_seq = {room_seq} - and user_seq = {target_user_seq} - """) - else: - return False +async def update_user_score(target_user_seq, after_score, room_seq, db): + query = text(f""" + update room_score_participant + set score = :after_score + where room_seq = :room_seq + and user_seq = :target_user_seq + """) + params = { + "after_score": after_score, + "room_seq": room_seq, + "target_user_seq": target_user_seq, + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -712,7 +934,7 @@ def insert_new_user(user_info, db): (select encode(digest('{user_info['user_pw']}{user_info['user_pw_solt']}', 'sha256'), 'hex')), '{user_info['user_pw_solt']}', '{user_info['nickname']}', - 'images/user/temp_dir/profile_img/basic_{user_info['user_id']}.png', + '/user/temp_dir/profile_img/profile.png', '{user_info['user_email']}', '{user_info.get('department', '')}', '{user_info.get('introduce_myself', '')}', @@ -864,3 +1086,99 @@ async def delete_room_score_participant(user_seq, room_seq, db): logger.error(f"sql error: {e}") return False + +# 진행중 강제종료 된 유저 진행중 방 조회 +async def select_running_room_by_user_seq(user_seq, db): + query = text(f""" + select + a.room_seq, + c.room_type_name, + b.room_title + from room_score_participant a + left join room_main b on a.room_seq = b.room_seq + left join room_type c on b.room_type_seq = c.room_type_seq + where a.user_seq = {user_seq} + and b.room_status = 'RUNNING' + and b.delete_yn = 'N' + order by a.room_seq desc + """) + return db.execute(query).fetchall() + + +# 설문조사 여부 확인 +async def select_nickname_survey_yn_join_game_yn_by_user_seq(user_seq, db): + query = text(f""" + select + nickname, + survey_yn, + join_game_yn + from manage_user + where user_seq = {user_seq} + """) + return db.execute(query).fetchall() + + +# 종료된 방 정보 가져오기 +async def select_finish_room_info(room_seq, db): + query = text(f""" + select + create_dt, + delete_dt, + delete_yn, + end_dt, + master_user_seq, + number_of_people, + number_of_teams, + open_yn, + room_intro, + room_status, + room_title, + room_type_name as room_type, + running_time, + score_open_range, + start_dt, + string_agg(c.team_name, ',') as team_name_list, + update_dt + from room_main a + left join room_type b on a.room_type_seq = b.room_type_seq + left join room_score_team_name c on a.room_seq = c.room_seq + where a.room_seq = {room_seq} + group by + create_dt, + delete_dt, + delete_yn, + end_dt, + master_user_seq, + number_of_people, + number_of_teams, + open_yn, + room_intro, + room_status, + room_title, + room_type, + running_time, + score_open_range, + start_dt, + update_dt + """) + return db.execute(query).fetchall() + + +# 종료된 방 참여자 정보 가져오기 +async def select_user_info_by_room_seq(room_seq, db): + query = text(f""" + select + department, + introduce_myself, + nickname, + participant_type, + profile_img, + score, + team_name, + user_seq + from room_score_participant + where room_seq = {room_seq} + """) + return db.execute(query).fetchall() + + diff --git a/fastapi/app/db/crud_survey.py b/fastapi/app/db/crud_survey.py new file mode 100644 index 0000000..687eeef --- /dev/null +++ b/fastapi/app/db/crud_survey.py @@ -0,0 +1,55 @@ +from sqlalchemy.orm import Session +from sqlalchemy import text +from db import models, schemas +from process.logger import logger +from db.base import get_db + + +#================================================================================================== +# 설문조사 관련 +#================================================================================================== + +# 설문조사 저장 +async def insert_survey_update_survey_yn(survey, db): + try: + for question, answer in zip(survey['question_list'], survey['answer_list']): + query = text(""" + INSERT INTO survey ( + user_seq, + question_msg, + answer_msg + ) + VALUES ( + :user_seq, + :question, + :answer + ) + """) + + # :user_seq, :question, :answer 자리에 들어갈 파라미터 정의 + params = { + "user_seq": survey['user_seq'], + "question": question, + "answer": answer + } + db.execute(query, params) + + query = text(""" + update manage_user + set + survey_yn = 'Y' + where + user_seq = :user_seq + """) + params = { + "user_seq": survey['user_seq'], + } + + db.execute(query, params) + + db.commit() + return True + except Exception as e: + logger.error(f"sql error: {e}") + return False + diff --git a/fastapi/app/db/crud_user.py b/fastapi/app/db/crud_user.py index 6e4de78..fab37ed 100644 --- a/fastapi/app/db/crud_user.py +++ b/fastapi/app/db/crud_user.py @@ -5,39 +5,86 @@ from process.logger import logger from db.base import get_db +#================================================================================================== +# 구글 Oauth관련 +#================================================================================================== + +# DB에서 user 찾기 +async def get_user_by_oauth_user_email(user_email, db): + query = text(f""" + select + user_seq + from manage_user + where + user_email = :user_email + """) + params = { + "user_email": user_email, + } + return db.execute(query, params).fetchall() + + +# 구글 유저 생성 +async def create_oauth_user(oauth_uid, user_email, user_id, user_nickname, db): + query = text(f""" + insert into manage_user(user_id, oauth_type, oauth_uid, nickname, profile_img, user_email, department, introduce_myself, last_login_dt, create_dt, update_dt, mandatory_terms_yn, withdraw_yn) + values(:user_id, 'google', :oauth_uid, :user_nickname, '/user/temp_dir/profile_img/profile.png', :user_email, '', '', now(), now(), now(), 'Y', 'N') + """) + params = { + "user_id": user_id, + "oauth_uid": oauth_uid, + "user_nickname": user_nickname, + "user_email": user_email, + } + try: + db.execute(query, params) + db.commit() + return True + except Exception as e: + logger.error(f"sql error: {e}") + return False + + # ================================================================ # 회원관리 함수 # ================================================================ # 로그인 -def do_login(user_id, user_pw, db): +async def do_login(user_id, user_pw, db): query = text(f""" select user_seq from manage_user where - user_id = '{user_id}' + user_id = :user_id and user_pw = (select encode( digest( - '{user_pw}' || (select user_pw_solt from manage_user where user_id = '{user_id}'), 'sha256' + :user_pw || (select user_pw_solt from manage_user where user_id = :user_id), 'sha256' ), 'hex' )) and withdraw_yn = 'N' """) - return db.execute(query).fetchall() + params = { + "user_id": user_id, + "user_pw": user_pw, + } + return db.execute(query, params).fetchall() # 마지막 로그인 시간 업데이트 -def update_last_login_dt(user_seq, db): +async def update_last_login_dt(user_seq, db): query = text(f""" update manage_user set last_login_dt = now() - where user_seq = {user_seq} + where user_seq = :user_seq and withdraw_yn = 'N' """) + params = { + "user_seq": user_seq, + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -46,52 +93,68 @@ def update_last_login_dt(user_seq, db): # 아이디 찾기(닉네임, 이메일) -def find_id_by_name_email(nickname, user_email, db): +async def find_id_by_name_email(nickname, user_email, db): query = text(f""" select user_seq, user_id from manage_user - where nickname = '{nickname}' - and user_email = '{user_email}' + where nickname = :nickname + and user_email = :user_email and withdraw_yn = 'N' """) - return db.execute(query).fetchall() + params = { + "nickname": nickname, + "user_email": user_email, + } + return db.execute(query, params).fetchall() # 아이디 찾기(user_seq) -def find_id_by_user_seq(user_seq, db): +async def find_id_by_user_seq(user_seq, db): query = text(f""" select user_id, user_email from manage_user - where user_seq = {user_seq} + where user_seq = :user_seq and withdraw_yn = 'N' """) - return db.execute(query).fetchall() + params = { + "user_seq": user_seq, + } + return db.execute(query, params).fetchall() # 이메일 발송 3회 이상 됐는지 확인 -def select_send_email_cnt(user_email, db): +async def select_send_email_cnt(user_email, db): query = text(f""" select count(user_cert_seq) from manage_user_cert - where user_info = '{user_email}' + where user_info = :user_email and cert_expired between current_date and current_date + interval '1 day' """) - return db.execute(query).fetchall() + params = { + "user_email": user_email, + } + return db.execute(query, params).fetchall() # 이메일 발송내역 기록(하루 3회만 발송가능하게 하기 위함) -def insert_send_email_info(user_seq, cert_type, user_info, cert_code, db): +async def insert_send_email_info(user_seq, cert_type, user_info, cert_code, db): query = text(f""" insert into manage_user_cert(user_seq, cert_type, user_info, cert_code, cert_expired) - values({user_seq}, '{cert_type}', '{user_info}', '{cert_code}', now() + INTERVAL '5 minutes') + values(:user_seq, :cert_type, :user_info, :cert_code, now() + INTERVAL '5 minutes') """) + params = { + "user_seq": user_seq, + "cert_type": cert_type, + "user_info": user_info, + "cert_code": cert_code, + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -100,51 +163,77 @@ def insert_send_email_info(user_seq, cert_type, user_info, cert_code, db): # 비밀번호 찾기 -def find_password_by_id_email(user_id, user_email, db): +async def find_password_by_id_email(user_id, user_email, db): query = text(f""" select user_seq from manage_user - where user_id = '{user_id}' - and user_email = '{user_email}' + where user_id = :user_id + and user_email = :user_email and withdraw_yn = 'N' """) - return db.execute(query).fetchall() + params = { + "user_id": user_id, + "user_email": user_email, + } + return db.execute(query, params).fetchall() # 신규 비밀번호 업데이트 -def update_new_password(user_seq, new_pw, new_solt, db): +async def update_new_password(user_seq, new_pw, new_solt, db): query = text(f""" update manage_user set - user_pw = encode(digest(encode(digest('{new_pw}', 'sha256'), 'hex') || '{new_solt}', 'sha256'), 'hex'), - user_pw_solt = '{new_solt}' + user_pw = encode(digest(encode(digest(:new_pw, 'sha256'), 'hex') || :new_solt, 'sha256'), 'hex'), + user_pw_solt = :new_solt where - user_seq = {user_seq} + user_seq = :user_seq and withdraw_yn = 'N' """) + params = { + "new_pw": new_pw, + "new_solt": new_solt, + "user_seq": user_seq, + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: logger.error(f"sql error: {e}") return False + - -# 회원가입 최종 아이디 중복 재검사 -def is_valid_user_id_by_user_id(user_id, db): +# 이메일 중복 확인 +async def is_valid_user_email_by_user_email(user_email, db): query = text(f""" select user_seq from manage_user - where user_id = '{user_id}' + where user_email = :user_email """) - return db.execute(query).fetchall() + params = { + "user_email": user_email, + } + return db.execute(query, params).fetchall() + + +# 회원가입 최종 아이디 중복 재검사 +async def is_valid_user_id_by_user_id(user_id, db): + query = text(f""" + select + user_seq + from manage_user + where user_id = :user_id + """) + params = { + "user_id": user_id, + } + return db.execute(query, params).fetchall() # 신규 유저 등록 -def insert_new_user(user_info, db): +async def insert_new_user(user_info, db): query = text(f""" insert into manage_user( @@ -163,23 +252,33 @@ def insert_new_user(user_info, db): withdraw_yn ) values( - '{user_info['user_id']}', - (select encode(digest('{user_info['user_pw']}{user_info['user_pw_solt']}', 'sha256'), 'hex')), - '{user_info['user_pw_solt']}', - '{user_info['nickname']}', - 'images/user/temp_dir/profile_img/basic_{user_info['user_id']}.png', - '{user_info['user_email']}', - '{user_info.get('department', '')}', - '{user_info.get('introduce_myself', '')}', + :user_id, + (select encode(digest(:user_pw || :user_pw_solt, 'sha256'), 'hex')), + :user_pw_solt, + :nickname, + '/user/temp_dir/profile_img/profile.png', + :user_email, + :department, + :introduce_myself, now(), now(), now(), - '{user_info.get('mandatory_terms_yn', '')}', + :mandatory_terms_yn, 'N' ) """) + params = { + "user_id": user_info['user_id'], + "user_pw": user_info['user_pw'], + "user_pw_solt": user_info['user_pw_solt'], + "nickname": user_info['nickname'], + "user_email": user_info['user_email'], + "department": user_info.get('department', ''), + "introduce_myself": user_info.get('introduce_myself', ''), + "mandatory_terms_yn": user_info.get('mandatory_terms_yn', 'N'), + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -188,17 +287,21 @@ def insert_new_user(user_info, db): # 프로필 이미지 업데이트 -def update_profile_img(user_seq, profile_img, db): +async def update_profile_img(user_seq, profile_img, db): query = text(f""" update manage_user set - profile_img = '{profile_img}' + profile_img = :profile_img where - user_seq = {user_seq} + user_seq = :user_seq and withdraw_yn = 'N' """) + params = { + "profile_img": profile_img, + "user_seq": user_seq, + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -207,7 +310,7 @@ def update_profile_img(user_seq, profile_img, db): # user_seq로 내정보 가져오기 -def get_my_info_by_user_seq(user_seq, db): +async def get_my_info_by_user_seq(user_seq, db): query = text(f""" select nickname, @@ -216,60 +319,77 @@ def get_my_info_by_user_seq(user_seq, db): profile_img, introduce_myself from manage_user - where user_seq = {user_seq} + where user_seq = :user_seq """) - return db.execute(query).fetchall() + params = { + "user_seq": user_seq, + } + return db.execute(query, params).fetchall() # 현재 비밀번호 일치 확인 -def check_current_user_pw(user_seq, user_pw, db): +async def check_current_user_pw(user_seq, user_pw, db): query = text(f""" select count(user_seq) from manage_user - where user_seq = {user_seq} + where user_seq = :user_seq and user_pw = (select encode( digest( - '{user_pw}' || (select user_pw_solt from manage_user where user_seq = '{user_seq}'), 'sha256' + :user_pw || (select user_pw_solt from manage_user where user_seq = :user_seq), 'sha256' ), 'hex' )) """) - return db.execute(query).fetchall() + params = { + "user_seq": user_seq, + "user_pw": user_pw, + } + return db.execute(query, params).fetchall() # 신규 비밀번호 업데이트 -def update_user_info(user_info, db): +async def update_user_info(user_info, db): if user_info['user_pw_change_yn'] == 'Y': query = text(f""" update manage_user set - user_pw = encode(digest('{user_info['new_user_pw']}' || '{user_info['user_pw_solt']}', 'sha256'), 'hex'), - user_pw_solt = '{user_info['user_pw_solt']}', - nickname = '{user_info['nickname']}', - user_email = '{user_info['user_email']}', - department = '{user_info['department']}', - profile_img = '{user_info['profile_img']}', - introduce_myself = '{user_info['introduce_myself']}' + user_pw = encode(digest(:new_user_pw || :user_pw_solt, 'sha256'), 'hex'), + user_pw_solt = :user_pw_solt, + nickname = :nickname, + user_email = :user_email, + department = :department, + profile_img = :profile_img, + introduce_myself = :introduce_myself where - user_seq = {user_info['user_seq']} + user_seq = :user_seq and withdraw_yn = 'N' """) else: query = text(f""" update manage_user set - nickname = '{user_info['nickname']}', - user_email = '{user_info['user_email']}', - department = '{user_info['department']}', - profile_img = '{user_info['profile_img']}', - introduce_myself = '{user_info['introduce_myself']}' + nickname = :nickname, + user_email = :user_email, + department = :department, + profile_img = :profile_img, + introduce_myself = :introduce_myself where - user_seq = {user_info['user_seq']} + user_seq = :user_seq and withdraw_yn = 'N' """) + params = { + "user_seq": user_info['user_seq'], + "new_user_pw": user_info['new_user_pw'], + "user_pw_solt": user_info['user_pw_solt'], + "nickname": user_info['nickname'], + "user_email": user_info['user_email'], + "department": user_info.get('department', ''), + "profile_img": user_info['profile_img'], + "introduce_myself": user_info.get('introduce_myself', ''), + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: @@ -278,15 +398,18 @@ def update_user_info(user_info, db): # 회원 탈퇴 처리 -def user_withdraw(user_seq, db): +async def user_withdraw(user_seq, db): query = text(f""" delete from manage_user where - user_seq = {user_seq} + user_seq = :user_seq and withdraw_yn = 'N' """) + params = { + "user_seq": user_seq, + } try: - db.execute(query) + db.execute(query, params) db.commit() return True except Exception as e: diff --git a/fastapi/app/main.py b/fastapi/app/main.py index fcf08fc..b425304 100644 --- a/fastapi/app/main.py +++ b/fastapi/app/main.py @@ -10,6 +10,8 @@ from router.card_service import router as router_card from router.image_api import router as image_api from router.manage_user_api import router as manage_user_api from router.room_score_api import router as room_score_api +from router.survey_api import router as survey_api +from router.inquiry_api import router as inquiry_api # test from router.test_service import router as test_service_api @@ -54,6 +56,12 @@ app.include_router(manage_user_api) # /room/score app.include_router(room_score_api) +# /survey +app.include_router(survey_api) + +# /inquiry +app.include_router(inquiry_api) + diff --git a/fastapi/app/process/firebase/firebase_app.py b/fastapi/app/process/firebase/firebase_app.py index 29b9345..342e94a 100644 --- a/fastapi/app/process/firebase/firebase_app.py +++ b/fastapi/app/process/firebase/firebase_app.py @@ -3,11 +3,11 @@ from firebase_admin import credentials, db def initialize_firebase(): # 1) 서비스 계정 키 경로 - cred = credentials.Certificate("/app/allscore-344c2-firebase-adminsdk-4ysfn-6585b694d2.json") + cred = credentials.Certificate("/app/allscore-29edf-firebase-adminsdk-fv5tf-0c2be71530.json") # 2) initialize_app firebase_admin.initialize_app(cred, { - "databaseURL": "https://allscore-344c2-default-rtdb.asia-southeast1.firebasedatabase.app" # Firebase Realtime Database URL + "databaseURL": "https://allscore-29edf-default-rtdb.asia-southeast1.firebasedatabase.app" # Firebase Realtime Database URL }) # 이제 이 모듈을 import 하면 어디서든 db.reference() 사용 가능 diff --git a/fastapi/app/process/firebase/firebase_process.py b/fastapi/app/process/firebase/firebase_process.py index 6bbd68f..63c9f97 100644 --- a/fastapi/app/process/firebase/firebase_process.py +++ b/fastapi/app/process/firebase/firebase_process.py @@ -36,8 +36,8 @@ async def update_room_setting_info(room_seq, data): # 파이어베이스 업데이트 async def update_firebase_score(room_seq, user_seq, newScore): try: - ref = frd_db.reference("rooms").child(f"korea-{room_seq}").child("userInfo").child(user_seq) - ref.update({"score": newScore}) + ref = frd_db.reference("rooms").child(f"korea-{room_seq}").child("userInfo").child(f"_{user_seq}") + ref.update({"score": int(newScore)}) return { "result": "OK", "msg": "업데이트 성공" @@ -59,7 +59,7 @@ async def create_firebase_room(data): initialData = { "roomInfo": { "room_type": data["room_type"], - "master_user_seq": data["user_seq"], + "master_user_seq": str(data["user_seq"]), "room_title": data["room_title"], "room_intro": data["room_intro"], "open_yn": data["open_yn"], @@ -69,16 +69,16 @@ async def create_firebase_room(data): "number_of_teams": data["number_of_teams"], "team_name_list": [], "score_open_range": data["score_open_range"], - "create_dt": f"'{data['create_dt']}'", - "update_dt": f"'{data['update_dt']}'", - "start_dt": f"'{data['start_dt']}'", - "end_dt": f"'{data['end_dt']}'", + "create_dt": f"{data['create_dt']}", + "update_dt": f"{data['update_dt']}", + "start_dt": f"{data['start_dt']}", + "end_dt": f"{data['end_dt']}", "delete_yn": "N", - "delete_dt": f"'{data['delete_dt']}'", + "delete_dt": f"{data['delete_dt']}", "team_name_list": data['team_name_list'] }, "userInfo": { - data['user_seq']: { + f"_{data['user_seq']}": { "participant_type": data['user_info']['participant_type'], "nickname": data['user_info']['nickname'], "team_name": data['user_info']['team_name'], @@ -87,10 +87,12 @@ async def create_firebase_room(data): "department": data['user_info']['department'], "introduce_myself": data['user_info']['introduce_myself'], "ready_yn": "N", + "user_seq": str(data['user_seq']), + "connect_yn": "Y" } }, "userList": { - data['user_seq']: True + f"_{data['user_seq']}": True } } @@ -117,7 +119,7 @@ def set_room_setting_info(body): "delete_dt": body['delete_dt'] if 'delete_dt' in body else 'null', "delete_yn": body['delete_yn'] if 'delete_yn' in body else 'N', "end_dt": body['end_dt'] if 'end_dt' in body else 'null', - "master_user_seq": body['master_user_seq'] if 'master_user_seq' in body else '', + "master_user_seq": str(body['master_user_seq']) if 'master_user_seq' in body else '', "number_of_people": body['number_of_people'] if 'number_of_people' in body else '', "number_of_teams": body['number_of_teams'] if 'number_of_teams' in body else '', "open_yn": body['open_yn'] if 'open_yn' in body else '', @@ -146,7 +148,7 @@ def set_room_setting_info(body): # 파이어베이스 참가자 역할&팀 수정하기 async def update_participant_role(data): try: - ref = frd_db.reference("rooms").child(f"korea-{data['room_seq']}").child("userInfo").child(data['target_user_seq']) + ref = frd_db.reference("rooms").child(f"korea-{data['room_seq']}").child("userInfo").child(f"_{data['target_user_seq']}") ref.update({ "participant_type": data['participant_type'], "team_name": data['team_name'] if data['room_type_name'] == 'team' or data['room_type_name'] == 'TEAM' else 'PRIVATE' @@ -200,13 +202,37 @@ async def update_team_name(data): "result": "FAIL", "msg": "업데이트 실패" } + +# 파이어베이스 팀명 확인 +async def check_granted_team_name(room_seq): + try: + ref = frd_db.reference("rooms").child(f"korea-{room_seq}").child("userInfo") + user_list = ref.get() + for user_seq, user_info in user_list.items(): + if user_info['team_name'] == 'WAIT': + return { + "result": "FAIL", + "msg": "대기중인 참가자가 있습니다." + } + return { + "result": "OK", + "msg": "대기중인 참가자가 없습니다." + } + except Exception as e: + logger.error(f"request error. URL: /room/score/check/granted/team/name\nerror message: {e}") + return { + "result": "FAIL", + "msg": "팀명 확인 실패" + } - -# 파이어베이스 방 상태 업데이트 -async def update_room_status(data): +# 파이어베이스 방 상태 및 시작시간 업데이트 +async def update_room_status_start_dt(data): try: ref = frd_db.reference("rooms").child(f"korea-{data['room_seq']}").child("roomInfo") - ref.update({"room_status": data['room_status']}) + ref.update({ + "room_status": data['room_status'], + "start_dt": data['start_dt'] + }) return { "result": "OK", "msg": "업데이트 성공" @@ -219,6 +245,25 @@ async def update_room_status(data): } +# 파이어베이스 방 상태 및 종료시간 업데이트 +async def update_room_status_end_dt(data): + try: + ref = frd_db.reference("rooms").child(f"korea-{data['room_seq']}").child("roomInfo") + ref.update({ + "room_status": data['room_status'], + "end_dt": data['end_dt'] + }) + return { + "result": "OK", + "msg": "업데이트 성공" + } + except Exception as e: + logger.error(f"request error. URL: /room/score/update/room/status/end/dt\nerror message: {e}") + return { + "result": "FAIL", + "msg": "업데이트 실패" + } + # 파이어베이스 방 삭제 async def delete_room_score_frd(room_seq): @@ -237,10 +282,10 @@ async def delete_room_score_frd(room_seq): } -# 파이어베이스 참여자 업데이트 -async def update_participant(data): +# 파이어베이스 나간 참여자 업데이트 +async def update_exit_participant(data): try: - user_seq = str(data['user_seq']) # user_seq를 문자열로 변환 + user_seq = f"_{str(data['user_seq'])}" # user_seq를 문자열로 변환 if not user_seq: # user_seq가 비어 있는지 확인 logger.error("user_seq is empty or invalid.") return { @@ -270,9 +315,17 @@ async def update_participant(data): async def enter_room_user(room_seq, user_info): try: ref_list = frd_db.reference("rooms").child(f"korea-{room_seq}").child("userList") - ref_list.child(str(user_info['user_seq'])).set(True) + ref_list.child(f"_{user_info['user_seq']}").set(True) - ref_info = frd_db.reference("rooms").child(f"korea-{room_seq}").child("userInfo").child(str(user_info['user_seq'])) + # 재입장인지 확인 + ref_list = frd_db.reference("rooms").child(f"korea-{room_seq}").child("userInfo") + if ref_list.child(f"_{user_info['user_seq']}").get() is not None: + return { + "result": "OK", + "msg": "재입장 성공" + } + + ref_info = frd_db.reference("rooms").child(f"korea-{room_seq}").child("userInfo").child(f"_{user_info['user_seq']}") ref_info.set(user_info) return { @@ -291,10 +344,10 @@ async def enter_room_user(room_seq, user_info): async def kick_participant(data): try: ref = frd_db.reference("rooms").child(f"korea-{data['room_seq']}").child("userList") - ref.update({f"{data['target_user_seq']}": False}) + ref.update({f"_{data['target_user_seq']}": False}) ref = frd_db.reference("rooms").child(f"korea-{data['room_seq']}").child("userInfo") - ref.child(data['target_user_seq']).delete() + ref.child(f"_{data['target_user_seq']}").delete() return { "result": "OK", @@ -311,8 +364,64 @@ async def kick_participant(data): # 파이어베이스 강퇴된 유저인지 확인 async def check_kick_user(user_seq, room_seq): try: + user_seq = f"_{str(user_seq)}" # user_seq를 문자열로 변환 + if not user_seq: # user_seq가 비어 있는지 확인 + logger.error("user_seq is empty or invalid.") + return { + "result": "FAIL", + "msg": "user_seq is empty or invalid." + } + ref = frd_db.reference("rooms").child(f"korea-{room_seq}").child("userList").child(user_seq) - return ref.get() + user_info = ref.get() + logger.info(f"user_info: {user_info}") + + if user_info is None: + return { + "result": "FAIL", + "msg": "강퇴된 유저가 아님" + } + + if not user_info: + return { + "result": "OK", + "msg": "강퇴된 유저" + } + else: + return { + "result": "FAIL", + "msg": "강퇴된 유저가 아님" + } except Exception as e: logger.error(f"request error. URL: /room/score/check/kick/user\nerror message: {e}") - return False + return { + "result": "FAIL", + "msg": "강퇴된 유저 확인 실패" + } + + +# 파이어베이스 진행중 강제종료 된 유저인지 확인 +async def check_force_exit_yn(user_seq, data): + try: + for room_seq, room_type_name, room_title in data: + ref = frd_db.reference("rooms").child(f"korea-{room_seq}").child("userList").child(f"_{user_seq}") + # True이면 강제종료 된 유저 + if ref.get() is True: + return { + "result": "OK", + "msg": "강제종료 된 유저", + "room_seq": room_seq, + "room_type_name": room_type_name, + "room_title": room_title + } + return { + "result": "FAIL", + "msg": "강제종료 된 유저가 아님" + } + except Exception as e: + logger.error(f"request error. URL: /room/score/check/force/exit/yn\nerror message: {e}") + return { + "result": "FAIL", + "msg": "업데이트 실패" + } + diff --git a/fastapi/app/process/inquiry/manage_inquiry.py b/fastapi/app/process/inquiry/manage_inquiry.py new file mode 100644 index 0000000..53dc2fc --- /dev/null +++ b/fastapi/app/process/inquiry/manage_inquiry.py @@ -0,0 +1,26 @@ +from fastapi import APIRouter, Depends, HTTPException, Header, Body, status, Request +from db import crud_inquiry +from sqlalchemy.orm import Session +from db.base import get_db +from db import models, schemas +from process.logger import logger + + + +#================================================================================================== +# 문의 관련 +#================================================================================================== + +# 문의 저장 +async def insert_inquiry(inquiry, db): + db_result_ori = await crud_inquiry.insert_inquiry(inquiry=inquiry, db=db) + + if db_result_ori: + return { + "result": "OK" + } + else: + return { + "result": "FAIL" + } + diff --git a/fastapi/app/process/room/connect_kafka_process.py b/fastapi/app/process/room/connect_kafka_process.py new file mode 100644 index 0000000..e83435f --- /dev/null +++ b/fastapi/app/process/room/connect_kafka_process.py @@ -0,0 +1,73 @@ +import json +import logger +import datetime +from kafka import KafkaProducer +from fastapi import Header +from typing import Optional + +KST = datetime.timezone(datetime.timedelta(hours=9)) +KAFKA_IP = '10.10.10.10' +KAFKA_TOPIC = 'allscore' + +class MessageProducer: + broker = "" + topic = "" + producer = None + + def __init__(self, broker, topic): + self.broker = broker + self.topic = topic + self.producer = KafkaProducer( + bootstrap_servers=self.broker, + value_serializer=lambda x: json.dumps(x).encode('utf-8'), + acks=0, + api_version=(2,5,0), + retries=3 + ) + + def send_message(self, msg): + try: + future = self.producer.send(self.topic, msg) + self.producer.flush() # 비우는 작업 + future.get(timeout=60) + return {'status_code': 200, 'error': None} + except Exception as e: + logger.error(f"kafka process error: {e}") + return e + + +async def update_connect_yn(user_seq: int, connect_yn: str): + content_Type: Optional[str] = Header(None) + X_HIT_TransactionId: Optional[str] = Header(None) + content_Length: Optional[str] = Header(None) + + body = { + "user_seq": user_seq, + "connect_yn": connect_yn + } + + data = { + 'content_Type': str(content_Type), + 'X_HIT_TransactionId': str(X_HIT_TransactionId), + 'content_Length': str(content_Length), + 'body': str(body) + } + message_producer = MessageProducer(KAFKA_IP, KAFKA_TOPIC) + # message_producer_dev = MessageProducer(KAFKA_IP_DEV, KAFKA_TOPIC) + + msg = { + "data_type": 'data_herit', + "data_herit": { + "content_type": data['content_Type'], + "x_hit_transactionid": data['X_HIT_TransactionId'], + "content_length": data['content_Length'], + "body": data['body'] + } + } + res = message_producer.send_message(msg) + # res_dev = message_producer_dev.send_message(msg) + + if res['status_code'] != status.HTTP_200_OK: + return {"reason": "SERVER ERROR"} + else : + return {"reason": "OK"} \ No newline at end of file diff --git a/fastapi/app/process/room/room_score.py b/fastapi/app/process/room/room_score.py index 9e8c551..a94fee0 100644 --- a/fastapi/app/process/room/room_score.py +++ b/fastapi/app/process/room/room_score.py @@ -8,7 +8,7 @@ from process.logger import logger # 방 만들기 async def create_room(data, db): try: - db_result = crud_room_score.create_room(data=data, db=db) + db_result = await crud_room_score.create_room(data=data, db=db) if db_result: return { @@ -73,7 +73,7 @@ async def insert_creater_user_participant(data, db): # 방장 참여자 입력 user_info = { - "user_seq": user_info[0], + "user_seq": str(user_info[0]), "nickname": user_info[1], "profile_img": user_info[2], "department": user_info[3], @@ -105,8 +105,8 @@ async def insert_creater_user_participant(data, db): # 방 참여자 조회 권한 확인 -async def check_auth_user(user_seq, room_type, room_seq, db): - db_result_ori = await crud_room_score.check_auth_user(user_seq=user_seq, room_type=room_type, room_seq=room_seq, db=db) +async def check_auth_user(user_seq, room_seq, db): + db_result_ori = await crud_room_score.check_auth_user(user_seq=user_seq, room_seq=room_seq, db=db) db_result = [] for db_data in db_result_ori: db_result.append(db_data) @@ -136,7 +136,7 @@ async def participant_user_list(user_seq, room_type, room_seq, db): for db_data in db_result_ori: if room_type == 'private' or room_type == 'PRIVATE': db_result.append({ - "user_seq": db_data[0], + "user_seq": str(db_data[0]), "participant_type": db_data[1], "nickname": db_data[2], "score": db_data[3], @@ -148,7 +148,7 @@ async def participant_user_list(user_seq, room_type, room_seq, db): }) elif room_type == 'team' or room_type == 'TEAM': db_result.append({ - "user_seq": db_data[0], + "user_seq": str(db_data[0]), "participant_type": db_data[1], "nickname": db_data[2], "team_name": db_data[3], @@ -181,6 +181,8 @@ async def check_requester_room_master_auth(user_seq, room_seq, db): } room_master_user_seq = db_result_ori[0][0] + logger.info(f"room_master_user_seq: {room_master_user_seq}") + logger.info(f"user_seq: {user_seq}") # 조회된 방장 SEQ와 요청자 SEQ 비교 if int(room_master_user_seq) == int(user_seq): @@ -207,7 +209,7 @@ async def check_granted_team_name(room_seq, db): # 요청자가 방장인지 확인 -async def update_room_status(room_seq, room_status, db): +async def update_room_status_start_dt_end_dt(room_seq, room_status, start_dt, end_dt, db): room_status_follow_list = ['WAIT', 'RUNNING', 'FINISH'] before_status_index = room_status_follow_list.index(room_status)-1 if before_status_index < 0: @@ -215,7 +217,7 @@ async def update_room_status(room_seq, room_status, db): "result": "FAIL", } before_status = room_status_follow_list[before_status_index] - db_result = await crud_room_score.update_room_status(room_seq=room_seq, room_status=room_status, before_status=before_status, db=db) + db_result = await crud_room_score.update_room_status_start_dt_end_dt(room_seq=room_seq, room_status=room_status, before_status=before_status, start_dt=start_dt, end_dt=end_dt, db=db) if db_result: return { @@ -227,6 +229,42 @@ async def update_room_status(room_seq, room_status, db): } +# 참여자 게임 참여 여부 업데이트 +async def update_participant_join_game_yn(room_seq, db): + if await crud_room_score.update_participant_join_game_yn(room_seq=room_seq, db=db): + return { + "result": "OK" + } + else: + return { + "result": "FAIL", + } + + +# 시작시간 업데이트 +async def update_start_dt(room_seq, start_dt, db): + if await crud_room_score.update_start_dt(room_seq=room_seq, start_dt=start_dt, db=db): + return { + "result": "OK" + } + else: + return { + "result": "FAIL", + } + + +# 종료시간 업데이트 +async def update_end_dt(room_seq, end_dt, db): + if await crud_room_score.update_end_dt(room_seq=room_seq, end_dt=end_dt, db=db): + return { + "result": "OK" + } + else: + return { + "result": "FAIL", + } + + # 방 설정정보 가져오기 async def select_room_setting_info(user_seq, room_seq, db): db_result_ori = await crud_room_score.select_room_setting_info(room_seq=room_seq, db=db) @@ -344,6 +382,21 @@ async def select_room_list(search_type, search_value, search_page, db): } +# 방 사회자 권한 확인 +async def select_mc_user_seq_by_room_seq(user_seq, room_seq, db): + db_result_ori = await crud_room_score.select_mc_user_seq_by_room_seq(room_seq=room_seq, db=db) + mc_user_seq_list = [str(x[0]) for x in db_result_ori] + + if str(user_seq) in mc_user_seq_list: + return { + "result": "OK", + } + else: + return { + "result": "FAIL", + } + + # 방번호로 방 상태 체크 async def check_room_status_by_room_seq_room_status(room_seq, room_status, db): db_result_ori = await crud_room_score.select_room_status_by_room_seq(room_seq=room_seq, db=db) @@ -376,6 +429,20 @@ async def check_room_seq_and_room_type_and_room_pw(room_seq, room_type, db): } +# 이미 입장되어 있는 대기중인 방이 있는지 확인 +async def check_already_enter_room(user_seq, room_seq, db): + db_result_ori = await crud_room_score.check_already_enter_room(user_seq=user_seq, room_seq=room_seq, db=db) + if len(db_result_ori) == 1: + return { + "result": "OK", + "room_title": db_result_ori[0][0] + } + else: + return { + "result": "FAIL", + } + + # 방번호로 방 상태 체크 async def check_already_enter_user(room_seq, room_type, user_seq, db): db_result_ori = await crud_room_score.check_already_enter_user(room_seq=room_seq, user_seq=user_seq, db=db) @@ -418,7 +485,7 @@ async def enter_user_info(user_seq, room_type, db): db_result_ori = await crud_room_score.select_user_info_by_user_seq(user_seq=user_seq, db=db) if len(db_result_ori) == 1: db_result = { - "user_seq": db_result_ori[0][0], + "user_seq": str(db_result_ori[0][0]), "nickname": db_result_ori[0][1], "profile_img": db_result_ori[0][2], "department": db_result_ori[0][3], @@ -426,6 +493,8 @@ async def enter_user_info(user_seq, room_type, db): "score": 0, "team_name": 'WAIT' if room_type == 'team' or room_type == 'TEAM' else 'PRIVATE', "ready_yn": 'N', + "participant_type": 'PLAYER', + "connect_yn": 'Y' } return { "result": "OK", @@ -450,8 +519,8 @@ async def enter_room_user(room_seq, user_seq, room_type, db): # 점수 수정하기 -async def update_user_score(target_user_seq, after_score, room_type, room_seq, db): - if await crud_room_score.update_user_score(target_user_seq=target_user_seq, after_score=after_score, room_type=room_type, room_seq=room_seq, db=db): +async def update_user_score(target_user_seq, after_score, room_seq, db): + if await crud_room_score.update_user_score(target_user_seq=target_user_seq, after_score=after_score, room_seq=room_seq, db=db): return { "result": "OK" } @@ -498,6 +567,98 @@ async def delete_room_score_participant(user_seq, room_seq, db): } +# 진행중 강제종료 된 유저 진행중 방 조회 +async def select_running_room_by_user_seq(user_seq, db): + db_result_ori = await crud_room_score.select_running_room_by_user_seq(user_seq=user_seq, db=db) + if len(db_result_ori) != 0: + return { + "result": "OK", + "data": db_result_ori + } + else: + return { + "result": "FAIL", + } + + +# 설문조사 여부 확인 +async def select_nickname_survey_yn_join_game_yn_by_user_seq(user_seq, db): + db_result_ori = await crud_room_score.select_nickname_survey_yn_join_game_yn_by_user_seq(user_seq=user_seq, db=db) + if len(db_result_ori) == 1: + return { + "result": "OK", + "nickname": db_result_ori[0][0], + "survey_yn": db_result_ori[0][1], + "join_game_yn": db_result_ori[0][2] + } + else: + return { + "result": "FAIL", + } + + +# 종료된 방 정보 가져오기 +async def select_finish_room_info(room_seq, db): + try: + room_info_result = await crud_room_score.select_finish_room_info(room_seq=room_seq, db=db) + user_info_result = await crud_room_score.select_user_info_by_room_seq(room_seq=room_seq, db=db) + + if len(room_info_result) != 1: + return { + "result": "FAIL", + } + + room_info = {} + for room_info_data in room_info_result: + room_info = { + "create_dt": room_info_data[0], + "delete_dt": room_info_data[1], + "delete_yn": room_info_data[2], + "end_dt": room_info_data[3], + "master_user_seq": room_info_data[4], + "number_of_people": room_info_data[5], + "number_of_teams": room_info_data[6], + "open_yn": room_info_data[7], + "room_intro": room_info_data[8], + "room_status": room_info_data[9], + "room_title": room_info_data[10], + "room_type": room_info_data[11], + "running_time": room_info_data[12], + "score_open_range": room_info_data[13], + "start_dt": room_info_data[14], + "team_name_list": room_info_data[15], + "update_dt": room_info_data[16], + } + + if len(user_info_result) == 0: + return { + "result": "FAIL", + } + + user_info = {} + for user_info_data in user_info_result: + user_info[room_seq] = { + "department": user_info_data[0], + "introduce_myself": user_info_data[1], + "nickname": user_info_data[2], + "participant_type": user_info_data[3], + "profile_img": user_info_data[4], + "score": user_info_data[5], + "team_name": user_info_data[6], + "user_seq": str(user_info_data[7]), + } + + return { + "result": "OK", + "room_info": room_info, + "user_info": user_info + } + except Exception as e: + logger.error(f"sql error: {e}") + return { + "result": "FAIL", + } + diff --git a/fastapi/app/process/survey/manage_survey.py b/fastapi/app/process/survey/manage_survey.py new file mode 100644 index 0000000..d727bbe --- /dev/null +++ b/fastapi/app/process/survey/manage_survey.py @@ -0,0 +1,26 @@ +from fastapi import APIRouter, Depends, HTTPException, Header, Body, status, Request +from db import crud_survey +from sqlalchemy.orm import Session +from db.base import get_db +from db import models, schemas +from process.logger import logger + + + +#================================================================================================== +# 설문조사 관련 +#================================================================================================== + +# 설문조사 저장 +async def insert_survey_update_survey_yn(survey, db): + db_result_ori = await crud_survey.insert_survey_update_survey_yn(survey=survey, db=db) + + if db_result_ori: + return { + "result": "OK" + } + else: + return { + "result": "FAIL" + } + diff --git a/fastapi/app/process/user/manage_user.py b/fastapi/app/process/user/manage_user.py index 18ba276..9a04330 100644 --- a/fastapi/app/process/user/manage_user.py +++ b/fastapi/app/process/user/manage_user.py @@ -5,10 +5,61 @@ from db.base import get_db from db import models, schemas from process.logger import logger + + +#================================================================================================== +# 구글 Oauth관련 +#================================================================================================== + +# DB에서 user 찾기 +async def select_user_seq_by_oauth_user_email(user_email, db): + db_result_ori = await crud_user.get_user_by_oauth_user_email(user_email=user_email, db=db) + + if len(db_result_ori) == 1: + return { + "result": "OK", + "user_seq": db_result_ori[0][0] + } + else: + return { + "result": "FAIL" + } + + +# 구글 유저 생성 +async def create_oauth_user(oauth_uid, user_email, user_id, user_nickname, db): + try: + create_oauth_user_result = await crud_user.create_oauth_user(oauth_uid=oauth_uid, user_email=user_email, user_id=user_id, user_nickname=user_nickname, db=db) + if not create_oauth_user_result: + return { + "result": "FAIL" + } + db_result_ori = await crud_user.get_user_by_oauth_user_email(user_email=user_email, db=db) + + if len(db_result_ori) == 1: + return { + "result": "OK", + "user_seq": db_result_ori[0][0] + } + else: + return { + "result": "FAIL" + } + except Exception as e: + logger.error(f"create_google_user error. URL: /user/google/signup\nerror message: {e}") + return { + "result": "FAIL" + } + + +#================================================================================================== +# 일반 로그인관련 +#================================================================================================== + # 로그인 수행 async def do_login(user_id, user_pw, db): # DB에서 유저 정보 확인 - db_result_ori = crud_user.do_login(user_id=user_id, user_pw=user_pw, db=db) + db_result_ori = await crud_user.do_login(user_id=user_id, user_pw=user_pw, db=db) db_result = [] for db_data in db_result_ori: db_result.append(db_data) @@ -28,7 +79,7 @@ async def do_login(user_id, user_pw, db): # 마지막 로그인 시간 업데이트 async def update_last_login_dt(user_seq, db): # 마지막 로그인 시간 업데이트 - db_result = crud_user.update_last_login_dt(user_seq=user_seq, db=db) + db_result = await crud_user.update_last_login_dt(user_seq=user_seq, db=db) if db_result: return { @@ -43,7 +94,7 @@ async def update_last_login_dt(user_seq, db): # 아이디 찾기(닉네임, 이메일) async def find_id_by_name_email(nickname, user_email, db): # DB에서 회원정보 찾기 - db_result_ori = crud_user.find_id_by_name_email(nickname=nickname, user_email=user_email, db=db) + db_result_ori = await crud_user.find_id_by_name_email(nickname=nickname, user_email=user_email, db=db) db_result = [] for db_data in db_result_ori: db_result.append(db_data) @@ -65,7 +116,7 @@ async def find_id_by_name_email(nickname, user_email, db): # 아이디 찾기(user_seq) async def find_id_by_user_seq(user_seq, db): # DB에서 회원정보 찾기 - db_result_ori = crud_user.find_id_by_user_seq(user_seq=user_seq, db=db) + db_result_ori = await crud_user.find_id_by_user_seq(user_seq=user_seq, db=db) db_result = [] for db_data in db_result_ori: db_result.append(db_data) @@ -86,7 +137,7 @@ async def find_id_by_user_seq(user_seq, db): # 이메일 발송 3회 이상 됐는지 확인 async def select_send_email_cnt(user_email, db): - db_result_ori = crud_user.select_send_email_cnt(user_email=user_email, db=db) + db_result_ori = await crud_user.select_send_email_cnt(user_email=user_email, db=db) db_result = [] for db_data in db_result_ori: db_result.append(db_data) @@ -100,7 +151,7 @@ async def select_send_email_cnt(user_email, db): # 이메일 발송내역 기록(하루 3회만 발송가능하게 하기 위함) async def insert_send_email_info(user_seq, cert_type, user_info, cert_code, db): - db_result = crud_user.insert_send_email_info(user_seq=user_seq, cert_type=cert_type, user_info=user_info, cert_code=cert_code, db=db) + db_result = await crud_user.insert_send_email_info(user_seq=user_seq, cert_type=cert_type, user_info=user_info, cert_code=cert_code, db=db) if db_result: return { @@ -115,7 +166,7 @@ async def insert_send_email_info(user_seq, cert_type, user_info, cert_code, db): # 비밀번호 찾기 수행 async def find_password_by_id_email(user_id, user_email, db): # DB에서 회원정보 찾기 - db_result_ori = crud_user.find_password_by_id_email(user_id=user_id, user_email=user_email, db=db) + db_result_ori = await crud_user.find_password_by_id_email(user_id=user_id, user_email=user_email, db=db) db_result = [] for db_data in db_result_ori: db_result.append(db_data) @@ -135,7 +186,7 @@ async def find_password_by_id_email(user_id, user_email, db): # 비밀번호 업데이트 수행 async def update_new_password(user_seq, new_pw, new_solt, db): # 회원정보 업데이트 - db_result = crud_user.update_new_password(user_seq=user_seq, new_pw=new_pw, new_solt=new_solt, db=db) + db_result = await crud_user.update_new_password(user_seq=user_seq, new_pw=new_pw, new_solt=new_solt, db=db) if db_result: return { @@ -147,10 +198,24 @@ async def update_new_password(user_seq, new_pw, new_solt, db): } +# 이메일 중복 확인 +async def is_valid_user_email_by_user_email(user_email, db): + db_result_ori = await crud_user.is_valid_user_email_by_user_email(user_email=user_email, db=db) + + if len(db_result_ori) == 0: + return { + "result": "OK" + } + else: + return { + "result": "FAIL" + } + + # 유저 회원가입 진행 async def insert_new_user(user_info, db): # DB에서 신규 유저 등록 - db_result_manage_user = crud_user.insert_new_user(user_info=user_info, db=db) + db_result_manage_user = await crud_user.insert_new_user(user_info=user_info, db=db) # 인증코드 입력 결과 if not db_result_manage_user: @@ -165,7 +230,7 @@ async def insert_new_user(user_info, db): # 프로필 이미지 업데이트 async def update_profile_img(user_seq, profile_img, db): - db_result = crud_user.update_profile_img(user_seq=user_seq, profile_img=profile_img, db=db) + db_result = await crud_user.update_profile_img(user_seq=user_seq, profile_img=profile_img, db=db) # 인증코드 입력 결과 if db_result: @@ -181,7 +246,7 @@ async def update_profile_img(user_seq, profile_img, db): # 마이페이지 - 유저 정보 가져오기 async def get_my_info_by_user_seq(user_seq, db): # DB에서 유저 정보 가져오기 - db_result_ori = crud_user.get_my_info_by_user_seq(user_seq=user_seq, db=db) + db_result_ori = await crud_user.get_my_info_by_user_seq(user_seq=user_seq, db=db) db_result = [] for db_data in db_result_ori: db_result.append(db_data) @@ -207,7 +272,7 @@ async def get_my_info_by_user_seq(user_seq, db): # 현재 비밀번호 일치 확인 async def check_current_user_pw(user_seq, user_pw, db): - db_result_ori = crud_user.check_current_user_pw(user_seq=user_seq, user_pw=user_pw, db=db) + db_result_ori = await crud_user.check_current_user_pw(user_seq=user_seq, user_pw=user_pw, db=db) db_result = [] for db_data in db_result_ori: db_result.append(db_data) @@ -225,7 +290,7 @@ async def check_current_user_pw(user_seq, user_pw, db): # 회원정보 업데이트 async def update_user_info(user_info, db): # 회원정보 업데이트 - db_result = crud_user.update_user_info(user_info=user_info, db=db) + db_result = await crud_user.update_user_info(user_info=user_info, db=db) if db_result: return { @@ -239,7 +304,7 @@ async def update_user_info(user_info, db): # 회원 탈퇴 처리 async def user_withdraw(user_seq, db): - db_result = crud_user.user_withdraw(user_seq=user_seq, db=db) + db_result = await crud_user.user_withdraw(user_seq=user_seq, db=db) if db_result: return { diff --git a/fastapi/app/process/user/manage_user_pattern.py b/fastapi/app/process/user/manage_user_pattern.py index 55f9f6c..8361791 100644 --- a/fastapi/app/process/user/manage_user_pattern.py +++ b/fastapi/app/process/user/manage_user_pattern.py @@ -102,7 +102,7 @@ def validate_user_phone(user_phone: str) -> bool: # 유저 아이디 중복 검사 async def is_valid_user_id_by_user_id(user_id, db): # DB에서 user_id 중복 확인하기 - db_result_ori = crud_user.is_valid_user_id_by_user_id(user_id=user_id, db=db) + db_result_ori = await crud_user.is_valid_user_id_by_user_id(user_id=user_id, db=db) db_result = [] for db_data in db_result_ori: db_result.append(db_data) diff --git a/fastapi/app/router/inquiry_api.py b/fastapi/app/router/inquiry_api.py new file mode 100644 index 0000000..cb3c8a9 --- /dev/null +++ b/fastapi/app/router/inquiry_api.py @@ -0,0 +1,99 @@ +from fastapi import APIRouter, Depends, HTTPException, Header, Body, status, Request +from sqlalchemy.orm import Session +from fastapi.security import APIKeyHeader +from typing import Union, Optional, List +from typing_extensions import Annotated +from db import models, schemas, crud +import json +import logging +import datetime +from kafka import KafkaProducer +from fastapi.responses import FileResponse, StreamingResponse +import io +import openpyxl +import time + +from db.schemas import RawData, RtuGenerator +from db.base import get_db +from db.models import RawDatas, Raw_data_herit +import pandas as pd + +from process.logger import logger + +from process.certification import cert_process +from process.response import response + +from process.inquiry import manage_inquiry + +KST = datetime.timezone(datetime.timedelta(hours=9)) + +router = APIRouter( + prefix="/inquiry", + tags=["inquiry"], + responses={404: {"description": "Not found"}}, +) + +# ----------------------------------------------------------------------------------------------- + +async def get_body(request: Request): + return await request.body() + +#================================================================================================== +# 문의 데이터 수집 +#================================================================================================== +@router.post("/request") +async def request_inquiry(request: Request, body: bytes = Depends(get_body), db: Session = Depends(get_db)): + try: + # 인증서 갱신 + auth_token = cert_process.renew_cert(request=request) + if auth_token['result'] == 'OK': + auth_token = auth_token['data'] + elif auth_token['result'] == 'TOKEN_EXPIRED': + raise token_expired_return_process(auth_token['msg']) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + # body에서 ID 추출 + try: + body = json.loads(body) + except json.JSONDecodeError as e: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='데이터 에러', msg_content='데이터 처리 장애가 발생했습니다. 요청정보를 정확히 입력했는지 확인해주세요.', data={}) + + user_seq_result = cert_process.get_user_seq_by_token(token=auth_token['token']) + if user_seq_result["result"] == 'OK': + user_seq = user_seq_result['data']['user_seq'] + body['user_seq'] = user_seq + # 데이터 검증 + title = body['title'] + contents = body['contents'] + # DB 저장 + insert_inquiry_result = await manage_inquiry.insert_inquiry(inquiry=body, db=db) + if insert_inquiry_result['result'] == 'OK': + return await response.ok_res(auth_token=auth_token, data={}, db=db) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='문의 저장 실패', msg_content='문의 저장 처리중 에러가 발생했습니다.', data={}) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + + except Exception as e: + logger.error(f"request error. URL: /room/score/create/room\nerror message: {e}") + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 생성 에러', msg_content='방 생성 처리중 에러가 발생했습니다.', data={}) + + + + + + + +#================================================================================================== +# 필요한 함수 +#================================================================================================== +# 401 에러 발생 +def token_expired_return_process(fail_msg): + logger.error(f"request fail: {fail_msg}") + return HTTPException( + status_code=401, + detail=f"{fail_msg}" + ) + + + diff --git a/fastapi/app/router/manage_user_api.py b/fastapi/app/router/manage_user_api.py index d5bb9b3..ea0ec35 100644 --- a/fastapi/app/router/manage_user_api.py +++ b/fastapi/app/router/manage_user_api.py @@ -14,10 +14,16 @@ import openpyxl import time import random import string - +from google.auth.transport import requests as google_requests +from google.oauth2 import id_token +import requests from db.schemas import RawData, RtuGenerator from db.base import get_db +# 파이어베이스 +from firebase_admin import credentials, auth +import firebase_admin + from process.logger import logger from process.certification import cert_process @@ -26,8 +32,12 @@ from process.user import manage_user from process.user import manage_user_pattern from process.email import email_user +from common import config + KST = datetime.timezone(datetime.timedelta(hours=9)) +GOOGLE_CLIENT_ID = config.GOOGLE_CLIENT_ID + router = APIRouter( prefix="/user", tags=["user"], @@ -39,6 +49,113 @@ router = APIRouter( async def get_body(request: Request): return await request.body() +#================================================================================================== +# 구글 로그인 +#================================================================================================== +@router.post("/google/login") +async def google_login(request: Request, body: bytes = Depends(get_body), db: Session = Depends(get_db)): + try: + # 인증서 갱신 + auth_token = cert_process.renew_cert(request=request) + auth_token = auth_token['data'] + # body에서 ID, PW 추출 + try: + body = json.loads(body) + except json.JSONDecodeError as e: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='데이터 에러', msg_content='데이터 처리 장애가 발생했습니다. 요청정보를 정확히 입력했는지 확인해주세요.', data={}) + + # 2) request body 파싱 + id_token_str = body.get('id_token', None) + + if not id_token_str: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='구글 토큰 에러', msg_content='구글 토큰 정보가 정확하지 않습니다.', data={}) + + decoded_token = auth.verify_id_token(id_token_str) + logger.debug(f"decoded_token: {decoded_token}") + + user_id = decoded_token['uid'] + user_email = decoded_token['email'].lower().strip() + user_nickname = decoded_token['name'] + # 닉네임이 없으면 랜덤 닉네임 생성 + if not user_nickname: + user_nickname = 'user' + str(time.time() * 19) + logger.debug(f"user_id: {user_id}, user_email: {user_email}, user_nickname: {user_nickname}") + + # 4) DB에서 user 찾기 + select_user_seq_by_oauth_user_email_result = await manage_user.select_user_seq_by_oauth_user_email(db=db, user_email=user_email) + if select_user_seq_by_oauth_user_email_result['result'] == 'FAIL': + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='로그인 실패', msg_content='가입되지 않은 구글 계정입니다. 회원가입이 필요합니다.', data={}) + + user_seq = select_user_seq_by_oauth_user_email_result['user_seq'] + + # 마지막 로그인 갱신 + update_last_login_dt_result = await manage_user.update_last_login_dt(user_seq=user_seq, db=db) + if update_last_login_dt_result['result'] == 'FAIL': + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='로그인 실패', msg_content='마지막 로그인 시간 업데이트에 실패했습니다.', data={}) + + # 5) JWT 발급 + final_auth_token = {"renew_yn": "Y", "token": cert_process.create_jwt(user_seq=user_seq, period=60*60*24*30), "user_seq": user_seq, "google_user_yn": "Y"} + + return await response.ok_res(auth_token=final_auth_token, data={}, db=db) + + except Exception as e: + logger.error(f"request error. URL: /user/google/login\nerror message: {e}") + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='로그인 에러', msg_content='로그인 처리중 에러가 발생했습니다.', data={}) + +#================================================================================================== +# 구글 회원가입 +#================================================================================================== +@router.post("/google/signup") +async def google_signup(request: Request, body: bytes = Depends(get_body), db: Session = Depends(get_db)): + try: + # 인증서 갱신 + auth_token = cert_process.renew_cert(request=request) + auth_token = auth_token['data'] + # body에서 ID, PW 추출 + try: + body = json.loads(body) + except json.JSONDecodeError as e: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='데이터 에러', msg_content='데이터 처리 장애가 발생했습니다. 요청정보를 정확히 입력했는지 확인해주세요.', data={}) + + id_token_str = body.get('id_token', None) + + if not id_token_str: + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='회원가입 실패', msg_content='id_token이 누락되었습니다.', data={}) + + decoded_token = auth.verify_id_token(id_token_str) + logger.debug(f"decoded_token: {decoded_token}") + + # 파이어베이스 토큰 분석 + user_id = decoded_token['uid'] + user_email = decoded_token['email'].lower().strip() + user_nickname = decoded_token['name'] + if not user_nickname: + user_nickname = 'user' + str(time.time() * 19) + logger.debug(f"user_email: {user_email}, user_nickname: {user_nickname}") + + # 4) DB에 이미 가입된 email인지 확인 + select_user_seq_by_oauth_user_email_result = await manage_user.select_user_seq_by_oauth_user_email(db=db, user_email=user_email) + if select_user_seq_by_oauth_user_email_result['result'] == 'OK': + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='회원가입 실패', msg_content='이미 구글 계정으로 가입된 이메일입니다.', data={}) + + # 5) 새 user 생성 + # 실제로는 DB 스키마에 "google_email", "google_sub" 필드 등 필요 (예시) TODO + create_oauth_user_result = await manage_user.create_oauth_user(oauth_uid=user_id, user_email=user_email, user_id=user_id, user_nickname=user_nickname, db=db) + + if create_oauth_user_result['result'] != 'OK': + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='회원가입 실패', msg_content='계정 생성에 실패했습니다.', data={}) + + new_user_seq = create_oauth_user_result['user_seq'] + + # 6) JWT 발급 + final_auth_token = {"renew_yn": "Y", "token": cert_process.create_jwt(user_seq=new_user_seq, period=60*60*24*30), "user_seq": new_user_seq, "google_user_yn": "Y"} + + return await response.ok_res(auth_token=final_auth_token, data={}, db=db) + + except Exception as e: + logger.error(f"request error. URL: /user/google/signup\nerror message: {e}") + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='로그인 에러', msg_content='로그인 처리중 에러가 발생했습니다.', data={}) + #================================================================================================== # 로그인 #================================================================================================== @@ -57,20 +174,15 @@ async def login(request: Request, body: bytes = Depends(get_body), db: Session = user_id = body['user_id'] user_pw = body['user_pw'] - logger.debug(f"test11") # ID, PW로 로그인 시도 login_result = await manage_user.do_login(user_id= user_id, user_pw= user_pw, db=db) - logger.debug(f"test12") # 로그인 결과에 따른 응답 if login_result['result'] == 'OK': - logger.debug(f"test13") user_seq = (login_result['user_seq'])[0] # 마지막 로그인 시간 업데이트 last_login_dt_result = await manage_user.update_last_login_dt(user_seq=user_seq, db=db) - logger.debug(f"test14") if last_login_dt_result['result'] == 'OK': - logger.debug(f"test15") auth_token = { "renew_yn": 'Y', "token": cert_process.create_jwt(user_seq=user_seq, period=60*60*24*30), @@ -78,10 +190,8 @@ async def login(request: Request, body: bytes = Depends(get_body), db: Session = } return await response.ok_res(auth_token=auth_token, data={}, db=db) else: - logger.debug(f"test16") return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='로그인 실패', msg_content='로그인 정보 업데이트에 실패했습니다.', data={}) else: - logger.debug(f"test17") return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='로그인 실패', msg_content='회원정보를 다시 확인해주세요.', data={}) except Exception as e: @@ -274,8 +384,8 @@ async def signup(request: Request, body: bytes = Depends(get_body), db: Session logger.debug(f"body: {body}") # user_id 유효성 검사 - is_valid_user_id = await manage_user_pattern.is_valid_user_id_by_user_id(user_id=body['user_id'], db=db) - fail_msg = None if is_valid_user_id else '아이디가 이미 존재합니다.' + is_valid_user_id_by_user_id_result = await manage_user_pattern.is_valid_user_id_by_user_id(user_id=body['user_id'], db=db) + fail_msg = None if is_valid_user_id_by_user_id_result else '아이디가 이미 존재합니다.' if fail_msg is not None: return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='회원가입 실패', msg_content=fail_msg, data={}) @@ -284,6 +394,11 @@ async def signup(request: Request, body: bytes = Depends(get_body), db: Session if mandatory_list_verify_msg is not None: return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='회원가입 실패', msg_content=mandatory_list_verify_msg, data={}) + # 이메일 중복 확인 + is_valid_user_email_by_user_email_result = await manage_user.is_valid_user_email_by_user_email(user_email=body['user_email'], db=db) + if is_valid_user_email_by_user_email_result['result'] == 'FAIL': + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='회원가입 실패', msg_content='이메일이 이미 존재합니다.', data={}) + # 회원가입 DB 입력 body['user_pw_solt'] = generate_random_string(10) # 비밀번호 SOLT 생성 insert_new_user_result = await manage_user.insert_new_user(user_info=body, db=db) @@ -354,12 +469,11 @@ async def update_profile_img(request: Request, body: str = Form(...), file: Uplo # 실제로 잘 저장됐는지 확인 if os.path.exists(file_path) and os.path.getsize(file_path) > 0: # # DB 업데이트해주기 - # update_profile_img_result = await manage_user.update_profile_img(user_seq=user_seq, profile_img=file_path.replace('images', ''), db=db) - # if update_profile_img_result['result'] == 'OK': - # return await response.ok_res(auth_token=auth_token, data={"img_src": '/'+file_path}, db=db) - # else: - # return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='이미지 업로드 실패', msg_content='이미지 업로드에 실패했습니다.', data={}) - return await response.ok_res(auth_token=auth_token, data={"img_src": '/'+file_path}, db=db) + update_profile_img_result = await manage_user.update_profile_img(user_seq=user_seq, profile_img=file_path.replace('images', ''), db=db) + if update_profile_img_result['result'] == 'OK': + return await response.ok_res(auth_token=auth_token, data={"img_src": '/'+file_path}, db=db) + else: + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='이미지 업로드 실패', msg_content='이미지 업로드에 실패했습니다.', data={}) else: return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='이미지 업로드 실패', msg_content='이미지 업로드에 실패했습니다.', data={}) else: @@ -500,21 +614,22 @@ async def withdraw_user(request: Request, body: bytes = Depends(get_body), db: S return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='데이터 에러', msg_content='데이터 처리 장애가 발생했습니다. 요청정보를 정확히 입력했는지 확인해주세요.', data={}) user_pw = body['user_pw'] + oauth_type = body['oauth_type'] user_seq_result = cert_process.get_user_seq_by_token(token=auth_token['token']) if user_seq_result["result"] == 'OK': user_seq = user_seq_result['data']['user_seq'] - # 현재 비밀번호 일치하는지 확인 - current_pw_correct_result = await manage_user.check_current_user_pw(user_seq=user_seq, user_pw=user_pw, db=db) - if current_pw_correct_result['result'] == 'OK': - # 회원 탈퇴 처리 - withdraw_result = await manage_user.user_withdraw(user_seq=user_seq, db=db) - if withdraw_result['result'] == 'OK': - return await response.ok_res(auth_token=auth_token, data={}, db=db) - else: - return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='회원탈퇴 에러', msg_content='회원탈퇴 처리중 에러가 발생헀습니다. 관리자에게 문의해주세요.', data={}) + if oauth_type == 'idpw': + # 현재 비밀번호 일치하는지 확인 + current_pw_correct_result = await manage_user.check_current_user_pw(user_seq=user_seq, user_pw=user_pw, db=db) + if current_pw_correct_result['result'] == 'FAIL': + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='현재 비밀번호 인증 실패', msg_content='현재 비밀번호가 일치하지 않습니다.', data={}) + # 회원 탈퇴 처리 + withdraw_result = await manage_user.user_withdraw(user_seq=user_seq, db=db) + if withdraw_result['result'] == 'OK': + return await response.ok_res(auth_token=auth_token, data={}, db=db) else: - return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='현재 비밀번호 인증 실패', msg_content='현재 비밀번호가 일치하지 않습니다.', data={}) + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='회원탈퇴 에러', msg_content='회원탈퇴 처리중 에러가 발생헀습니다. 관리자에게 문의해주세요.', data={}) else: logger.error(f"request error. URL: /user/withdraw/user\nerror message: {e}") return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) @@ -566,4 +681,26 @@ def get_now_time_str(): # YYYYMMDDHHMMSSsss 형식으로 포맷 formatted_time = now.strftime('%Y%m%d%H%M%S%f')[:17] - return formatted_time \ No newline at end of file + return formatted_time + + + + +# 구글 id_token 검증 +async def verify_google_id_token(id_token: str) -> dict: + """ + 실제로는 Google의 public key 등을 활용하여 id_token 서명 검증해야 합니다. + 간단히 tokeninfo endpoint를 사용하는 예시: + https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123 + """ + url = f"https://oauth2.googleapis.com/tokeninfo?id_token={id_token}" + try: + resp = await requests.get(url) + if resp.status_code == 200: + data = resp.json() + # data 안에 email, sub, name, picture, etc... + return data + else: + return {} + except Exception as e: + return {} diff --git a/fastapi/app/router/room_score_api.py b/fastapi/app/router/room_score_api.py index 723644f..084f2be 100644 --- a/fastapi/app/router/room_score_api.py +++ b/fastapi/app/router/room_score_api.py @@ -68,6 +68,11 @@ async def create_room(request: Request, body: bytes = Depends(get_body), db: Ses verify_create_room_data_result = await room_score_pattern.verify_create_room_data(data=body, db=db) if verify_create_room_data_result is not None: return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 생성 실패', msg_content=verify_create_room_data_result, data={}) + # 이미 입장되어 있는 대기중인 방이 있는지 확인 + check_already_enter_room_result = await room_score.check_already_enter_room(user_seq=user_seq, room_seq='0', db=db) + if check_already_enter_room_result['result'] == 'OK': + msg_content = f'이미 입장되어 있는 대기중인 방이 있습니다.\n방제목은 아래와 같습니다.\n{check_already_enter_room_result["room_title"]}' + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 생성 실패', msg_content=msg_content, data={}) # 방 생성 body = setting_etc_data(data=body) create_room_result = await room_score.create_room(data=body, db=db) @@ -169,16 +174,79 @@ async def start_game(request: Request, body: bytes = Depends(get_body), db: Sess check_granted_team_name_result = await room_score.check_granted_team_name(room_seq=body['room_seq'], db=db) if check_granted_team_name_result['result'] == 'FAIL': return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='게임 시작 실패', msg_content='팀전일 경우 팀배치가 완료되어야 시작가능합니다.', data={}) - # 방 상태 RUNNING으로 변경 - update_room_status_result = await room_score.update_room_status(room_seq=body['room_seq'], room_status='RUNNING', db=db) - if update_room_status_result['result'] == 'OK': + # FRD에도 team_name이 WAIT상태가 없는지 확인 + check_granted_team_name_result = await firebase_process.check_granted_team_name(room_seq=body['room_seq']) + if check_granted_team_name_result['result'] == 'FAIL': + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='게임 시작 실패', msg_content='팀전일 경우 팀배치가 완료되어야 시작가능합니다.', data={}) + # 방 상태 RUNNING으로 변경 & 시작시간 업데이트 + body['start_dt'] = datetime.datetime.now(KST).strftime('%Y-%m-%d %H:%M:%S') + update_room_status_start_dt_end_dt_result = await room_score.update_room_status_start_dt_end_dt(room_seq=body['room_seq'], room_status='RUNNING', start_dt=body['start_dt'], end_dt='', db=db) + if update_room_status_start_dt_end_dt_result['result'] == 'OK': # 파이어베이스 방 상태 업데이트 body['room_status'] = 'RUNNING' - update_firebase_room_status_result = await firebase_process.update_room_status(data=body) + update_firebase_room_status_result = await firebase_process.update_room_status_start_dt(data=body) if update_firebase_room_status_result['result'] == 'OK': return await response.ok_res(auth_token=auth_token, data={}, db=db) else: return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 상태 업데이트 에러', msg_content='방 상태 업데이트중 에러가 발생했습니다. 관리자에게 문의해주세요.', data={}) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='시작시간 업데이트 에러', msg_content='시작시간 업데이트중 에러가 발생했습니다. 관리자에게 문의해주세요.', data={}) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='게임 시작처리 에러', msg_content='방장에게만 게임시작 권한이 있습니다.', data={}) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + + except Exception as e: + logger.error(f"request error. URL: /room/score/game/start\nerror message: {e}") + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='(대기중인 방-게임 시작하기) 에러', msg_content='(대기중인 방-게임 시작하기) 처리중 에러가 발생했습니다.', data={}) + + +#================================================================================================== +# 진행중인 방 - 게임 종료 +#================================================================================================== +@router.post("/game/finish") +async def finish_game(request: Request, body: bytes = Depends(get_body), db: Session = Depends(get_db)): + try: + # 인증서 갱신 + auth_token = cert_process.renew_cert(request=request) + if auth_token['result'] == 'OK': + auth_token = auth_token['data'] + elif auth_token['result'] == 'TOKEN_EXPIRED': + raise token_expired_return_process(auth_token['msg']) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + # body에서 ID 추출 + try: + body = json.loads(body) + except json.JSONDecodeError as e: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='데이터 에러', msg_content='데이터 처리 장애가 발생했습니다. 요청정보를 정확히 입력했는지 확인해주세요.', data={}) + + user_seq_result = cert_process.get_user_seq_by_token(token=auth_token['token']) + if user_seq_result["result"] == 'OK': + user_seq = user_seq_result['data']['user_seq'] + # 요청자가 방장인지 확인 + check_requester_room_master_auth_result = await room_score.check_requester_room_master_auth(user_seq=user_seq, room_seq=body['room_seq'], db=db) + if check_requester_room_master_auth_result['result'] == 'OK': + # 방 상태가 진행중 인지 확인 + check_room_status_by_room_seq_room_status_result = await room_score.check_room_status_by_room_seq_room_status(room_seq=body['room_seq'], room_status='RUNNING', db=db) + if check_room_status_by_room_seq_room_status_result['result'] == 'FAIL': + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='게임 종료 실패', msg_content='게임 종료는 진행중 상태에서만 가능합니다.', data={}) + # 방 상태 FINISH로 변경 & 종료시간 업데이트 + body['end_dt'] = datetime.datetime.now(KST).strftime('%Y-%m-%d %H:%M:%S') + update_room_status_start_dt_end_dt_result = await room_score.update_room_status_start_dt_end_dt(room_seq=body['room_seq'], room_status='FINISH', start_dt='', end_dt=body['end_dt'], db=db) + if update_room_status_start_dt_end_dt_result['result'] == 'OK': + # 방 참여자 게임 참여 여부 업데이트 + update_participant_join_game_yn_result = await room_score.update_participant_join_game_yn(room_seq=body['room_seq'], db=db) + if update_participant_join_game_yn_result['result'] == 'OK': + # 파이어베이스 방 상태 업데이트 + body['room_status'] = 'FINISH' + update_firebase_room_status_result = await firebase_process.update_room_status_end_dt(data=body) + if update_firebase_room_status_result['result'] == 'OK': + return await response.ok_res(auth_token=auth_token, data={}, db=db) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 상태 업데이트 에러', msg_content='방 상태 업데이트중 에러가 발생했습니다. 관리자에게 문의해주세요.', data={}) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 상태 업데이트 에러', msg_content='방 상태 업데이트중 에러가 발생했습니다. 관리자에게 문의해주세요.', data={}) else: return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='게임 시작처리 에러', msg_content='게임 시작처리중 에러가 발생했습니다. 관리자에게 문의해주세요.', data={}) else: @@ -187,8 +255,8 @@ async def start_game(request: Request, body: bytes = Depends(get_body), db: Sess return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) except Exception as e: - logger.error(f"request error. URL: /room/score/game/start\nerror message: {e}") - return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='(대기중인 방-게임 시작하기) 에러', msg_content='(대기중인 방-게임 시작하기) 처리중 에러가 발생했습니다.', data={}) + logger.error(f"request error. URL: /room/score/game/finish\nerror message: {e}") + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='(진행중인 방-게임 종료) 에러', msg_content='(진행중인 방-게임 종료) 처리중 에러가 발생했습니다.', data={}) #================================================================================================== @@ -237,9 +305,9 @@ async def leave_game(request: Request, body: bytes = Depends(get_body), db: Sess # 일반 참여자가 방나가기 했을 경우 delete_room_score_participant_result = await room_score.delete_room_score_participant(user_seq=user_seq, room_seq=body['room_seq'], db=db) if delete_room_score_participant_result['result'] == 'OK': - # 파이어베이스 참여자 업데이트 + # 파이어베이스 나간 참여자 업데이트 logger.info(f"body: {body}") - update_firebase_participant_result = await firebase_process.update_participant(data=body) + update_firebase_participant_result = await firebase_process.update_exit_participant(data=body) if update_firebase_participant_result['result'] == 'OK': return await response.ok_res(auth_token=auth_token, data={}, db=db) else: @@ -279,11 +347,7 @@ async def check_connected_user(request: Request, body: bytes = Depends(get_body) user_seq_result = cert_process.get_user_seq_by_token(token=auth_token['token']) if user_seq_result["result"] == 'OK': user_seq = user_seq_result['data']['user_seq'] - # 요청자가 참여자인지 확인 - check_requester_participant_auth_result = await room_score.check_requester_participant_auth(user_seq=user_seq, room_seq=body['room_seq'], db=db) - if check_requester_participant_auth_result['result'] == 'OK': - # - 1 + # KAFKA 연결 여부 업데이트 else: return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) @@ -317,6 +381,7 @@ async def kick_participant(request: Request, body: bytes = Depends(get_body), db user_seq = user_seq_result['data']['user_seq'] # 방장이 맞는지 확인 check_requester_room_master_auth_result = await room_score.check_requester_room_master_auth(user_seq=user_seq, room_seq=body['room_seq'], db=db) + logger.info(f"check_requester_room_master_auth_result: {check_requester_room_master_auth_result}") if check_requester_room_master_auth_result['result'] == 'OK': # 대상 DB에서 참여자 삭제 delete_room_score_participant_result = await room_score.delete_room_score_participant(user_seq=body['target_user_seq'], room_seq=body['room_seq'], db=db) @@ -330,7 +395,7 @@ async def kick_participant(request: Request, body: bytes = Depends(get_body), db else: return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='참여자 강퇴 실패', msg_content='참여자 강퇴중 에러가 발생했습니다. 관리자에게 문의해주세요.', data={}) else: - return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='참여자 강퇴 실패', msg_content='참여자 강퇴 권한이 없습니다.', data={}) + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='참여자 강퇴 실패', msg_content='참여자 강퇴 권한이 없습니다.', data={}) else: return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) @@ -444,7 +509,7 @@ async def update_room_setting_info(request: Request, body: bytes = Depends(get_b if user_seq_result["result"] == 'OK': user_seq = user_seq_result['data']['user_seq'] # 방 참여자 조회 권한 확인 - check_auth_user_result = await room_score.check_auth_user(user_seq=user_seq, room_type=body['room_type'], room_seq=body['room_seq'], db=db) + check_auth_user_result = await room_score.check_auth_user(user_seq=user_seq, room_seq=body['room_seq'], db=db) if check_auth_user_result == 'FAIL': return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='참가자 조회 실패', msg_content='참가자 조회 권한이 없습니다.', data={}) # 방 설정정보 가져오기 @@ -642,10 +707,6 @@ async def enter_room(request: Request, body: bytes = Depends(get_body), db: Sess if open_yn == 'N': if str(room_pw) != str(body['room_pw']): return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 입장 실패', msg_content='방 비밀번호가 틀렸습니다.', data={}) - # 이미 입장한 유저인지 확인 - check_already_enter_user_result = await room_score.check_already_enter_user(room_seq=body['room_seq'], room_type=body['room_type'], user_seq=user_seq, db=db) - if check_already_enter_user_result['result'] == 'FAIL': - return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 입장 실패', msg_content='이미 입장한 유저입니다.', data={}) # 방번호, 방종류로 현재 인원수 체크 후 입장 가능여부 확인 check_now_number_of_people_and_can_enter_result = await room_score.check_now_number_of_people_and_can_enter(room_seq=body['room_seq'], db=db) if check_now_number_of_people_and_can_enter_result['result'] == 'FAIL': @@ -654,8 +715,19 @@ async def enter_room(request: Request, body: bytes = Depends(get_body), db: Sess check_kick_user_result = await firebase_process.check_kick_user(user_seq=user_seq, room_seq=body['room_seq']) if check_kick_user_result['result'] == 'OK': return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 입장 실패', msg_content='강퇴된 유저입니다.', data={}) - # 방 입장하기 - enter_room_user_result = await room_score.enter_room_user(room_seq=body['room_seq'], user_seq=user_seq, room_type=body['room_type'], db=db) + # 이미 입장되어 있는 대기중인 방이 있는지 확인 + check_already_enter_room_result = await room_score.check_already_enter_room(user_seq=user_seq, room_seq=body['room_seq'], db=db) + if check_already_enter_room_result['result'] == 'OK': + msg_content = f'이미 입장되어 있는 대기중인 방이 있습니다.\n방제목은 아래와 같습니다.\n{check_already_enter_room_result["room_title"]}' + return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 입장 실패', msg_content=msg_content, data={}) + # 이미 입장한 유저인지 확인 + check_already_enter_user_result = await room_score.check_already_enter_user(room_seq=body['room_seq'], room_type=body['room_type'], user_seq=user_seq, db=db) + if check_already_enter_user_result['result'] == 'OK': + # 방 입장하기 DB 입력 + enter_room_user_result = await room_score.enter_room_user(room_seq=body['room_seq'], user_seq=user_seq, room_type=body['room_type'], db=db) + else: + enter_room_user_result = {"result": "OK"} + # 방 입장하기 파이어베이스 입력 if enter_room_user_result['result'] == 'OK': # 입장하는 유저 정보 가져오기 enter_user_info_result = await room_score.enter_user_info(user_seq=user_seq, room_type=body['room_type'], db=db) @@ -674,6 +746,111 @@ async def enter_room(request: Request, body: bytes = Depends(get_body), db: Sess return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='(방 입장하기) 에러', msg_content='(방 입장하기) 처리중 에러가 발생했습니다.', data={}) +#================================================================================================== +# 진행중 강제종료 된 유저 진행중 방 입장하기 +#================================================================================================== +# @router.post("/enter/running/room") +# async def enter_running_room(request: Request, body: bytes = Depends(get_body), db: Session = Depends(get_db)): +# try: +# # 인증서 갱신 +# auth_token = cert_process.renew_cert(request=request) +# if auth_token['result'] == 'OK': +# auth_token = auth_token['data'] +# elif auth_token['result'] == 'TOKEN_EXPIRED': +# raise token_expired_return_process(auth_token['msg']) +# else: +# return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) +# # body에서 ID 추출 +# try: +# body = json.loads(body) +# except json.JSONDecodeError as e: +# return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='데이터 에러', msg_content='데이터 처리 장애가 발생했습니다. 요청정보를 정확히 입력했는지 확인해주세요.', data={}) + +# user_seq_result = cert_process.get_user_seq_by_token(token=auth_token['token']) +# if user_seq_result["result"] == 'OK': +# user_seq = user_seq_result['data']['user_seq'] +# body['user_seq'] = user_seq +# # 해당 유저가 참여중인 진행중인 방 조회 +# select_running_room_by_user_seq_result = await room_score.select_running_room_by_user_seq(user_seq=user_seq, db=db) +# logger.info(f"select_running_room_by_user_seq_result: {select_running_room_by_user_seq_result}") +# if select_running_room_by_user_seq_result['result'] == 'OK': +# # 파이어베이스 진행중 강제종료 된 유저인지 나가기한 유저인지 확인 +# firebase_check_force_exit_yn_result = await firebase_process.check_force_exit_yn(user_seq=user_seq, data=select_running_room_by_user_seq_result['data']) +# logger.info(f"firebase_check_force_exit_yn_result: {firebase_check_force_exit_yn_result}") +# if firebase_check_force_exit_yn_result['result'] == 'OK': +# data = { +# "force_exit_yn": "Y", +# "room_seq": firebase_check_force_exit_yn_result['room_seq'], +# "room_type_name": firebase_check_force_exit_yn_result['room_type_name'], +# "room_title": firebase_check_force_exit_yn_result['room_title'] +# } +# return await response.ok_res(auth_token=auth_token, data=data, db=db) +# return await response.ok_res(auth_token=auth_token, data={"force_exit_yn": "N"}, db=db) +# else: +# return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + +# except Exception as e: +# logger.error(f"request error. URL: /room/score/enter/running/room\nerror message: {e}") +# return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='(진행중 방 재입장하기) 에러', msg_content='(진행중 방 재입장하기) 처리중 에러가 발생했습니다.', data={}) + + +#================================================================================================== +# 메인페이지 랜딩시 필요한 정보 가져오기 - 설문조사 여부 확인 +#================================================================================================== +@router.post("/landing/mainpage/info") +async def get_landing_mainpage_info(request: Request, body: bytes = Depends(get_body), db: Session = Depends(get_db)): + try: + # 인증서 갱신 + auth_token = cert_process.renew_cert(request=request) + if auth_token['result'] == 'OK': + auth_token = auth_token['data'] + elif auth_token['result'] == 'TOKEN_EXPIRED': + raise token_expired_return_process(auth_token['msg']) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + # body에서 ID 추출 + try: + body = json.loads(body) + except json.JSONDecodeError as e: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='데이터 에러', msg_content='데이터 처리 장애가 발생했습니다. 요청정보를 정확히 입력했는지 확인해주세요.', data={}) + + user_seq_result = cert_process.get_user_seq_by_token(token=auth_token['token']) + if user_seq_result["result"] == 'OK': + user_seq = user_seq_result['data']['user_seq'] + body['user_seq'] = user_seq + data = {} + # 해당 유저가 참여중인 진행중인 방 조회 + select_running_room_by_user_seq_result = await room_score.select_running_room_by_user_seq(user_seq=user_seq, db=db) + if select_running_room_by_user_seq_result['result'] == 'OK': + # 파이어베이스 진행중 강제종료 된 유저인지 나가기한 유저인지 확인 + firebase_check_force_exit_yn_result = await firebase_process.check_force_exit_yn(user_seq=user_seq, data=select_running_room_by_user_seq_result['data']) + logger.info(f"firebase_check_force_exit_yn_result: {firebase_check_force_exit_yn_result}") + if firebase_check_force_exit_yn_result['result'] == 'OK': + data["force_exit_yn"] = "Y" + data["room_seq"] = firebase_check_force_exit_yn_result['room_seq'] + data["room_type_name"] = firebase_check_force_exit_yn_result['room_type_name'] + data["room_title"] = firebase_check_force_exit_yn_result['room_title'] + else: + data["force_exit_yn"] = "N" + + # 설문조사 여부 & 게임 참여 여부 확인 + select_nickname_survey_yn_join_game_yn_by_user_seq_result = await room_score.select_nickname_survey_yn_join_game_yn_by_user_seq(user_seq=user_seq, db=db) + if select_nickname_survey_yn_join_game_yn_by_user_seq_result['result'] == 'OK': + data["nickname"] = select_nickname_survey_yn_join_game_yn_by_user_seq_result['nickname'] + data["survey_yn"] = select_nickname_survey_yn_join_game_yn_by_user_seq_result['survey_yn'] + data["join_game_yn"] = select_nickname_survey_yn_join_game_yn_by_user_seq_result['join_game_yn'] + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='설문조사 여부 확인 에러', msg_content='설문조사 여부 확인 처리중 에러가 발생했습니다.', data={}) + + return await response.ok_res(auth_token=auth_token, data=data, db=db) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + + except Exception as e: + logger.error(f"request error. URL: /room/score/enter/running/room\nerror message: {e}") + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='(진행중 방 재입장하기) 에러', msg_content='(진행중 방 재입장하기) 처리중 에러가 발생했습니다.', data={}) + + #================================================================================================== # 진행중인방 점수 정보 가져오기 #================================================================================================== @@ -742,16 +919,17 @@ async def update_running_room_score(request: Request, body: bytes = Depends(get_ if user_seq_result["result"] == 'OK': user_seq = user_seq_result['data']['user_seq'] # 방 사회자 권한 확인 - select_master_user_seq_by_user_seq_and_room_seq_result = await room_score.select_master_user_seq_by_user_seq_and_room_seq(user_seq=user_seq, room_seq=body['room_seq'], db=db) - if select_master_user_seq_by_user_seq_and_room_seq_result == 'FAIL': + select_mc_user_seq_by_room_seq_result = await room_score.select_mc_user_seq_by_room_seq(user_seq=user_seq, room_seq=body['room_seq'], db=db) + if select_mc_user_seq_by_room_seq_result == 'FAIL': return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='점수 수정 실패', msg_content='점수 수정 권한이 없습니다.', data={}) # 방 상태가 진행중 인지 확인 check_room_status_by_room_seq_room_status_result = await room_score.check_room_status_by_room_seq_room_status(room_seq=body['room_seq'], room_status='RUNNING', db=db) if check_room_status_by_room_seq_room_status_result['result'] == 'FAIL': return await response.fail_res(auth_token=auth_token, auth_type='NOMAL', msg_title='점수 조회 실패', msg_content='점수 정보 조회는 진행중 상태만 조회가 가능합니다.', data={}) # 점수 수정하기 - update_user_score_result = await room_score.update_user_score(target_user_seq=body['target_user_seq'], after_score=body['after_score'], room_type=body['room_type'], room_seq=body['room_seq'], db=db) + update_user_score_result = await room_score.update_user_score(target_user_seq=body['target_user_seq'], after_score=body['after_score'], room_seq=body['room_seq'], db=db) if update_user_score_result['result'] == 'OK': + # 파이어베이스 점수 업데이트 update_firebase_score_result = await firebase_process.update_firebase_score(room_seq=body['room_seq'], user_seq=body['target_user_seq'], newScore=body['after_score']) if update_firebase_score_result['result'] == 'OK': return await response.ok_res(auth_token=auth_token, data={}, db=db) @@ -764,6 +942,46 @@ async def update_running_room_score(request: Request, body: bytes = Depends(get_ return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='(점수 수정하기) 에러', msg_content='(점수 수정하기) 처리중 에러가 발생했습니다.', data={}) +#================================================================================================== +# 종료된 방 정보 가져오기 +#================================================================================================== +@router.post("/get/finish/room/info") +async def get_finish_room_info(request: Request, body: bytes = Depends(get_body), db: Session = Depends(get_db)): + try: + # 인증서 갱신 + auth_token = cert_process.renew_cert(request=request) + if auth_token['result'] == 'OK': + auth_token = auth_token['data'] + elif auth_token['result'] == 'TOKEN_EXPIRED': + raise token_expired_return_process(auth_token['msg']) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + # body에서 ID 추출 + try: + body = json.loads(body) + except json.JSONDecodeError as e: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='데이터 에러', msg_content='데이터 처리 장애가 발생했습니다. 요청정보를 정확히 입력했는지 확인해주세요.', data={}) + + user_seq_result = cert_process.get_user_seq_by_token(token=auth_token['token']) + if user_seq_result["result"] == 'OK': + user_seq = user_seq_result['data']['user_seq'] + # 종료된 방 정보 가져오기 + select_finish_room_info_result = await room_score.select_finish_room_info(room_seq=body['room_seq'], db=db) + if select_finish_room_info_result['result'] == 'OK': + data = { + "room_info": select_finish_room_info_result['room_info'], + "user_info": select_finish_room_info_result['user_info'] + } + return await response.ok_res(auth_token=auth_token, data=data, db=db) + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='종료된 방 정보 가져오기 에러', msg_content='종료된 방 정보 가져오기 처리중 에러가 발생했습니다.', data={}) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + + except Exception as e: + logger.error(f"request error. URL: /room/score/update/score\nerror message: {e}") + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='(점수 수정하기) 에러', msg_content='(점수 수정하기) 처리중 에러가 발생했습니다.', data={}) + + diff --git a/fastapi/app/router/survey_api.py b/fastapi/app/router/survey_api.py new file mode 100644 index 0000000..ea25bfa --- /dev/null +++ b/fastapi/app/router/survey_api.py @@ -0,0 +1,107 @@ +from fastapi import APIRouter, Depends, HTTPException, Header, Body, status, Request +from sqlalchemy.orm import Session +from fastapi.security import APIKeyHeader +from typing import Union, Optional, List +from typing_extensions import Annotated +from db import models, schemas, crud +import json +import logging +import datetime +from kafka import KafkaProducer +from fastapi.responses import FileResponse, StreamingResponse +import io +import openpyxl +import time + +from db.schemas import RawData, RtuGenerator +from db.base import get_db +from db.models import RawDatas, Raw_data_herit +import pandas as pd + +from process.logger import logger + +from process.certification import cert_process +from process.response import response + +from process.survey import manage_survey + +KST = datetime.timezone(datetime.timedelta(hours=9)) + +router = APIRouter( + prefix="/survey", + tags=["survey"], + responses={404: {"description": "Not found"}}, +) + +# ----------------------------------------------------------------------------------------------- + +async def get_body(request: Request): + return await request.body() + +#================================================================================================== +# 설문조사 데이터 수집 +#================================================================================================== +@router.post("/collect") +async def collect_survey(request: Request, body: bytes = Depends(get_body), db: Session = Depends(get_db)): + try: + # 인증서 갱신 + auth_token = cert_process.renew_cert(request=request) + if auth_token['result'] == 'OK': + auth_token = auth_token['data'] + elif auth_token['result'] == 'TOKEN_EXPIRED': + raise token_expired_return_process(auth_token['msg']) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + # body에서 ID 추출 + try: + body = json.loads(body) + except json.JSONDecodeError as e: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='데이터 에러', msg_content='데이터 처리 장애가 발생했습니다. 요청정보를 정확히 입력했는지 확인해주세요.', data={}) + + user_seq_result = cert_process.get_user_seq_by_token(token=auth_token['token']) + if user_seq_result["result"] == 'OK': + user_seq = user_seq_result['data']['user_seq'] + body['user_seq'] = user_seq + # 데이터 검증 + qna_list = body['QNA'] + question_list = [] + answer_list = [] + for idx, qna in enumerate(qna_list): + if idx%2 == 0: + question_list.append(qna) + else: + answer_list.append(qna) + body['question_list'] = question_list + body['answer_list'] = answer_list + # DB 저장 + insert_survey_update_survey_yn_result = await manage_survey.insert_survey_update_survey_yn(survey=body, db=db) + if insert_survey_update_survey_yn_result['result'] == 'OK': + return await response.ok_res(auth_token=auth_token, data={}, db=db) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='설문조사 저장 실패', msg_content='설문조사 저장 처리중 에러가 발생했습니다.', data={}) + else: + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='토큰 에러', msg_content='토큰 정보가 정확하지 않습니다.', data={}) + + except Exception as e: + logger.error(f"request error. URL: /room/score/create/room\nerror message: {e}") + return await response.error_res(auth_token=auth_token, auth_type='NOMAL', msg_title='방 생성 에러', msg_content='방 생성 처리중 에러가 발생했습니다.', data={}) + + + + + + + +#================================================================================================== +# 필요한 함수 +#================================================================================================== +# 401 에러 발생 +def token_expired_return_process(fail_msg): + logger.error(f"request fail: {fail_msg}") + return HTTPException( + status_code=401, + detail=f"{fail_msg}" + ) + + +