From 24e4db954a7032b478b3e977f09bd0c30982ee84 Mon Sep 17 00:00:00 2001 From: QuangMinh_123 Date: Wed, 10 Dec 2025 09:57:16 +0000 Subject: [PATCH] FixNameFile --- apps/ailbl-admin_phone-delete.py | 37 +++++ ...=> ailbl-admin_phone-insert-update-get.py} | 29 +--- ... => ailbl-user_phone-insert-update-get.py} | 59 +++----- apps/ailbl-user_phone_delete.py | 47 ++++++ apps/crud.py | 135 +++++++++++------- apps/filters.py | 4 +- apps/helpers.py | 6 +- apps/requirements.txt | 10 +- apps/validators.py | 2 +- 9 files changed, 205 insertions(+), 124 deletions(-) create mode 100644 apps/ailbl-admin_phone-delete.py rename apps/{ailbl-admin_avatar-insert-update-delete-get.py => ailbl-admin_phone-insert-update-get.py} (61%) rename apps/{ailbl-user_avatar-insert-update-delete-get.py => ailbl-user_phone-insert-update-get.py} (55%) create mode 100644 apps/ailbl-user_phone_delete.py diff --git a/apps/ailbl-admin_phone-delete.py b/apps/ailbl-admin_phone-delete.py new file mode 100644 index 0000000..85ec28f --- /dev/null +++ b/apps/ailbl-admin_phone-delete.py @@ -0,0 +1,37 @@ +import crud +from flask import jsonify, request + + +def main(): + """ + ```fission + { + "name": "phonenumbers-admin-delete", + "http_triggers": { + "phonenumbers-admin-delete-http": { + "url": "/ailbl/admin/users/{UserId}/phones/{UserPhoneId}", + "methods": ["DELETE"] + } + } + } + ``` + """ + try: + if request.method == "DELETE": + return make_delete_request() + else: + return {"error": "Method not allow"}, 405 + except Exception as ex: + return jsonify({"error": str(ex)}), 500 + + +def make_delete_request(): + try: + user_id = request.headers.get("X-User") + if not user_id: + return jsonify({"error": "user_id is required"}), 400 + + response, status = crud + return jsonify(response), status + except Exception as e: + return jsonify({"error": str(e)}), 500 diff --git a/apps/ailbl-admin_avatar-insert-update-delete-get.py b/apps/ailbl-admin_phone-insert-update-get.py similarity index 61% rename from apps/ailbl-admin_avatar-insert-update-delete-get.py rename to apps/ailbl-admin_phone-insert-update-get.py index 25a9813..e1a9379 100644 --- a/apps/ailbl-admin_avatar-insert-update-delete-get.py +++ b/apps/ailbl-admin_phone-insert-update-get.py @@ -2,26 +2,22 @@ import crud from flask import jsonify, request - - def main(): """ ```fission { - "name": "phonenumbers-admin-get-insert-delete", + "name": "phonenumbers-admin-get-insert", "http_triggers": { - "phonenumbers-admin-get-insert-delete-http": { + "phonenumbers-admin-get-insert-http": { "url": "/ailbl/admin/users/{UserId}/phones", - "methods": [ "POST", "DELETE", "GET"] + "methods": [ "POST", "GET"] } } } ``` """ try: - if request.method == "DELETE": - return make_delete_request() - elif request.method == "POST": + if request.method == "POST": return make_insert_request() elif request.method == "GET": return make_get_request() @@ -34,11 +30,11 @@ def main(): def make_insert_request(): try: user_id = request.headers.get("X-User") - + response, status = crud return jsonify(response), status except Exception as e: - return jsonify({"error": str(e)}), 500 + return jsonify({"error": str(e)}), 500 def make_get_request(): @@ -50,16 +46,3 @@ def make_get_request(): return crud except Exception as e: return jsonify({"error": str(e)}), 500 - - -def make_delete_request(): - try: - user_id = request.headers.get("X-User") - if not user_id: - return jsonify({"error": "user_id is required"}), 400 - - response, status = crud - return jsonify(response), status - except Exception as e: - return jsonify({"error": str(e)}), 500 - diff --git a/apps/ailbl-user_avatar-insert-update-delete-get.py b/apps/ailbl-user_phone-insert-update-get.py similarity index 55% rename from apps/ailbl-user_avatar-insert-update-delete-get.py rename to apps/ailbl-user_phone-insert-update-get.py index 575f79a..0453857 100644 --- a/apps/ailbl-user_avatar-insert-update-delete-get.py +++ b/apps/ailbl-user_phone-insert-update-get.py @@ -5,26 +5,22 @@ from helpers import CORS_HEADERS from validators import validate_phone_number - - def main(): """ ```fission { - "name": "phonenumbers-users-get-insert-delete", + "name": "phonenumbers-users-get-insert", "http_triggers": { - "phonenumbers-users-get-insert-delete-http": { + "phonenumbers-users-get-insert-http": { "url": "/ailbl/users/phones", - "methods": ["POST", "DELETE", "GET"] + "methods": ["POST", "GET"] } } } ``` """ try: - if request.method == "DELETE": - return make_delete_request() - elif request.method == "POST": + if request.method == "POST": return make_insert_request() elif request.method == "GET": return make_get_request() @@ -37,43 +33,24 @@ def main(): def make_insert_request(): try: user_id = request.headers.get("X-User") # Lay user_id tu header X-User - + if not user_id: return jsonify({"error": "user_id or file is required"}), 400, CORS_HEADERS - + data = request.get_json() - if not data: + if not data: return jsonify({"error": "phone_number is required"}), 400, CORS_HEADERS - + phone_number = data.get("phone_number") if not validate_phone_number(phone_number): return jsonify({"error": "Invalid phone number"}), 400, CORS_HEADERS - + + if crud.exists_phone(phone_number, user_id): + return jsonify({"error": "Phone is exists"}), 404 + response, status = crud.create_phone(user_id, data) - - return jsonify(response), status, CORS_HEADERS - except Exception as e: - return jsonify({"error": str(e)}), 500 - - - -def make_delete_request(): - try: - user_id = request.headers.get("X-User") # Lay user_id tu header X-User - if not user_id: - return jsonify({"error": "user_id is required"}), 400 - - phone_id = request.header.get("X-Fission-Params-UserPhoneId") - if not phone_id: - return jsonify({"error": "phone_id is required"}), 400 - - # Kiem tra so dien thoai co ton tai trong db khong ? - if not crud.exists_phone(user_id, phone_id): - return jsonify({"error": "Phone not found"}), 404 - - response, status = crud - return jsonify(response), status + return jsonify(response) except Exception as e: return jsonify({"error": str(e)}), 500 @@ -83,11 +60,13 @@ def make_get_request(): user_id = request.headers.get("X-User") if not user_id: return jsonify({"error": "user_id is required"}), 400, CORS_HEADERS - + # Lấy tham số filter và phân trang từ request - paging = PhonePage.from_request_queries() # Sử dụng default_factory để lấy filter và paging - - response = crud.filter_phone(user_id, paging) + # Sử dụng default_factory để lấy filter và paging + paging = PhonePage.from_request_queries() + print(paging) + + response = crud.filter_phone(user_id, paging) return jsonify(response), 200, CORS_HEADERS except Exception as e: return jsonify({"error": str(e)}), 500 diff --git a/apps/ailbl-user_phone_delete.py b/apps/ailbl-user_phone_delete.py new file mode 100644 index 0000000..d256b40 --- /dev/null +++ b/apps/ailbl-user_phone_delete.py @@ -0,0 +1,47 @@ +import crud +from flask import jsonify, request +from filters import PhonePage +from helpers import CORS_HEADERS + + +def main(): + """ + ```fission + { + "name": "phonenumbers-users-delete", + "http_triggers": { + "phonenumbers-users-delete-http": { + "url": "/ailbl/users/phones/{UserPhoneId}", + "methods": ["DELETE"] + } + } + } + ``` + """ + try: + if request.method == "DELETE": + return make_delete_request() + else: + return {"error": "Method not allow"}, 405 + except Exception as ex: + return jsonify({"error": str(ex)}), 500 + + +def make_delete_request(): + try: + user_id = request.headers.get("X-User") # Lay user_id tu header X-User + if not user_id: + return jsonify({"error": "user_id is required"}), 400 + + phone_id = request.headers.get("X-Fission-Params-UserPhoneId") + if not phone_id: + return jsonify({"error": "phone_id is required"}), 400 + + # Kiem tra so dien thoai co ton tai trong db khong ? + if not crud.exists_phone(phone_id, user_id): + return jsonify({"error": "Phone not found"}), 404 + + response, status = crud.delete_phone(phone_id, user_id) + return jsonify(response), status + except Exception as e: + return jsonify({"error": str(e)}), 500 diff --git a/apps/crud.py b/apps/crud.py index 8ae646a..92592f0 100644 --- a/apps/crud.py +++ b/apps/crud.py @@ -1,47 +1,55 @@ import io - +from filters import PhonePage from flask import jsonify, request from helpers import init_db_connection, CORS_HEADERS from PIL import Image -# Create&Update function to upload or update user avatar S3/Minio def create_phone(user_id: str, data): try: conn = init_db_connection() cursor = conn.cursor() - + # Câu truy vấn SQL để thêm số điện thoại vào bảng UserPhone query = """ - INSERT INTO UserPhone (user_id, PhoneNumber, Prefix, Created, Modified) - VALUES (%s, %s, %s, NOW(), NOW()) + INSERT INTO ailbl_user_phone (user_id, phone_number, prefix, area_code, created, modified) + VALUES (%s, %s, %s,%s, NOW(), NOW()) """ # Lấy các trường từ data phone_number = data.get("phone_number") - prefix = data.get("prefix", None) # Nếu không có prefix, có thể để null - + # Nếu không có prefix, có thể để null + prefix = data.get("prefix", None) + area_code = data.get("area_code") # Thực thi câu truy vấn SQL - cursor.execute(query, (user_id, phone_number, prefix)) + cursor.execute(query, (user_id, phone_number, prefix, area_code)) conn.commit() # Lưu thay đổi vào cơ sở dữ liệu - result = cursor.fetchall(), - - return result, 200, CORS_HEADERS + return { + "user_id": user_id, + "phone_number": phone_number, + "prefix": prefix, + "area": area_code, + "status": "added" + }, 200, CORS_HEADERS + + # result = cursor.fetchall() + # return {"message": "Phone created successfully"}, 200, CORS_HEADERS except Exception as e: - return {"error": str(e)}, 500 - + return {"error": str(e)}, 500, CORS_HEADERS -def filter_phone(user_id: str, paging): # Read function to get user avatar from S3/Minio +def filter_phone(user_id: str, paging): + conn = None # Khởi tạo conn với giá trị None + cursor = None try: conn = init_db_connection() - cursor = conn.cursor() - - #Xay dung dieu kien loc + cursor = conn.cursor() + + # Xay dung dieu kien loc conditions = ["user_id = %(user_id)s"] values = {"user_id": user_id} # Điều kiện cơ bản cho user_id - + # Lọc theo phone_number if paging.filter.phone_number: conditions.append("LOWER(PhoneNumber) LIKE %(phone_number)s") @@ -69,72 +77,95 @@ def filter_phone(user_id: str, paging): # Read function to get user avatar from if paging.filter.modified_to: conditions.append("Modified <= %(modified_to)s") values["modified_to"] = paging.filter.modified_to - + # Ket hop dieu kien loc - where_clause = "AND".join(conditions) - if where_clause: - where_clause = "WHERE" + where_clause - - #Sap xep ket qua neu co: - order_clause="" - if paging.sortby: - direction="ASC" if paging.asc else "DESC" + where_clause = " AND ".join(conditions) + if where_clause: + where_clause = "WHERE " + where_clause + + # Sap xep ket qua neu co: + order_clause = "" + if paging.sortby: + direction = "ASC" if paging.asc else "DESC" order_clause = f"ORDER BY {paging.sortby} {direction}" - + # Gop Truy van sql = f""" SELECT *, COUNT(*) OVER() AS total FROM ailbl_user_phone {where_clause} {order_clause} - LIMIT %(limit)s OFFSET%(offset)s - """ + LIMIT %(limit)s OFFSET %(offset)s + """ values["limit"] = paging.size values["offset"] = paging.page * paging.size - - cursor.execute(sql, values) # Thuc Thi Cau Truy Van + + cursor.execute(sql, values) # Thuc Thi Cau Truy Van phones = cursor.fetchall() - + + # Chuyển kết quả thành danh sách các đối tượng với tên trường rõ ràng + phone_list = [] + for phone in phones: + phone_dict = { + "id": phone[0], + "user_id": phone[1], + "phone_number": phone[2], + "prefix": phone[3], + "area_code": phone[4], + "created": phone[5], + "modified": phone[6] + } + phone_list.append(phone_dict) + return phones, 200, CORS_HEADERS - + except Exception as e: return {"error": str(e)}, 500 - finally: - if conn: + finally: + if conn: conn.close() -# Delete Function to delete user avatar from S3/Minio def delete_phone(phone_id: str, user_id: str) -> dict: try: conn = init_db_connection() cursor = conn.cursor() - + query = "DELETE FROM ailbl_user_phone WHERE id = %s AND user_id = %s" cursor.execute(query, (phone_id, user_id)) - conn.commit() # Save DB + conn.commit() # Save DB return {"message": "Phone deleted successfully"}, 200, CORS_HEADERS - + except Exception as e: return {"error": str(e)}, 500 -def exists_phone( phone_id:str, user_id:str): +def exists_phone(user_id: str, phone_number: str = None, phone_id: str = None): try: conn = init_db_connection() cursor = conn.cursor() - - cursor.execute(""" - SELECT 1 - FROM ailbl_user_phone - WHERE id = %s AND user_id = %s; + + if phone_number: # Nếu là `POST`, kiểm tra sự tồn tại của phone_number + cursor.execute(""" + SELECT 1 + FROM ailbl_user_phone + WHERE user_id = %s AND phone_number = %s + """, (user_id, phone_number)) + + elif phone_id: # Nếu là `DELETE`, kiểm tra sự tồn tại của phone_id + cursor.execute(""" + SELECT 1 + FROM ailbl_user_phone + WHERE id = %s AND user_id = %s """, (phone_id, user_id)) - - row = cursor.fetchone() # Co ket qua thi tra ve du lieu 1 dong - return row is not None # Nếu có dòng dữ liệu, trả về True (tồn tại số điện thoại), nếu không, trả về False + + row = cursor.fetchone() # Co ket qua thi tra ve du lieu 1 dong + # Nếu có dòng dữ liệu, trả về True (tồn tại số điện thoại), nếu không, trả về False + return row is not None except Exception as e: return False finally: - if conn: - conn.close() - + if cursor: + cursor.close() + if conn: + conn.close() # Đảm bảo đóng kết nối sau khi xong diff --git a/apps/filters.py b/apps/filters.py index 98d3536..1ad5d94 100644 --- a/apps/filters.py +++ b/apps/filters.py @@ -6,7 +6,7 @@ from helpers import str_to_bool @dataclasses.dataclass class PhoneFilter: - phone_numbers: Optional[str] = None + phone_number: Optional[str] = None prefix: Optional[str] = None created_from: Optional[str] = None created_to: Optional[str] = None @@ -41,7 +41,7 @@ class Page: @dataclasses.dataclass -class PhonePage(Page): # Ke thua +class PhonePage(Page): # Ke thua sortby: Optional[str] = None filter: PhoneFilter = dataclasses.field( default_factory=PhoneFilter.from_request_queries diff --git a/apps/helpers.py b/apps/helpers.py index 51d2bfa..c20cf06 100644 --- a/apps/helpers.py +++ b/apps/helpers.py @@ -10,6 +10,9 @@ from psycopg2.extras import LoggingConnection CORS_HEADERS = { "Content-Type": "application/json", } +SECRET_NAME = "fission-ailbl-user-phone-env" +CONFIG_NAME = "fission-eom-notification-config" +K8S_NAMESPACE = "default" logging.basicConfig(level=logging.DEBUG) @@ -95,6 +98,7 @@ def check_port_open(ip: str, port: int, timeout: int = 30): current_app.logger.err(f"Check port open error: {err}") return False + def str_to_bool(value: str | None) -> typing.Optional[bool]: if value is None: return None @@ -103,4 +107,4 @@ def str_to_bool(value: str | None) -> typing.Optional[bool]: return True if val in ("false", "0", "no"): return False - return None \ No newline at end of file + return None diff --git a/apps/requirements.txt b/apps/requirements.txt index 3347361..c4e3900 100644 --- a/apps/requirements.txt +++ b/apps/requirements.txt @@ -1,8 +1,8 @@ Flask==3.1.0 phonenumbers==8.12.17 requests==2.25.1 -# psycopg2-binary==2.9.10 -# pydantic==2.11.3 -# minio==7.2.5 -# Pillow==10.4.0 -# boto3==1.35.70 \ No newline at end of file +psycopg2-binary==2.9.10 +pydantic==2.11.3 +minio==7.2.5 +Pillow==10.4.0 +boto3==1.35.70 \ No newline at end of file diff --git a/apps/validators.py b/apps/validators.py index 57affae..4bca348 100644 --- a/apps/validators.py +++ b/apps/validators.py @@ -7,5 +7,5 @@ def validate_phone_number(phone_number: str) -> bool: try: parsed_number = phonenumbers.parse(phone_number) # Phân tích số điện thoại return phonenumbers.is_valid_number(parsed_number) # Kiểm tra tính hợp lệ của số - except NumberParseException: + except phonenumbers.phonenumberutil.NumberParseException: return False # Trả về False nếu số không hợp lệ