Multi-Tenancy là gì? Cách thực hiện với Simple Trait trong Laravel?

644
Multi-Tenancy là gì

Multi-Tenancy là gì?

Multi-Tenancy là một hệ thống web application có nhiều khách hàng cùng sử dụng nhưng dữ liệu giữa các khách hàng hoàn tập độc lập, khách hàng này không thể truy cập vào dữ liệu của khách hàng kia.

Ví dụ cơ bản

  • Hệ thống quản lý khách sạn cho phép nhiều khách sạn có thể truy cập với những tài khoản độc lập, dữ liệu độc lập, nhưng vẫn cùng chung 1 hệ thống site.
  • Hệ thống quản lý công văn sử dụng trong tổng công ty và nhiều công ty con, cùng site nhưng dữ liệu độc lập.
  • Hệ thống quản lý dự án Jira
  • Hệ thống CRM của zoho, saleforce ….

Bài toán multi-tenancy thực tế gặp rất nhiều và tùy theo từng hệ thống sẽ triển khai theo mỗi cách khác nhau. Ở bài viết này, mình sẽ cùng bạn tìm hiểu để implement một cách đơn giản nhất vào project Laravel Framework nhé!

Bài toán

Có một hệ thống quản lí khách sạn và danh sách book phòng theo từng khách sạn.

  • CEO của khách sạn A đăng kí tài khoản vào hệ thống, sau đó tạo các khách sạn để quản lí.
  • CEO của khách sạn B cũng tương tự vậy (đăng kí tài khoản vào hệ thống, sau đó tạo các khách sạn để quản lí.)

Vấn đề:

  • Nếu không Multi-Tenancy: CEO A có thể thấy được các thông tin của khách sạn ông B gồm: tên, địa chỉ của các khách hàng đã đặt phòng trên khách sạn ông B ==> Lộ thông tin rồi, ông A lúc này có thể lợi dụng những thông tin có được để thực hiện những hành vi không đúng: spam email + số điện thoại chẳng hạn…
  • Nếu có Multi-Tenancy: Tất cả dữ liệu khách sạn của ông A và ông B hoàn toàn độc lập, không liên quan và không ai có thể thấy hay truy cập vào các dữ liệu của người khác (trừ admin).

Migration

Tạo thêm 1 trường created_by_user_id trong bảng hotels. Trường này dùng để xác định ông nào đã tạo ra cái khách sạn ấy trên hệ thống.

  • Note: Từ ver 5.8, Laravel đã thay đổi kiểu dữ liệu (data type) trường Id là big int. Vậy nên khi liên kết khóa ngoại, bạn cũng phải set data type của trường liên kết là big int nhé.

Sau đó, thêm created_by_user_id vào fillable trong Model

Bây giờ làm sao để field tự insert vào DB khi user tạo mới một Hotels? Bạn có thể sử dụng Model Observers. Tuy nhiên để mở rộng và tái sử dụng ở các Model khác nhau, mình sẽ tạo ra 1 Trait Multitenantable thay vì cứ mỗi Model mình lại tạo ra 1 Observers như vầy. Xem thêm một số kiến thức về Migration trong Laravel tại đây để hiểu hơn các bạn nhé.

Trait Multitenantable

Tạo file app/Traits/Multitenantable.php

  • Note: hàm bootMultitenantable() với name convention là bootXYZ(), Laravel sẽ tự chạy hàm này khi Trait được sử dụng (Có thể gọi nó là trait “constructor”)
  Service Provider là gì? Tìm hiểu Service Provider trong Laravel
  Xây dựng ứng dụng chat realtime bằng Laravel + Vuejs + Socket + Redis

Trait Multitenantable sẽ có nhiệm vụ khi user đó tạo một thứ gì đó thì nó tự động insert vào DB ở field created_by_user_id với value là id của user đang đang nhập.

Implement trait này vào model Hotel

Kết quả khi tạo mới 1 Hotel:

Filtering Data bằng User

Đây là bước quan trọng nhất để giải quyết bài toán: Tất cả dữ liệu khách sạn của ông A và ông B hoàn toàn độc lập, không liên quan và không ai có thể thấy hay truy cập vào các dữ liệu của người khác.

Trong Laravel rất đơn giản, ta dùng Global Scope để fillter tất cả các query trên Model.

Thêm vào trait Multitenantable như sau:

Oki, lúc này nó sẽ lọc tất cả các khách sạn của user đang nhập hiện tại, còn các khách sạn của user khác hoàn toàn ko hiển thị và không access vào được.

SQL thuần nó sẽ như này:SELECT * FROM hotels WHERE created_by_user_id=1 (với 1 là id của user đang đăng nhập).

Kết quả ở Hotel list:

Thử truy cập vào thằng hotel có id=1 mà chưa set trường created_by_user_id

404 ngay.

Bây giờ bạn thử set created_by_user_id=2, back lại và xem kết quả nhé (Thêm 1 record ở list + có thể access vào rồi)

Làm sao để admin thấy được tất cả?

Ngoài ra để đảm bảo thằng Admin có thể view được hết các dữ liệu trên hệ thống thì bạn check thêm if nhé.

Ok, vậy là coi như mình đã implement Multi-Tenancy trên model Hotels rồi.

Giờ muốn tái sử dụng Trait này, thì bạn cứ use trong Model là ngon ngay (Nhớ model implement phải có trường created_by_user_id).

Kết luận

Trên đây mình đã giới thiệu với bạn Multi-Tenancy là gì? Cách implement Multi-Tenancy một cách đơn giản nhất vào project Laravel Framework như thế nào. Hi vọng từ bài viết này bạn có thể hiểu về Multi-Tenancy và áp dụng vào các bài toán của mình.

Tham khảo:

TopDev via viblo

  Cơ cấu xử lý request trong Laravel như thế nào?
  Nhận diện khuôn mặt trong ứng dụng Laravel sử dụng Google Cloud Vision API