Let's Go Further مجوز مبتنی بر نقش › راه‌اندازی جدول پایگاه داده مجوزها
قبلی · فهرست مطالب · بعدی
فصل ۱۶.۲.

راه‌اندازی جدول پایگاه داده مجوزها

محدود کردن API به طوری که داده‌های فیلم فقط توسط کاربران فعال قابل دسترسی و ویرایش باشد، مفید است، اما گاهی اوقات ممکن است به سطح کنترل دقیق‌تری نیاز داشته باشید. به عنوان مثال، در مورد ما ممکن است راضی باشیم که کاربران «عادی» API ما بتوانند داده‌های فیلم را بخوانند (به شرطی که فعال باشند)، اما می‌خواهیم دسترسی نوشتن را به زیرمجموعه کوچکی از کاربران مورد اعتماد محدود کنیم.

در این فصل، مفهوم مجوزها (permissions) را به برنامه خود معرفی می‌کنیم، به طوری که فقط کاربرانی که مجوز خاصی دارند بتوانند عملیات خاصی انجام دهند. در مورد ما، دو مجوز ایجاد خواهیم کرد: مجوز movies:read که به کاربر اجازه می‌دهد فیلم‌ها را دریافت و فیلتر کند، و مجوز movies:write که به کاربران اجازه می‌دهد فیلم‌ها را ایجاد، ویرایش و حذف کنند.

مجوزهای مورد نیاز با endpoint‌های API ما به شرح زیر هماهنگ هستند:

متد الگوی URL مجوز مورد نیاز
GET /v1/healthcheck
GET /v1/movies movies:read
POST /v1/movies movies:write
GET /v1/movies/:id movies:read
PATCH /v1/movies/:id movies:write
DELETE /v1/movies/:id movies:write
POST /v1/users
PUT /v1/users/activated
POST /v1/tokens/authentication

رابطه بین مجوزها و کاربران

رابطه بین مجوزها و کاربران نمونه عالی از یک رابطه چند به چند است. یک کاربر ممکن است مجوزهای متعددی داشته باشد و همان مجوز ممکن است به کاربران متعددی تعلق داشته باشد.

روش کلاسیک مدیریت رابطه چند به چند در یک پایگاه داده رابطه‌ای مانند PostgreSQL، ایجاد یک جدول اتصال (joining table) بین دو موجودیت است. من به سرعت توضیح می‌دهم که این چگونه کار می‌کند.

فرض کنید داده‌های کاربران خود را در یک جدول users ذخیره می‌کنیم که به این شکل است:

id email
1 alice@example.com
2 bob@example.com

و داده‌های مجوزهای ما در یک جدول permissions به این شکل ذخیره می‌شوند:

id code
1 movies:read
2 movies:write

سپس می‌توانیم یک جدول اتصال به نام users_permissions ایجاد کنیم تا اطلاعات مربوط به کدام کاربران چه مجوزهایی دارند را ذخیره کند، مشابه این:

user_id permission_id
1 1
2 1
2 2

در مثال بالا، کاربر alice@example.com (شناسه کاربر 1) فقط مجوز movies:read (شناسه مجوز 1) را دارد، در حالی که bob@example.com (شناسه کاربر 2) هر دو مجوز movies:read و movies:write را دارد.

درست مانند رابطه یک به چند که قبلاً در کتاب بررسی کردیم، ممکن است بخواهید این رابطه را از هر دو طرف در مدل‌های پایگاه داده خود جستجو کنید. به عنوان مثال، در مدل‌های پایگاه داده خود ممکن است بخواهید متدهای زیر را ایجاد کنید:

PermissionModel.GetAllForUser(user)       → Retrieve all permissions for a user
UserModel.GetAllForPermission(permission) → Retrieve all users with a specific permission

ایجاد SQL migrations

بیایید این را عملی کنیم و یک SQL migration ایجاد کنیم که جداول permissions و users_permissions جدیدی در پایگاه داده ما ایجاد می‌کند، بر اساس الگویی که در بالا توضیح دادیم.

دستور زیر را اجرا کنید تا فایل‌های migration ایجاد شوند:

$ migrate create -seq -ext .sql -dir ./migrations add_permissions
/home/alex/Projects/greenlight/migrations/000006_add_permissions.up.sql
/home/alex/Projects/greenlight/migrations/000006_add_permissions.down.sql

سپس دستورات SQL زیر را به فایل migration ‘up’ اضافه کنید:

فایل: migrations/000006_add_permissions.up.sql
CREATE TABLE IF NOT EXISTS permissions (
    id bigserial PRIMARY KEY,
    code text NOT NULL
);

CREATE TABLE IF NOT EXISTS users_permissions (
    user_id bigint NOT NULL REFERENCES users ON DELETE CASCADE,
    permission_id bigint NOT NULL REFERENCES permissions ON DELETE CASCADE,
    PRIMARY KEY (user_id, permission_id)
);

-- Add the two permissions to the table.
INSERT INTO permissions (code)
VALUES 
    ('movies:read'),
    ('movies:write');

چند نکته مهم در اینجا وجود دارد:

بیایید دستورات DROP TABLE لازم را نیز به فایل migration ‘down’ اضافه کنیم، به شکل زیر:

فایل: migrations/000006_add_permissions.down.sql
DROP TABLE IF EXISTS users_permissions;
DROP TABLE IF EXISTS permissions;

حالا که این کار تمام شد، لطفاً migration را اجرا کنید:

$ migrate -path ./migrations -database $GREENLIGHT_DB_DSN up
6/u add_permissions (22.74009ms)