UserPhoneDone
Some checks failed
K8S Fission Deployment / Deployment fission functions (push) Failing after 21s
Some checks failed
K8S Fission Deployment / Deployment fission functions (push) Failing after 21s
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
import crud
|
import crud
|
||||||
from flask import jsonify, request
|
from flask import jsonify, request
|
||||||
|
from filters import PhonePage
|
||||||
|
from helpers import CORS_HEADERS
|
||||||
|
from validators import validate_phone_number
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -34,14 +37,21 @@ 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
|
||||||
# Lay file tu form-data voi key la 'avatar'
|
|
||||||
file = request.files.get("avatar")
|
|
||||||
if not user_id or not file:
|
|
||||||
return jsonify({"error": "user_id or file is required"}), 400
|
|
||||||
|
|
||||||
|
if not user_id:
|
||||||
|
return jsonify({"error": "user_id or file is required"}), 400, CORS_HEADERS
|
||||||
|
|
||||||
response, status = crud
|
data = request.get_json()
|
||||||
return jsonify(response), status
|
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
|
||||||
|
|
||||||
|
response, status = crud.create_phone(user_id, data)
|
||||||
|
|
||||||
|
return jsonify(response), status, CORS_HEADERS
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"error": str(e)}), 500
|
return jsonify({"error": str(e)}), 500
|
||||||
|
|
||||||
@@ -53,7 +63,14 @@ def make_delete_request():
|
|||||||
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 is required"}), 400
|
return jsonify({"error": "user_id is required"}), 400
|
||||||
# Call CRUD function to delete avatar
|
|
||||||
|
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
|
response, status = crud
|
||||||
return jsonify(response), status
|
return jsonify(response), status
|
||||||
@@ -65,9 +82,12 @@ def make_get_request():
|
|||||||
try:
|
try:
|
||||||
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
|
return jsonify({"error": "user_id is required"}), 400, CORS_HEADERS
|
||||||
|
|
||||||
return crud
|
# Lấy tham số filter và phân trang từ request
|
||||||
# return jsonify(response), status
|
paging = PhonePage.from_request_queries() # Sử dụng default_factory để lấy filter và paging
|
||||||
|
|
||||||
|
response = crud.filter_phone(user_id, paging)
|
||||||
|
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
|
||||||
|
|||||||
120
apps/crud.py
120
apps/crud.py
@@ -1,38 +1,140 @@
|
|||||||
import io
|
import io
|
||||||
|
|
||||||
from flask import Response
|
from flask import jsonify, request
|
||||||
from helpers import S3_BUCKET, get_secret, s3_client
|
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
|
# Create&Update function to upload or update user avatar S3/Minio
|
||||||
def create_phone(user_id: str, file):
|
def create_phone(user_id: str, data):
|
||||||
try:
|
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())
|
||||||
|
"""
|
||||||
|
# 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
|
||||||
|
|
||||||
return result, 200
|
# Thực thi câu truy vấn SQL
|
||||||
|
cursor.execute(query, (user_id, phone_number, prefix))
|
||||||
|
conn.commit() # Lưu thay đổi vào cơ sở dữ liệu
|
||||||
|
|
||||||
|
result = cursor.fetchall(),
|
||||||
|
|
||||||
|
return result, 200, CORS_HEADERS
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"error": str(e)}, 500
|
return {"error": str(e)}, 500
|
||||||
|
|
||||||
|
|
||||||
def get_phone(user_id: str): # Read function to get user avatar from S3/Minio
|
|
||||||
|
def filter_phone(user_id: str, paging): # Read function to get user avatar from S3/Minio
|
||||||
try:
|
try:
|
||||||
|
conn = init_db_connection()
|
||||||
|
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
|
||||||
|
|
||||||
return Response(
|
# Lọc theo phone_number
|
||||||
|
if paging.filter.phone_number:
|
||||||
|
conditions.append("LOWER(PhoneNumber) LIKE %(phone_number)s")
|
||||||
|
values["phone_number"] = f"%{paging.filter.phone_number.lower()}%"
|
||||||
|
|
||||||
), 200
|
# Lọc theo prefix
|
||||||
|
if paging.filter.prefix:
|
||||||
|
conditions.append("Prefix = %(prefix)s")
|
||||||
|
values["prefix"] = paging.filter.prefix
|
||||||
|
|
||||||
|
# Lọc theo ngày tạo
|
||||||
|
if paging.filter.created_from:
|
||||||
|
conditions.append("Created >= %(created_from)s")
|
||||||
|
values["created_from"] = paging.filter.created_from
|
||||||
|
|
||||||
|
if paging.filter.created_to:
|
||||||
|
conditions.append("Created <= %(created_to)s")
|
||||||
|
values["created_to"] = paging.filter.created_to
|
||||||
|
|
||||||
|
# Lọc theo ngày sửa đổi
|
||||||
|
if paging.filter.modified_from:
|
||||||
|
conditions.append("Modified >= %(modified_from)s")
|
||||||
|
values["modified_from"] = paging.filter.modified_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"
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
values["limit"] = paging.size
|
||||||
|
values["offset"] = paging.page * paging.size
|
||||||
|
|
||||||
|
cursor.execute(sql, values) # Thuc Thi Cau Truy Van
|
||||||
|
phones = cursor.fetchall()
|
||||||
|
|
||||||
|
return phones, 200, CORS_HEADERS
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"error": str(e)}, 500
|
return {"error": str(e)}, 500
|
||||||
|
finally:
|
||||||
|
if conn:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
# Delete Function to delete user avatar from S3/Minio
|
# Delete Function to delete user avatar from S3/Minio
|
||||||
def delete_phone(user_id: str) -> dict:
|
def delete_phone(phone_id: str, user_id: str) -> dict:
|
||||||
try:
|
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
|
||||||
|
return {"message": "Phone deleted successfully"}, 200, CORS_HEADERS
|
||||||
|
|
||||||
return result, 200
|
|
||||||
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):
|
||||||
|
try:
|
||||||
|
conn = init_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
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
|
||||||
|
except Exception as e:
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if conn:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class Page:
|
|||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class PhonePage(Page):
|
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
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
# Flask==3.1.0
|
Flask==3.1.0
|
||||||
|
phonenumbers==8.12.17
|
||||||
|
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
|
||||||
|
|||||||
11
apps/validators.py
Normal file
11
apps/validators.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# validators.py
|
||||||
|
import phonenumbers
|
||||||
|
from phonenumbers import NumberParseException
|
||||||
|
|
||||||
|
def validate_phone_number(phone_number: str) -> bool:
|
||||||
|
"""Kiểm tra tính hợp lệ của số điện thoại"""
|
||||||
|
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:
|
||||||
|
return False # Trả về False nếu số không hợp lệ
|
||||||
Reference in New Issue
Block a user