FixNameFile
Some checks failed
K8S Fission Deployment / Deployment fission functions (push) Failing after 21s

This commit is contained in:
QuangMinh_123
2025-12-10 09:57:16 +00:00
parent 085501b946
commit 24e4db954a
9 changed files with 205 additions and 124 deletions

View File

@@ -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

View File

@@ -2,26 +2,22 @@ import crud
from flask import jsonify, request from flask import jsonify, request
def main(): def main():
""" """
```fission ```fission
{ {
"name": "phonenumbers-admin-get-insert-delete", "name": "phonenumbers-admin-get-insert",
"http_triggers": { "http_triggers": {
"phonenumbers-admin-get-insert-delete-http": { "phonenumbers-admin-get-insert-http": {
"url": "/ailbl/admin/users/{UserId}/phones", "url": "/ailbl/admin/users/{UserId}/phones",
"methods": [ "POST", "DELETE", "GET"] "methods": [ "POST", "GET"]
} }
} }
} }
``` ```
""" """
try: try:
if request.method == "DELETE": if request.method == "POST":
return make_delete_request()
elif request.method == "POST":
return make_insert_request() return make_insert_request()
elif request.method == "GET": elif request.method == "GET":
return make_get_request() return make_get_request()
@@ -34,11 +30,11 @@ def main():
def make_insert_request(): def make_insert_request():
try: try:
user_id = request.headers.get("X-User") user_id = request.headers.get("X-User")
response, status = crud response, status = crud
return jsonify(response), status return jsonify(response), status
except Exception as e: except Exception as e:
return jsonify({"error": str(e)}), 500 return jsonify({"error": str(e)}), 500
def make_get_request(): def make_get_request():
@@ -50,16 +46,3 @@ def make_get_request():
return crud return crud
except Exception as e: except Exception as e:
return jsonify({"error": str(e)}), 500 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

View File

@@ -5,26 +5,22 @@ from helpers import CORS_HEADERS
from validators import validate_phone_number from validators import validate_phone_number
def main(): def main():
""" """
```fission ```fission
{ {
"name": "phonenumbers-users-get-insert-delete", "name": "phonenumbers-users-get-insert",
"http_triggers": { "http_triggers": {
"phonenumbers-users-get-insert-delete-http": { "phonenumbers-users-get-insert-http": {
"url": "/ailbl/users/phones", "url": "/ailbl/users/phones",
"methods": ["POST", "DELETE", "GET"] "methods": ["POST", "GET"]
} }
} }
} }
``` ```
""" """
try: try:
if request.method == "DELETE": if request.method == "POST":
return make_delete_request()
elif request.method == "POST":
return make_insert_request() return make_insert_request()
elif request.method == "GET": elif request.method == "GET":
return make_get_request() return make_get_request()
@@ -37,43 +33,24 @@ def main():
def make_insert_request(): def make_insert_request():
try: try:
user_id = request.headers.get("X-User") # Lay user_id tu header X-User user_id = request.headers.get("X-User") # Lay user_id tu header X-User
if not user_id: if not user_id:
return jsonify({"error": "user_id or file is required"}), 400, CORS_HEADERS return jsonify({"error": "user_id or file is required"}), 400, CORS_HEADERS
data = request.get_json() data = request.get_json()
if not data: if not data:
return jsonify({"error": "phone_number is required"}), 400, CORS_HEADERS return jsonify({"error": "phone_number is required"}), 400, CORS_HEADERS
phone_number = data.get("phone_number") phone_number = data.get("phone_number")
if not validate_phone_number(phone_number): if not validate_phone_number(phone_number):
return jsonify({"error": "Invalid phone number"}), 400, CORS_HEADERS 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) response, status = crud.create_phone(user_id, data)
return jsonify(response), status, CORS_HEADERS
except Exception as e:
return jsonify({"error": str(e)}), 500
return jsonify(response)
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
except Exception as e: except Exception as e:
return jsonify({"error": str(e)}), 500 return jsonify({"error": str(e)}), 500
@@ -83,11 +60,13 @@ def make_get_request():
user_id = request.headers.get("X-User") user_id = request.headers.get("X-User")
if not user_id: if not user_id:
return jsonify({"error": "user_id is required"}), 400, CORS_HEADERS return jsonify({"error": "user_id is required"}), 400, CORS_HEADERS
# Lấy tham số filter và phân trang từ request # 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 # Sử dụng default_factory để lấy filter và paging
paging = PhonePage.from_request_queries()
response = crud.filter_phone(user_id, paging) print(paging)
response = crud.filter_phone(user_id, paging)
return jsonify(response), 200, CORS_HEADERS return jsonify(response), 200, CORS_HEADERS
except Exception as e: except Exception as e:
return jsonify({"error": str(e)}), 500 return jsonify({"error": str(e)}), 500

