वेब अनुप्रयोगों की एक सामान्य आवश्यकता विशिष्ट भूमिकाओं और अनुमतियों को निर्दिष्ट करने की क्षमता है।
कई प्रकार के वेब एप्लिकेशन प्रतिबंधित पहुंच प्रदान करने में व्यवस्थापक और नियमित उपयोगकर्ताओं के बीच अंतर करते हैं। यह अक्सर एक साधारण बूलियन का उपयोग करके किया जाता है जो यह निर्धारित करता है कि उपयोगकर्ता एक व्यवस्थापक है या नहीं। हालाँकि, भूमिकाएँ और अनुमतियाँ बहुत अधिक जटिल हो सकती हैं।
आपके आवेदन का मूल्य कुछ डेटा और कार्यों तक पहुंच को प्रतिबंधित करने में निहित है। यह निश्चित रूप से ऐसा कुछ है जिसे आप गड़बड़ नहीं करना चाहते हैं। इस पोस्ट में, हम समझाएंगे कि एक बुनियादी रूबी ऑन रेल्स एप्लिकेशन में भूमिकाओं और अनुमतियों को कैसे लागू किया जाए।
क्या मुझे अनुमतियों को प्रबंधित करने के लिए एक रत्न की आवश्यकता है?
नहीं, आपको रत्न की आवश्यकता नहीं है, खासकर यदि आपका आवेदन छोटा है और आप अपने कोड आधार पर अधिक निर्भरता जोड़ने से बचना चाहते हैं। हालांकि, यदि आप विकल्पों की तलाश कर रहे हैं, तो यहां सबसे लोकप्रिय रत्न हैं जो भूमिकाओं और अनुमतियों से संबंधित हैं। :
-
DeviseDevise प्रमाणीकरण और भूमिका प्रबंधन के लिए एक रत्न है, और यह वास्तव में एक जटिल और मजबूत समाधान है। GitHub पर 21.7k सितारों के साथ, यह इस पोस्ट में सबसे लोकप्रिय रेपो है, लेकिन यह भूमिका प्रबंधन से अधिक करता है। इसे एक प्रमाणीकरण समाधान के रूप में जाना जाता है, इसलिए इसे अपने कोडबेस पर तभी लागू करें जब आपको एक बहुत मजबूत लाइब्रेरी की आवश्यकता हो।
-
पंडित:पंडित एक रत्न है जो साधारण रूबी वस्तुओं का उपयोग करता है, और शायद यह सबसे सरल नीति रत्न है जिसे हम कवर करेंगे। उपयोग करने में आसान है, न्यूनतम प्राधिकरण है, और शुद्ध रूबी का उपयोग करने के समान है। GitHub पर 7.3k सितारों के साथ, यह वर्तमान में सबसे लोकप्रिय नीति रत्न है।
-
कैनकैन:कैनकैन एक प्राधिकरण पुस्तकालय है जो उन संसाधनों को प्रतिबंधित करता है जिन्हें किसी दिए गए उपयोगकर्ता को एक्सेस करने की अनुमति है। हालांकि, कैनकैन को वर्षों से छोड़ दिया गया है और केवल रेल 3 और पहले के रिलीज के साथ काम करता है।
-
CanCanCan:CanCanCan रूबी और रूबी ऑन रेल्स के लिए एक और प्राधिकरण पुस्तकालय है। यह कैनकैन का एक विकल्प है और वर्तमान में इसका रखरखाव किया जा रहा है। GitHub पर 4.9k सितारों के साथ, यह सबसे कम लोकप्रिय है, लेकिन यह बहुत अच्छी तरह से काम करता है और अच्छी तरह से बनाए रखा जाता है।
ये सभी रत्न बहुत अच्छे हैं, लेकिन सादे रूबी में स्वयं अनुमतियाँ बनाना बहुत कठिन नहीं है। पॉलिसी ऑब्जेक्ट पैटर्न नामक रणनीति का उपयोग करके, मैं आपको दिखाऊंगा कि बिना रत्न के अनुमतियों को कैसे प्रबंधित किया जाए।
नीति ऑब्जेक्ट पैटर्न
पॉलिसी ऑब्जेक्ट एक डिज़ाइन पैटर्न है जिसका उपयोग अनुमतियों और भूमिकाओं से निपटने के लिए किया जाता है। आप इसका उपयोग हर बार यह जांचने के लिए कर सकते हैं कि क्या कुछ या किसी को कोई कार्य करने की अनुमति है। यह जटिल व्यावसायिक नियमों को समाहित करता है और विभिन्न नियमों के साथ अन्य नीतिगत वस्तुओं द्वारा आसानी से प्रतिस्थापित किया जा सकता है। सभी बाहरी निर्भरताओं को पॉलिसी ऑब्जेक्ट में इंजेक्ट किया जाता है, अनुमति जांच तर्क को समाहित करता है, जिसके परिणामस्वरूप एक स्वच्छ नियंत्रक और मॉडल होता है। पंडित, कैनकन और कैनकन जैसे रत्न इस पैटर्न को लागू कर सकते हैं।
शुद्ध नीति ऑब्जेक्ट नियम
- रिटर्न एक बूलियन मान होना चाहिए
- तर्क सरल होना चाहिए
- विधि के अंदर, हमें केवल पारित वस्तुओं पर विधियों को कॉल करना चाहिए
कार्यान्वयन
आइए नामकरण परंपरा से शुरू करें; फ़ाइल नाम में _policy
है प्रत्यय लागू और अंत में वर्ग और नीति। इस पद्धति में, नाम हमेशा ?
के साथ समाप्त होते हैं वर्ण (उदा.,UsersPolicy#allowed?
)।
यहाँ कुछ उदाहरण कोड है:
class UsersPolicy
def initialize(user)
@user = user
end
def allowed?
admin? || editor?
end
def editor?
@user.where(editor: true)
end
def admin?
@user.where(admin: true)
end
end
किस परिदृश्यों में मुझे उनका उपयोग करना चाहिए?
जब आपके ऐप में एक से अधिक प्रकार की प्रतिबंधित पहुंच और प्रतिबंधित कार्रवाइयां हों। उदाहरण के लिए, पोस्ट निम्न के साथ बनाई जा सकती हैं:
- कम से कम एक टैग,
- एक प्रतिबंध जो केवल व्यवस्थापक और संपादक ही बना सकते हैं, और
- एक आवश्यकता जिसे संपादकों को सत्यापित करने की आवश्यकता है।
नीति वस्तु के बिना एक उदाहरण नियंत्रक यहां दिया गया है:
class PostsController < ApplicationController
def create
if @post.tag_ids.size > 0
&& (current_user.role == ‘admin’
|| (current_user.role == ‘editor’ && current_user.verified_email))
# create
end
end
end
चूंकि उपरोक्त स्थिति जांच लंबी, बदसूरत और अपठनीय हैं, इसलिए पॉलिसी ऑब्जेक्ट पैटर्न लागू किया जाना चाहिए।
आइए PostsCreationPolicy
creating बनाकर शुरू करते हैं ।
class PostsCreationPolicy
attr_reader :user, :post
def initialize(user, post)
@user = user
@post = post
end
def self.create?(user, post)
new(user, post).create?
end
def create?
with_tags? && author_is_allowed?
end
private
def with_tags?
post.tag_ids.size > 0
end
def author_is_allowed?
is_admin? || editor_is_verified?
end
def is_admin?
user.role == ‘admin’
end
def editor_is_verified?
user.role == ‘editor` && user.verified_email
end
end
नीति वस्तु के साथ हमारा नियंत्रक इस तरह दिखता है:
class PostsController < ApplicationController
def create
if PostsCreationPolicy.create?(current_user, @post)
# create
end
end
end
रेल में नीति ऑब्जेक्ट का उपयोग कैसे करें
ऐप के अंदर एक नीति निर्देशिका बनाएं /policies
और अपनी सभी नीति वर्गों को वहां रखें। जब आपको नियंत्रक को कॉल करने की आवश्यकता हो, तो आप सीधे किसी क्रिया में ऐसा कर सकते हैं या before_action
का उपयोग कर सकते हैं :
class PostsController < ApplicationController
before_action :authorized?, only: [:edit, :create, :update, :destroy]
def authorized?
unless ::PostsCreationPolicy.create?(current_user, @post)
render :file => "public/404.html", :status => :unauthorized
end
end
end
नीति वस्तुओं का परीक्षण कैसे करें
नियंत्रक में व्यवहार का परीक्षण करना आसान है:
require 'rails_helper'
RSpec.describe "/posts", type: :request do
describe "when user is not allowed" do
let(:user_not_allowed) { create(:user, admin: false, editor: false) }
let(:tag) { create(:tag) }
let(:valid_attributes) { attributes_for(:post, tag_id: tag.id) }
before do
sign_in user_not_allowed
end
describe "GET /index" do
it "return code 401" do
diet = Post.create! valid_attributes
get edit_post_url(post)
expect(response).to have_http_status(401)
end
end
end
end
नीति का परीक्षण करना भी सरल है; हमारे पास केवल एक जिम्मेदारी के साथ बहुत सी छोटी विधियां हैं।
require 'rails_helper'
RSpec.describe PostsCreationPolicy do
describe "when user is not allowed" do
let(:user) { create(:user, editor: false, admin: false) }
let(:user_editor) { create(:user, editor: true, email: verified) }
let(:tag) { create(:tag) }
let(:post) { create(:post, tag_id: tag.id) }
describe ".create?" do
context "when user is allowed" do
it "creates a new post" do
expect(described_class.create?(user_editor, post)).to eq(true)
end
end
context "when user is not allowed" do
it "does not create a new post" do
expected(described_class.create?(user, post)).to eq(false)
end
end
end
# ...more test cases
end
end
हम परीक्षण करते हैं कि ऑब्जेक्ट को हर परिदृश्य में बनाने की अनुमति है या नहीं।
निष्कर्ष
नीति पैटर्न की अवधारणा छोटी है लेकिन बड़े परिणाम देती है। हर बार जब आपको सरल या जटिल अनुमतियों से निपटना हो तो नीति वस्तु को लागू करने पर विचार करें। जब आरएसपीसी के साथ परीक्षण की बात आती है, तो आपको डेटाबेस रिकॉर्ड का उपयोग करने की आवश्यकता नहीं होती है; आपकी नीतियां विशुद्ध रूप से रूबी ऑब्जेक्ट हैं, और आपका परीक्षण सरल और तेज़ होगा।