Nhiệm vụ: Tích hợp các phiên (session) frontend của MODX vào ngữ cảnh xác thực của haih-agent
Tích hợp các phiên (session) frontend của MODX vào ngữ cảnh xác thực của haih-agent
Hướng dẫn frontend mới của Kilfor nhận diện người dùng hiện tại trực tiếp thông qua session MODX hiện có mà không phụ thuộc vào legacy HTTP endpoint.
Bối cảnh
Các phiên người dùng Kilfor hiện tại được lưu trữ và quản lý bởi MODX. Frontend mới dựa trên haih-agent đã tự thực hiện một phần logic ứng dụng, do đó nó định kỳ cần thông tin chi tiết về người dùng hiện tại đã được xác thực.
MODX có PHP API nội bộ để làm việc với người dùng hiện tại bên trong MODX runtime, nhưng không có sẵn HTTP endpoint bên ngoài tiêu chuẩn ở cấp độ current user cho ngữ cảnh frontend. modSociety có endpoint riêng để lấy thông tin người dùng, tuy nhiên frontend mới không được phụ thuộc vào thành phần legacy này.
Mục tiêu
Triển khai một tầng hạ tầng trong haih-agent có khả năng xác định người dùng được ủy quyền trong một ngữ cảnh frontend cụ thể (web hoặc ngữ cảnh khác) dựa trên cookie session MODX hiện có, và cung cấp dữ liệu người dùng đã chuẩn hóa cho mã ứng dụng của frontend mới.
Cần nghiên cứu và triển khai
- Tìm hiểu định dạng lưu trữ session frontend thực tế trong phiên bản MODX đang sử dụng và trên Kilfor.
- Xác định cách lấy người dùng cho một context key cụ thể từ session ID và dữ liệu
modx_session. - Phân tích cú pháp serialization của PHP một cách chính xác mà không phụ thuộc vào các mẹo dùng biểu thức chính quy (regex hack).
- Lấy dữ liệu người dùng cần thiết từ
modUser,modUserProfilevà các mối quan hệ dự án. - Biến phần cài đặt riêng cho MODX thành một adapter/provider độc lập để mã ứng dụng làm việc với trừu tượng hóa
currentUserthay vì phải biết cấu trúc session của MODX. - Không mã cứng (hardcode)
webvào trình phân tích cú pháp tầng thấp: context key phải được thiết lập qua cấu hình hoặc bởi tầng xác thực gọi đến. - Xử lý việc hết hạn/không hợp lệ của session và việc thiếu quyền xác thực trong ngữ cảnh được yêu cầu.
- Không chuyển đổi toàn bộ MODX ACL/security runtime nếu không có nhu cầu cụ thể; ở giai đoạn đầu, nhiệm vụ là xác định đáng tin cậy người dùng và dữ liệu của họ.
- Dự trù khả năng sử dụng các kho lưu trữ/trình xử lý session khác trong tương lai, tránh gắn kết chặt chẽ toàn bộ mã xác thực với các truy vấn SQL vào
modx_session. - Phủ kiểm thử parser và việc nhận diện người dùng bằng các fixture/integration test sử dụng dữ liệu mẫu session frontend MODX thực tế.
Kết quả mong đợi
Người dùng hiện tại đã được chuẩn hóa cho ngữ cảnh frontend được chỉ định, được lấy trực tiếp từ session MODX hiện có, sẽ có sẵn trong GraphQL/request context của haih-agent. Điều này loại bỏ yêu cầu phải gọi riêng một request tới legacy endpoint modSociety hoặc khởi động lại (bootstrap) MODX cho mỗi request của frontend mới.
Ворклоги
Tổng kết công việc
Nhiệm vụ đọc các phiên (session) frontend MODX hiện có ở phía haih-agent hầu như đã được giải quyết và có thể coi là hoàn thành.
Những gì đã được kiểm tra
Ở phía frontend mới, chúng tôi đã có thể đọc trực tiếp dữ liệu phiên MODX mà không cần bootstrap MODX và không cần gọi endpoint legacy modSociety. Điều này xác nhận khả năng kiến trúc về việc sử dụng MODX làm kho lưu trữ phiên hiện tại, trong khi việc phân tích cú pháp và xử lý dữ liệu tiếp theo sẽ được thực hiện bên trong haih-agent.
Ngoài ra, vấn đề kỹ thuật chính hóa ra không nằm ở việc đọc bản ghi phiên từ cơ sở dữ liệu, mà nằm ở việc giải tuần tự hóa (deserialize) payload phiên PHP của nó trong Node.js.
Vấn đề với php-serialize
php-serialize không giải quyết trực tiếp vấn đề này vì phiên MODX/PHP ở định dạng được sử dụng không chỉ đơn giản là kết quả của serialize($_SESSION). Do đó, thư viện này không phù hợp làm bộ giải mã phiên có sẵn cho trường hợp hiện tại.
Sử dụng php-session-unserialize
Để phân tích cú pháp phiên, gói php-session-unserialize đã được sử dụng. Nó đọc chính xác định dạng phiên PHP, nhưng một điểm đặc biệt trong cách triển khai của thư viện đã được phát hiện: các mảng kết hợp (associative array) của PHP bên trong readArray() luôn được tạo dưới dạng Array trong JavaScript.
Về cơ bản, thư viện thực hiện những việc sau:
const resultArray = []
resultArray[key] = value
Nếu mảng PHP chứa khóa chuỗi (string key), ví dụ như mgr, kết quả trong JavaScript là một mảng có thuộc tính được đặt tên (arr.mgr = ...). Trong console.log, dữ liệu này có thể nhìn thấy, nhưng JSON.stringify và GraphQL chỉ tuần tự hóa các phần tử mảng có chỉ mục (indexed element), do đó các thuộc tính có tên sẽ bị mất.
Ví dụ thực tế: giá trị phiên MODX dạng
modx.user.0.resourceGroups => { mgr: [] }
sau khi phân tích cú pháp ban đầu trông có vẻ chính xác trong log, nhưng qua GraphQL lại biến thành:
"modx.user.0.resourceGroups": []
Giải pháp tạm thời (Workaround) đã triển khai
Sau hàm unserialize(), một quá trình chuẩn hóa đệ quy kết quả đã được thêm vào:
function convertArraysToObjects(obj: unknown): unknown {
if (Array.isArray(obj)) {
const keys = Object.keys(obj)
const hasStringKeys = keys.some((k) => isNaN(Number(k)))
if (hasStringKeys) {
const result: Record<string, unknown> = {}
for (const key of keys) {
result[key] = convertArraysToObjects(
(obj as unknown as Record<string, unknown>)[key],
)
}
return result
}
return obj.map(convertArraysToObjects)
}
if (obj && typeof obj === 'object') {
const result: Record<string, unknown> = {}
for (const [key, value] of Object.entries(obj)) {
result[key] = convertArraysToObjects(value)
}
return result
}
return obj
}
Sau bước này, các mảng kết hợp PHP có khóa dạng chuỗi được chuyển đổi thành các đối tượng JS thông thường và đi qua JSON/GraphQL một cách chính xác.
Kết quả
Sau khi chuẩn hóa, dữ liệu phiên MODX được đọc chính xác, bao gồm cả các cấu trúc lồng nhau. Cụ thể, các nhánh sau đã được lấy thành công:
{
"modx.user.0.resourceGroups": {
"mgr": []
},
"modx.user.0.attributes": {
"web": {
"modAccessContext": {
"web": [
{
"principal": 0,
"authority": "0",
"policy": {
"load": true,
"formit": true,
"formit_encryptions": false
}
}
]
}
}
}
}
Ngoài ra, dữ liệu cho các người dùng/ ngữ cảnh khác cũng hiển thị trong phiên, ví dụ như modx.user.1.attributes và các cấu trúc ACL với tập hợp quyền quản lý (manager permissions) lớn. Tức là payload phiên giờ đây đã có sẵn hoàn toàn và không bị mất mát trong quá trình tuần tự hóa GraphQL.
Hạn chế của giải pháp hiện tại
Về mặt lý thuyết, bộ chuyển đổi hiện tại có thể chuyển đổi không rõ ràng đối với mảng PHP có cả khóa số và khóa chuỗi hỗn hợp: khi có ít nhất một khóa chuỗi, toàn bộ mảng JS sẽ biến thành Đối tượng (Object). Đối với các cấu trúc phiên MODX thông thường, điều này hiện không quá quan trọng; dữ liệu thực tế cần thiết trong dự án vẫn đến chính xác sau khi chuẩn hóa.
Do đó, ở giai đoạn này không cần thiết phải viết một trình phân tích cú pháp phiên PHP riêng hoặc fork thư viện. Nếu sau này gặp phải một payload phiên MODX thực tế nào mà sơ đồ hiện tại phân tích không chính xác, vấn đề đó có thể được tách thành một nhiệm vụ kỹ thuật riêng biệt.
Phạm vi của nhiệm vụ đã hoàn thành
Mục tiêu của nhiệm vụ này chính là khả năng cốt lõi trong việc đọc và giải tuần tự hóa chính xác phiên frontend MODX hiện có ở phía haih-agent. Mục tiêu này đã đạt được.
Logic xác định người dùng hiện tại cụ thể dựa trên nội dung phiên, lựa chọn ngữ cảnh frontend cần thiết, lấy dữ liệu người dùng bổ sung và tiếp tục xây dựng API auth/currentUser là lớp ứng dụng tiếp theo và nếu cần thiết, nên được định hình riêng biệt.