View File

@@ -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

View File

@@ -1,47 +1,55 @@
import io import io
from filters import PhonePage
from flask import jsonify, request from flask import jsonify, request
from helpers import init_db_connection, CORS_HEADERS from helpers import init_db_connection, CORS_HEADERS
from PIL import Image from PIL import Image
# Create&Update function to upload or update user avatar S3/Minio
def create_phone(user_id: str, data): def create_phone(user_id: str, data):
try: try:
conn = init_db_connection() conn = init_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
# Câu truy vấn SQL để thêm số điện thoại vào bảng UserPhone # Câu truy vấn SQL để thêm số điện thoại vào bảng UserPhone
query = """ query = """
INSERT INTO UserPhone (user_id, PhoneNumber, Prefix, Created, Modified) INSERT INTO ailbl_user_phone (user_id, phone_number, prefix, area_code, created, modified)
VALUES (%s, %s, %s, NOW(), NOW()) VALUES (%s, %s, %s,%s, NOW(), NOW())
""" """
# Lấy các trường từ data # Lấy các trường từ data
phone_number = data.get("phone_number") 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 # 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 conn.commit() # Lưu thay đổi vào cơ sở dữ liệu
result = cursor.fetchall(), return {
"user_id": user_id,
return result, 200, CORS_HEADERS "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: 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: try:
conn = init_db_connection() conn = init_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
#Xay dung dieu kien loc # Xay dung dieu kien loc
conditions = ["user_id = %(user_id)s"] conditions = ["user_id = %(user_id)s"]
values = {"user_id": user_id} # Điều kiện cơ bản cho user_id values = {"user_id": user_id} # Điều kiện cơ bản cho user_id
# Lọc theo phone_number # Lọc theo phone_number
if paging.filter.phone_number: if paging.filter.phone_number:
conditions.append("LOWER(PhoneNumber) LIKE %(phone_number)s") 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: if paging.filter.modified_to:
conditions.append("Modified <= %(modified_to)s") conditions.append("Modified <= %(modified_to)s")
values["modified_to"] = paging.filter.modified_to values["modified_to"] = paging.filter.modified_to
# Ket hop dieu kien loc # Ket hop dieu kien loc
where_clause = "AND".join(conditions) where_clause = " AND ".join(conditions)
if where_clause: if where_clause:
where_clause = "WHERE" + where_clause where_clause = "WHERE " + where_clause
#Sap xep ket qua neu co: # Sap xep ket qua neu co:
order_clause="" order_clause = ""
if paging.sortby: if paging.sortby:
direction="ASC" if paging.asc else "DESC" direction = "ASC" if paging.asc else "DESC"
order_clause = f"ORDER BY {paging.sortby} {direction}" order_clause = f"ORDER BY {paging.sortby} {direction}"
# Gop Truy van # Gop Truy van
sql = f""" sql = f"""
SELECT *, COUNT(*) OVER() AS total SELECT *, COUNT(*) OVER() AS total
FROM ailbl_user_phone FROM ailbl_user_phone
{where_clause} {where_clause}
{order_clause} {order_clause}
LIMIT %(limit)s OFFSET%(offset)s LIMIT %(limit)s OFFSET %(offset)s
""" """
values["limit"] = paging.size values["limit"] = paging.size
values["offset"] = paging.page * 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() 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 return phones, 200, CORS_HEADERS
except Exception as e: except Exception as e:
return {"error": str(e)}, 500 return {"error": str(e)}, 500
finally: finally:
if conn: if conn:
conn.close() conn.close()
# Delete Function to delete user avatar from S3/Minio
def delete_phone(phone_id: str, user_id: str) -> dict: def delete_phone(phone_id: str, user_id: str) -> dict:
try: try:
conn = init_db_connection() conn = init_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
query = "DELETE FROM ailbl_user_phone WHERE id = %s AND user_id = %s" query = "DELETE FROM ailbl_user_phone WHERE id = %s AND user_id = %s"
cursor.execute(query, (phone_id, user_id)) cursor.execute(query, (phone_id, user_id))
conn.commit() # Save DB conn.commit() # Save DB
return {"message": "Phone deleted successfully"}, 200, CORS_HEADERS return {"message": "Phone deleted successfully"}, 200, CORS_HEADERS
except Exception as e: except Exception as e:
return {"error": str(e)}, 500 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: try:
conn = init_db_connection() conn = init_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(""" if phone_number: # Nếu là `POST`, kiểm tra sự tồn tại của phone_number
SELECT 1 cursor.execute("""
FROM ailbl_user_phone SELECT 1
WHERE id = %s AND user_id = %s; 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)) """, (phone_id, user_id))
row = cursor.fetchone() # Co ket qua thi tra ve du lieu 1 dong 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 # 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: except Exception as e:
return False return False
finally: finally:
if conn: if cursor:
conn.close() cursor.close()
if conn:
conn.close() # Đảm bảo đóng kết nối sau khi xong

View File

@@ -6,7 +6,7 @@ from helpers import str_to_bool
@dataclasses.dataclass @dataclasses.dataclass
class PhoneFilter: class PhoneFilter:
phone_numbers: Optional[str] = None phone_number: Optional[str] = None
prefix: Optional[str] = None prefix: Optional[str] = None
created_from: Optional[str] = None created_from: Optional[str] = None
created_to: Optional[str] = None created_to: Optional[str] = None
@@ -41,7 +41,7 @@ class Page:
@dataclasses.dataclass @dataclasses.dataclass
class PhonePage(Page): # Ke thua class PhonePage(Page): # Ke thua
sortby: Optional[str] = None sortby: Optional[str] = None
filter: PhoneFilter = dataclasses.field( filter: PhoneFilter = dataclasses.field(
default_factory=PhoneFilter.from_request_queries default_factory=PhoneFilter.from_request_queries

View File

@@ -10,6 +10,9 @@ from psycopg2.extras import LoggingConnection
CORS_HEADERS = { CORS_HEADERS = {
"Content-Type": "application/json", "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) 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}") current_app.logger.err(f"Check port open error: {err}")
return False return False
def str_to_bool(value: str | None) -> typing.Optional[bool]: def str_to_bool(value: str | None) -> typing.Optional[bool]:
if value is None: if value is None:
return None return None
@@ -103,4 +107,4 @@ def str_to_bool(value: str | None) -> typing.Optional[bool]:
return True return True
if val in ("false", "0", "no"): if val in ("false", "0", "no"):
return False return False
return None return None

View File

@@ -1,8 +1,8 @@
Flask==3.1.0 Flask==3.1.0
phonenumbers==8.12.17 phonenumbers==8.12.17
requests==2.25.1 requests==2.25.1
# psycopg2-binary==2.9.10 psycopg2-binary==2.9.10
# pydantic==2.11.3 pydantic==2.11.3
# minio==7.2.5 minio==7.2.5
# Pillow==10.4.0 Pillow==10.4.0
# boto3==1.35.70 boto3==1.35.70

View File

@@ -7,5 +7,5 @@ def validate_phone_number(phone_number: str) -> bool:
try: try:
parsed_number = phonenumbers.parse(phone_number) # Phân tích số điện thoại 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ố 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ệ return False # Trả về False nếu số không hợp lệ