Bouncer เป็นแนวทางที่หรูหราและไม่เชื่อเรื่องกรอบงานในการจัดการบทบาทและความสามารถของแอปใดๆ ก็ตามที่ใช้โมเดล Eloquent
bouncer:clean
Bouncer เป็นแนวทางที่หรูหราและไม่เชื่อเรื่องกรอบงานในการจัดการบทบาทและความสามารถของแอปใดๆ ก็ตามที่ใช้โมเดล Eloquent ด้วยไวยากรณ์ที่ชัดเจนและคล่องแคล่ว มันจะไม่เกะกะคุณมากที่สุดเท่าที่จะเป็นไปได้: ใช้เมื่อคุณต้องการ เพิกเฉยเมื่อคุณไม่ต้องการ
หากต้องการดูรายการฟีเจอร์ของ Bouncer อย่างรวดเร็วและเข้าใจง่าย โปรดดูเอกสารสรุป
Bouncer ทำงานได้ดีกับความสามารถอื่นๆ ที่คุณฮาร์ดโค้ดในแอปของคุณเอง รหัสของคุณมีความสำคัญกว่าเสมอ: หากรหัสของคุณอนุญาตให้ดำเนินการได้ Bouncer จะไม่รบกวน
เมื่อติดตั้งแล้ว คุณสามารถบอกคนโกหกว่าคุณต้องการอนุญาตอะไรบ้างที่ประตู:
// Give a user the ability to create posts
Bouncer:: allow ( $ user )-> to ( ' create ' , Post::class);
// Alternatively, do it through a role
Bouncer:: allow ( ' admin ' )-> to ( ' create ' , Post::class);
Bouncer:: assign ( ' admin ' )-> to ( $ user );
// You can also grant an ability only to a specific model
Bouncer:: allow ( $ user )-> to ( ' edit ' , $ post );
เมื่อคุณตรวจสอบความสามารถที่ประตูของ Laravel Bouncer จะถูกปรึกษาโดยอัตโนมัติ หาก Bouncer เห็นความสามารถที่มอบให้กับผู้ใช้ปัจจุบัน (ไม่ว่าจะโดยตรงหรือผ่านบทบาท) ก็จะอนุญาตการตรวจสอบ
หมายเหตุ : Bouncer v1.0.2 ต้องใช้ PHP 8.2+ และ Laravel/Eloquent 11+
หากคุณใช้ Laravel v6-v10 ให้ใช้ Bouncer v1.0.1 หากคุณใช้ Laravel v5.5-v5.8 ให้ใช้ Bouncer RC6
ติดตั้ง Bouncer พร้อมผู้แต่ง:
composer require silber/bouncer
เพิ่มคุณลักษณะของ Bouncer ให้กับโมเดลผู้ใช้ของคุณ:
use Silber Bouncer Database HasRolesAndAbilities ;
class User extends Model
{
use HasRolesAndAbilities;
}
ตอนนี้ เพื่อดำเนินการย้ายข้อมูลของ Bouncer ขั้นแรกให้เผยแพร่การย้ายข้อมูลลงในไดเร็กทอรี migrations
ของแอปของคุณ โดยเรียกใช้คำสั่งต่อไปนี้:
php artisan vendor:publish --tag="bouncer.migrations"
สุดท้าย ให้ดำเนินการย้ายข้อมูล:
php artisan migrate
เมื่อใดก็ตามที่คุณใช้ส่วนหน้าของ Bouncer
ในโค้ดของคุณ อย่าลืมเพิ่มบรรทัดนี้ในการนำเข้าเนมสเปซของคุณที่ด้านบนของไฟล์:
use Bouncer ;
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Laravel Facades โปรดดูเอกสารประกอบของ Laravel
ติดตั้ง Bouncer พร้อมผู้แต่ง:
composer require silber/bouncer
ตั้งค่าฐานข้อมูลด้วยส่วนประกอบ Eloquent Capsule:
use Illuminate Database Capsule Manager as Capsule ;
$ capsule = new Capsule ;
$ capsule -> addConnection ([ /* connection config */ ]);
$ capsule -> setAsGlobal ();
โปรดดูเอกสารประกอบของ Eloquent Capsule สำหรับรายละเอียดเพิ่มเติม
เรียกใช้การย้ายข้อมูลด้วยวิธีใดวิธีหนึ่งต่อไปนี้:
ใช้เครื่องมือเช่น vagabond เพื่อเรียกใช้การย้ายข้อมูล Laravel นอกแอป Laravel คุณจะพบการย้ายข้อมูลที่จำเป็นในไฟล์ stub การย้ายข้อมูล
หรือคุณสามารถเรียกใช้ SQL แบบดิบได้โดยตรงในฐานข้อมูลของคุณ
เพิ่มคุณลักษณะของ Bouncer ให้กับโมเดลผู้ใช้ของคุณ:
use Illuminate Database Eloquent Model ;
use Silber Bouncer Database HasRolesAndAbilities ;
class User extends Model
{
use HasRolesAndAbilities;
}
สร้างตัวอย่างของ Bouncer:
use Silber Bouncer Bouncer ;
$ bouncer = Bouncer:: create ();
// If you are in a request with a current user
// that you'd wish to check permissions for,
// pass that user to the "create" method:
$ bouncer = Bouncer:: create ( $ user );
หากคุณใช้ Dependency Inject ในแอปของคุณ คุณสามารถลงทะเบียน Bouncer
instance เป็นซิงเกิลตันในคอนเทนเนอร์ได้:
use Silber Bouncer Bouncer ;
use Illuminate Container Container ;
Container:: getInstance ()-> singleton (Bouncer::class, function () {
return Bouncer:: create ();
});
ตอนนี้คุณสามารถส่ง Bouncer
เข้าไปในคลาสใดก็ได้ที่ต้องการ
วิธี create
จะสร้างอินสแตนซ์ Bouncer
ด้วยค่าเริ่มต้นที่สมเหตุสมผล หากต้องการปรับแต่งอย่างเต็มที่ ให้ใช้เมธอด make
เพื่อรับอินสแตนซ์จากโรงงาน เรียก create()
บนโรงงานเพื่อสร้างอินสแตนซ์ Bouncer
:
use Silber Bouncer Bouncer ;
$ bouncer = Bouncer:: make ()
-> withCache ( $ customCacheInstance )
-> create ();
ตรวจสอบคลาส Factory
เพื่อดูการปรับแต่งทั้งหมดที่มี
กำหนดว่าจะใช้โมเดลใดเป็นโมเดลผู้ใช้ทั่วทั้งแอปของคุณ:
$ bouncer -> useUserModel (User::class);
สำหรับการกำหนดค่าเพิ่มเติม โปรดดูส่วนการกำหนดค่าด้านล่าง
ตามค่าเริ่มต้น ข้อความค้นหาของ Bouncer จะถูกแคชไว้สำหรับคำขอปัจจุบัน เพื่อประสิทธิภาพที่ดีขึ้น คุณอาจต้องการเปิดใช้งานการแคชคำขอข้าม
การเพิ่มบทบาทและความสามารถให้กับผู้ใช้นั้นทำได้ง่ายมาก คุณไม่จำเป็นต้องสร้างบทบาทหรือความสามารถล่วงหน้า เพียงส่งชื่อของบทบาท/ความสามารถ แล้ว Bouncer จะสร้างมันขึ้นมาหากไม่มีอยู่
หมายเหตุ: ตัวอย่างด้านล่างทั้งหมดใช้ส่วนหน้าของ
Bouncer
หากคุณไม่ใช้ส่วนหน้า คุณสามารถแทรกSilberBouncerBouncer
เข้าไปในชั้นเรียนของคุณได้แทน
มาสร้างบทบาทที่เรียกว่า admin
และให้ความสามารถในการ ban-users
จากเว็บไซต์ของเรา:
Bouncer:: allow ( ' admin ' )-> to ( ' ban-users ' );
แค่นั้นแหละ. เบื้องหลัง Bouncer จะสร้างทั้ง Role
และแบบ Ability
ให้กับคุณ
หากคุณต้องการเพิ่มคุณลักษณะเพิ่มเติมให้กับบทบาท/ความสามารถ เช่น ชื่อที่มนุษย์สามารถอ่านได้ คุณสามารถสร้างได้ด้วยตนเองโดยใช้วิธี role
และ ability
ในคลาส Bouncer
:
$ admin = Bouncer:: role ()-> firstOrCreate ([
' name ' => ' admin ' ,
' title ' => ' Administrator ' ,
]);
$ ban = Bouncer:: ability ()-> firstOrCreate ([
' name ' => ' ban-users ' ,
' title ' => ' Ban users ' ,
]);
Bouncer:: allow ( $ admin )-> to ( $ ban );
หากต้องการมอบบทบาท admin
ให้กับผู้ใช้ในตอนนี้ เพียงบอกผู้โกหกว่าผู้ใช้ที่ได้รับควรได้รับมอบหมายบทบาทผู้ดูแลระบบ:
Bouncer:: assign ( ' admin ' )-> to ( $ user );
หรือคุณสามารถเรียกวิธี assign
โดยตรงกับผู้ใช้:
$ user -> assign ( ' admin ' );
บางครั้งคุณอาจต้องการให้ความสามารถแก่ผู้ใช้โดยตรง โดยไม่ต้องใช้บทบาท:
Bouncer:: allow ( $ user )-> to ( ' ban-users ' );
ที่นี่คุณก็สามารถทำสิ่งเดียวกันนี้ให้สำเร็จได้โดยตรงจากผู้ใช้:
$ user -> allow ( ' ban-users ' );
บางครั้งคุณอาจต้องการจำกัดความสามารถให้กับประเภทโมเดลเฉพาะ เพียงส่งชื่อรุ่นเป็นอาร์กิวเมนต์ที่สอง:
Bouncer:: allow ( $ user )-> to ( ' edit ' , Post::class);
หากคุณต้องการจำกัดความสามารถให้กับอินสแตนซ์โมเดลเฉพาะ ให้ส่งโมเดลจริงแทน:
Bouncer:: allow ( $ user )-> to ( ' edit ' , $ post );
ใช้เมธอด toOwn
เพื่อให้ผู้ใช้สามารถจัดการโมเดล ของตนเอง ได้:
Bouncer:: allow ( $ user )-> toOwn (Post::class);
ตอนนี้ เมื่อตรวจสอบที่ประตูว่าผู้ใช้สามารถดำเนินการกับโพสต์ที่กำหนดได้หรือไม่ user_id
ของโพสต์จะถูกเปรียบเทียบกับ id
ของผู้ใช้ที่เข้าสู่ระบบ (ซึ่งสามารถปรับแต่งได้) หากตรงกัน ประตูจะอนุญาตให้ดำเนินการได้
ข้อมูลข้างต้นจะมอบความสามารถทั้งหมดให้กับโมเดลที่ "เป็นเจ้าของ" ของผู้ใช้ คุณสามารถจำกัดความสามารถได้โดยทำตามด้วยการเรียกไปยังเมธอด to
:
Bouncer:: allow ( $ user )-> toOwn (Post::class)-> to ( ' view ' );
// Or pass it an array of abilities:
Bouncer:: allow ( $ user )-> toOwn (Post::class)-> to ([ ' view ' , ' update ' ]);
คุณยังสามารถอนุญาตให้ผู้ใช้เป็นเจ้าของโมเดลทุก ประเภท ในแอปพลิเคชันของคุณ:
Bouncer:: allow ( $ user )-> toOwnEverything ();
// And to restrict ownership to a given ability
Bouncer:: allow ( $ user )-> toOwnEverything ()-> to ( ' view ' );
นักเลงยังสามารถเพิกถอนบทบาทที่ได้รับมอบหมายก่อนหน้านี้จากผู้ใช้ได้:
Bouncer:: retract ( ' admin ' )-> from ( $ user );
หรือทำโดยตรงกับผู้ใช้:
$ user -> retract ( ' admin ' );
นักเลงยังสามารถลบความสามารถที่เคยมอบให้กับผู้ใช้ก่อนหน้านี้ได้:
Bouncer:: disallow ( $ user )-> to ( ' ban-users ' );
หรือโดยตรงกับผู้ใช้:
$ user -> disallow ( ' ban-users ' );
หมายเหตุ: หากผู้ใช้มีบทบาทที่อนุญาตให้
ban-users
พวกเขาจะยังคงมีความสามารถนั้นอยู่ หากต้องการยกเลิกการอนุญาต ให้ลบความสามารถออกจากบทบาทหรือถอนบทบาทออกจากผู้ใช้
หากความสามารถได้รับการมอบให้ผ่านบทบาท ให้บอกคนโกหกให้ถอดความสามารถออกจากบทบาทแทน:
Bouncer:: disallow ( ' admin ' )-> to ( ' ban-users ' );
หากต้องการลบความสามารถสำหรับประเภทโมเดลเฉพาะ ให้ส่งชื่อเป็นอาร์กิวเมนต์ที่สอง:
Bouncer:: disallow ( $ user )-> to ( ' delete ' , Post::class);
คำเตือน: หากผู้ใช้สามารถ
delete
สแตนซ์$post
เฉพาะได้ โค้ดด้านบนจะ ไม่ ลบความสามารถนั้น คุณจะต้องลบความสามารถแยกกัน - โดยส่ง$post
จริงเป็นอาร์กิวเมนต์ที่สอง - ดังที่แสดงด้านล่าง
หากต้องการลบความสามารถสำหรับอินสแตนซ์โมเดลเฉพาะ ให้ส่งโมเดลจริงแทน:
Bouncer:: disallow ( $ user )-> to ( ' delete ' , $ post );
หมายเหตุ : วิธี
disallow
จะลบเฉพาะความสามารถที่มอบให้กับผู้ใช้/บทบาทนี้ก่อนหน้านี้เท่านั้น หากคุณต้องการไม่อนุญาตชุดย่อยของสิ่งที่ความสามารถทั่วไปอนุญาต ให้ใช้วิธีforbid
Bouncer ยังช่วยให้คุณสามารถ forbid
ความสามารถที่กำหนดได้ เพื่อการควบคุมที่ละเอียดยิ่งขึ้น ในบางครั้งคุณอาจต้องการให้ผู้ใช้/บทบาทมีความสามารถที่ครอบคลุมการกระทำต่างๆ มากมาย แต่จะจำกัดการกระทำเหล่านั้นเพียงบางส่วนเท่านั้น
นี่คือตัวอย่างบางส่วน:
คุณอาจอนุญาตให้ผู้ใช้ดูเอกสารทั้งหมดโดยทั่วไป แต่มีเอกสารเฉพาะที่มีการจัดประเภทสูงซึ่งไม่ควรได้รับอนุญาตให้ดู:
Bouncer:: allow ( $ user )-> to ( ' view ' , Document::class);
Bouncer:: forbid ( $ user )-> to ( ' view ' , $ classifiedDocument );
คุณอาจต้องการอนุญาตให้ superadmin
ทำทุกอย่างในแอปของคุณ รวมถึงการเพิ่ม/ลบผู้ใช้ จากนั้น คุณอาจมีบทบาท admin
ที่สามารถทำทุกอย่าง นอกเหนือจาก การจัดการผู้ใช้:
Bouncer:: allow ( ' superadmin ' )-> everything ();
Bouncer:: allow ( ' admin ' )-> everything ();
Bouncer:: forbid ( ' admin ' )-> toManage (User::class);
คุณอาจต้องการแบนผู้ใช้เป็นครั้งคราว โดยยกเลิกการอนุญาตความสามารถทั้งหมดของพวกเขา อย่างไรก็ตาม การลบบทบาทและความสามารถทั้งหมดออกไปจริงๆ หมายความว่าเมื่อยกเลิกการแบนแล้ว เราจะต้องค้นหาว่าบทบาทและความสามารถเดิมของพวกเขาคืออะไร
การใช้ความสามารถต้องห้ามหมายความว่าพวกเขาสามารถรักษาบทบาทและความสามารถที่มีอยู่ทั้งหมดไว้ได้ แต่ก็ยังไม่ได้รับอนุญาตสำหรับสิ่งใดๆ เราสามารถทำได้โดยการสร้างบทบาทพิเศษ banned
ซึ่งเราจะห้ามทุกอย่าง:
Bouncer:: forbid ( ' banned ' )-> everything ();
จากนั้น เมื่อใดก็ตามที่เราต้องการแบนผู้ใช้ เราจะกำหนดบทบาท banned
ให้กับพวกเขา:
Bouncer:: assign ( ' banned ' )-> to ( $ user );
หากต้องการยกเลิกการแบน เราจะถอนบทบาทออกจากผู้ใช้:
Bouncer:: retract ( ' banned ' )-> from ( $ user );
อย่างที่คุณเห็น ความสามารถต้องห้ามของ Bouncer ช่วยให้คุณควบคุมการอนุญาตในแอปของคุณได้อย่างละเอียด
หากต้องการลบความสามารถต้องห้าม ให้ใช้วิธีการ unforbid
:
Bouncer:: unforbid ( $ user )-> to ( ' view ' , $ classifiedDocument );
หมายเหตุ : การดำเนินการนี้จะลบความสามารถใดๆ ที่ถูกห้ามไว้ก่อนหน้านี้ มันจะ ไม่ อนุญาตให้ความสามารถโดยอัตโนมัติ หากไม่ได้รับอนุญาตจากความสามารถปกติอื่นที่มอบให้กับผู้ใช้/บทบาทนี้
หมายเหตุ : โดยทั่วไปแล้ว คุณไม่จำเป็นต้องตรวจสอบบทบาทโดยตรง เป็นการดีกว่าที่จะอนุญาตให้มีบทบาทบางอย่าง จากนั้นตรวจสอบความสามารถเหล่านั้นแทน หากสิ่งที่คุณต้องการเป็นเรื่องทั่วไป คุณสามารถสร้างความสามารถที่กว้างมากได้ ตัวอย่างเช่น ความสามารถ
access-dashboard
จะดีกว่าการตรวจสอบบทบาทadmin
หรือeditor
โดยตรงเสมอ สำหรับโอกาสที่เกิดขึ้นไม่บ่อยนักที่คุณต้องการตรวจสอบบทบาท ฟังก์ชันดังกล่าวมีให้ที่นี่
นักเลงสามารถตรวจสอบได้ว่าผู้ใช้มีบทบาทเฉพาะหรือไม่:
Bouncer:: is ( $ user )-> a ( ' moderator ' );
หากบทบาทที่คุณกำลังตรวจสอบเริ่มต้นด้วยสระ คุณอาจต้องการใช้เมธอด an
:
Bouncer:: is ( $ user )-> an ( ' admin ' );
ในทางกลับกัน คุณยังสามารถตรวจสอบได้ว่าผู้ใช้ ไม่มี บทบาทเฉพาะหรือไม่:
Bouncer:: is ( $ user )-> notA ( ' moderator ' );
Bouncer:: is ( $ user )-> notAn ( ' admin ' );
คุณสามารถตรวจสอบว่าผู้ใช้มีบทบาทอย่างใดอย่างหนึ่งหรือไม่:
Bouncer:: is ( $ user )-> a ( ' moderator ' , ' editor ' );
คุณยังสามารถตรวจสอบได้ว่าผู้ใช้มีบทบาทที่กำหนดทั้งหมดหรือไม่:
Bouncer:: is ( $ user )-> all ( ' editor ' , ' moderator ' );
คุณยังสามารถตรวจสอบได้ว่าผู้ใช้ไม่มีบทบาทที่กำหนดหรือไม่:
Bouncer:: is ( $ user )-> notAn ( ' editor ' , ' moderator ' );
การตรวจสอบเหล่านี้สามารถทำได้โดยตรงกับผู้ใช้:
$ user -> isAn ( ' admin ' );
$ user -> isA ( ' subscriber ' );
$ user -> isNotAn ( ' admin ' );
$ user -> isNotA ( ' subscriber ' );
$ user -> isAll ( ' editor ' , ' moderator ' );
คุณสามารถสอบถามผู้ใช้ของคุณว่าพวกเขามีบทบาทที่กำหนดหรือไม่:
$ users = User:: whereIs ( ' admin ' )-> get ();
คุณยังอาจส่งผ่านหลายบทบาท เพื่อค้นหาผู้ใช้ที่มีบทบาท ใด ๆ ที่กำหนด:
$ users = User:: whereIs ( ' superadmin ' , ' admin ' )-> get ();
หากต้องการค้นหาผู้ใช้ที่มีบทบาทที่กำหนด ทั้งหมด ให้ใช้เมธอด whereIsAll
:
$ users = User:: whereIsAll ( ' sales ' , ' marketing ' )-> get ();
คุณสามารถรับบทบาททั้งหมดสำหรับผู้ใช้ได้โดยตรงจากโมเดลผู้ใช้:
$ roles = $ user -> getRoles ();
คุณสามารถรับความสามารถทั้งหมดสำหรับผู้ใช้ได้โดยตรงจากรุ่นผู้ใช้:
$ abilities = $ user -> getAbilities ();
ซึ่งจะส่งคืนคอลเลกชันความสามารถที่ผู้ใช้อนุญาต รวมถึงความสามารถใดๆ ที่มอบให้แก่ผู้ใช้ผ่านบทบาทของพวกเขา
คุณยังสามารถรับรายการความสามารถที่ถูกห้าม อย่างชัดเจน :
$ forbiddenAbilities = $ user -> getForbiddenAbilities ();
การอนุญาตผู้ใช้ได้รับการจัดการโดยตรงที่ Laravel's Gate
หรือบนรุ่นผู้ใช้ ( $user->can($ability)
)
เพื่อความสะดวก คลาส Bouncer
มีวิธีการส่งผ่านเหล่านี้:
Bouncer:: can ( $ ability );
Bouncer:: can ( $ ability , $ model );
Bouncer:: canAny ( $ abilities );
Bouncer:: canAny ( $ abilities , $ model );
Bouncer:: cannot ( $ ability );
Bouncer:: cannot ( $ ability , $ model );
Bouncer:: authorize ( $ ability );
Bouncer:: authorize ( $ ability , $ model );
สิ่งเหล่านี้เรียกโดยตรงไปยังวิธีการที่เทียบเท่าในคลาส Gate
Bouncer ไม่ได้เพิ่มคำสั่งเบลดของตัวเอง เนื่องจาก Bouncer ทำงานโดยตรงกับเกตของ Laravel เพียงใช้คำสั่ง @can
เพื่อตรวจสอบความสามารถของผู้ใช้ปัจจุบัน:
@can ('update', $post)
< a href =" {{ route('post.update', $post) }} " > Edit Post </ a >
@endcan
เนื่องจากโดยทั่วไปแล้วไม่แนะนำให้ตรวจสอบบทบาทโดยตรง Bouncer จึงไม่จัดส่งคำสั่งแยกต่างหากสำหรับสิ่งนั้น หากคุณยังคงยืนกรานที่จะตรวจสอบบทบาท คุณสามารถทำได้โดยใช้คำสั่ง @if
ทั่วไป:
@ if ( $ user -> isAn ( ' admin ' ))
//
@endif
แบบสอบถามทั้งหมดที่ดำเนินการโดย Bouncer จะถูกแคชไว้สำหรับคำขอปัจจุบัน หากคุณเปิดใช้งานการแคชคำขอข้าม แคชจะยังคงอยู่ในคำขอที่แตกต่างกัน
เมื่อใดก็ตามที่คุณต้องการ คุณสามารถรีเฟรชแคชของคนโกหกได้อย่างเต็มที่:
Bouncer:: refresh ();
หมายเหตุ: การรีเฟรชแคชโดยสมบูรณ์สำหรับผู้ใช้ทุกคนจะใช้แท็กแคช หากมี ไดรเวอร์แคชบางตัวไม่รองรับสิ่งนี้ โปรดดูเอกสารประกอบของ Laravel เพื่อดูว่าไดรเวอร์ของคุณรองรับแท็กแคชหรือไม่ หากไดรเวอร์ของคุณไม่รองรับแท็กแคช การเรียก
refresh
อาจช้าเล็กน้อย ขึ้นอยู่กับจำนวนผู้ใช้ในระบบของคุณ
หรือคุณสามารถรีเฟรชแคชสำหรับผู้ใช้ที่ระบุเท่านั้น:
Bouncer:: refreshFor ( $ user );
หมายเหตุ : เมื่อใช้ขอบเขตแบบหลายผู้เช่า สิ่งนี้จะรีเฟรชแคชสำหรับผู้ใช้ในบริบทของขอบเขตปัจจุบันเท่านั้น หากต้องการล้างข้อมูลแคชสำหรับผู้ใช้รายเดียวกันในบริบทขอบเขตอื่น จะต้องเรียกข้อมูลจากภายในขอบเขตนั้น
Bouncer รองรับแอปที่มีผู้เช่าหลายรายอย่างสมบูรณ์ ช่วยให้คุณสามารถรวมบทบาทและความสามารถของ Bouncer สำหรับผู้เช่าทั้งหมดภายในแอปเดียวกันได้อย่างราบรื่น
ในการเริ่มต้น ให้เผยแพร่มิดเดิลแวร์ขอบเขตลงในแอปของคุณก่อน:
php artisan vendor:publish --tag="bouncer.middleware"
มิดเดิลแวร์จะถูกเผยแพร่ไปยัง app/Http/Middleware/ScopeBouncer.php
มิดเดิลแวร์นี้เป็นที่ที่คุณบอก Bouncer ว่าผู้เช่ารายใดที่จะใช้สำหรับคำขอปัจจุบัน ตัวอย่างเช่น สมมติว่าผู้ใช้ของคุณทั้งหมดมีแอตทริบิวต์ account_id
มิดเดิลแวร์ของคุณจะมีลักษณะดังนี้:
public function handle ( $ request , Closure $ next )
{
$ tenantId = $ request -> user ()-> account_id ;
Bouncer:: scope ()-> to ( $ tenantId );
return $ next ( $ request );
}
คุณมีอิสระที่จะปรับเปลี่ยนมิดเดิลแวร์นี้ให้เหมาะกับความต้องการของแอปของคุณ เช่น การดึงข้อมูลผู้เช่าจากโดเมนย่อยและคณะ
ขณะนี้มีมิดเดิลแวร์แล้ว อย่าลืมลงทะเบียนไว้ในเคอร์เนล HTTP ของคุณ:
protected $ middlewareGroups = [
' web ' => [
// Keep the existing middleware here, and add this:
App Http Middleware ScopeBouncer::class,
]
];
ข้อความค้นหาทั้งหมดของ Bouncer จะถูกกำหนดขอบเขตไปยังผู้เช่าที่กำหนด
ขึ้นอยู่กับการตั้งค่าแอปของคุณ คุณอาจไม่ต้องการให้การสืบค้น ทั้งหมด ถูกกำหนดขอบเขตไปยังผู้เช่าปัจจุบัน ตัวอย่างเช่น คุณอาจมีชุดบทบาท/ความสามารถคงที่ซึ่งเหมือนกันสำหรับผู้เช่าทั้งหมด และอนุญาตให้ผู้ใช้ของคุณควบคุมได้ว่าผู้ใช้รายใดจะได้รับมอบหมายบทบาทใด และบทบาทใดมีความสามารถใดบ้าง เพื่อให้บรรลุเป้าหมายนี้ คุณสามารถบอกขอบเขตของ Bouncer ให้กำหนดขอบเขตความสัมพันธ์ระหว่างโมเดลของ Bouncer เท่านั้น แต่ไม่ใช่ตัวโมเดลเอง:
Bouncer:: scope ()-> to ( $ tenantId )-> onlyRelations ();
นอกจากนี้ แอปของคุณอาจไม่อนุญาตให้ผู้ใช้ควบคุมความสามารถที่มีบทบาทที่กำหนดด้วยซ้ำ ในกรณีดังกล่าว ให้แจ้งขอบเขตของ Bouncer ให้แยกความสามารถตามบทบาทออกจากขอบเขต เพื่อให้ความสัมพันธ์เหล่านั้นคงอยู่ทั่วโลกสำหรับผู้เช่าทั้งหมด:
Bouncer:: scope ()-> to ( $ tenantId )-> onlyRelations ()-> dontScopeRoleAbilities ();
หากความต้องการของคุณมีความเฉพาะเจาะจงมากกว่าที่อธิบายไว้ข้างต้น คุณสามารถสร้าง Scope
ของคุณเองโดยใช้ตรรกะแบบกำหนดเองใดก็ได้ที่คุณต้องการ:
use Silber Bouncer Contracts Scope ;
class MyScope implements Scope
{
// Whatever custom logic your app needs
}
จากนั้นในผู้ให้บริการ ให้ลงทะเบียนขอบเขตที่คุณกำหนดเอง:
Bouncer:: scope ( new MyScope );
Bouncer จะเรียกใช้เมธอดบนอินเทอร์ Scope
ที่จุดต่างๆ ในการดำเนินการ คุณมีอิสระในการจัดการตามความต้องการเฉพาะของคุณ
Bouncer มาพร้อมกับค่าเริ่มต้นที่สมเหตุสมผล ดังนั้นโดยส่วนใหญ่จึงไม่จำเป็นต้องมีการกำหนดค่าใดๆ สำหรับการควบคุมที่ละเอียดยิ่งขึ้น Bouncer สามารถปรับแต่งได้โดยการเรียกวิธีการกำหนดค่าต่างๆ ในคลาส Bouncer
หากคุณใช้ตัวเลือกการกำหนดค่าเหล่านี้เพียงหนึ่งหรือสองตัวเลือก คุณสามารถรวมตัวเลือกเหล่านั้นไว้ในวิธี boot
ของ AppServiceProvider
หลักของคุณได้ หากคลาสเริ่มเติบโต คุณสามารถสร้างคลาส BouncerServiceProvider
แยกต่างหากในไดเรกทอรี app/Providers
ของคุณ (อย่าลืมลงทะเบียนในอาร์เรย์การกำหนดค่า providers
)
ตามค่าเริ่มต้น ข้อความค้นหาทั้งหมดที่ดำเนินการโดย Bouncer จะถูกแคชไว้สำหรับคำขอปัจจุบัน เพื่อประสิทธิภาพที่ดีขึ้น คุณอาจต้องการใช้การแคชคำขอข้าม:
Bouncer:: cache ();
คำเตือน: หากคุณเปิดใช้งานการแคชคำขอข้าม คุณต้องรับผิดชอบในการรีเฟรชแคชทุกครั้งที่คุณทำการเปลี่ยนแปลงบทบาท/ความสามารถของผู้ใช้ สำหรับวิธีรีเฟรชแคช โปรดอ่านการรีเฟรชแคช
ในทางกลับกัน คุณอาจต้องการ ปิดการใช้งานแคชโดยสมบูรณ์ ในบางครั้ง แม้ว่าจะอยู่ในคำขอเดียวกันก็ตาม:
Bouncer:: dontCache ();
สิ่งนี้มีประโยชน์อย่างยิ่งในการทดสอบหน่วย เมื่อคุณต้องการดำเนินการยืนยันบทบาท/ความสามารถที่เพิ่งได้รับมอบหมาย
หากต้องการเปลี่ยนชื่อตารางฐานข้อมูลที่ Bouncer ใช้ ให้ส่งอาร์เรย์ที่เชื่อมโยงไปยังเมธอดของ tables
คีย์ควรเป็นชื่อตารางเริ่มต้นของ Bouncer และค่าควรเป็นชื่อตารางที่คุณต้องการใช้ คุณไม่จำเป็นต้องส่งชื่อตารางทั้งหมด เฉพาะสิ่งที่คุณต้องการเปลี่ยน
Bouncer:: tables ([
' abilities ' => ' my_abilities ' ,
' permissions ' => ' granted_abilities ' ,
]);
การย้ายข้อมูลที่เผยแพร่ของ Bouncer จะใช้ชื่อตารางจากการกำหนดค่านี้ ดังนั้น โปรดเตรียมชื่อตารางเหล่านี้ให้พร้อมก่อนดำเนินการย้ายข้อมูลจริง
คุณสามารถขยายโมเดล Role
และ Ability
ในตัวของ Bouncer ได้อย่างง่ายดาย:
namespace App Models ;
use Silber Bouncer Database Ability as BouncerAbility ;
class Ability extends BouncerAbility
{
// custom code
}
namespace App Models ;
use Silber Bouncer Database Role as BouncerRole ;
class Role extends BouncerRole
{
// custom code
}
หรือคุณสามารถใช้คุณลักษณะ IsAbility
และ IsRole
ของ Bouncer ได้โดยไม่ต้องขยายโมเดลใดๆ ของ Bouncer:
namespace App Models ;
use Illuminate Database Eloquent Model ;
use Silber Bouncer Database Concerns IsAbility ;
class Ability extends Model
{
use IsAbility;
// custom code
}
namespace App Models ;
use Illuminate Database Eloquent Model ;
use Silber Bouncer Database Concerns IsRole ;
class Role extends Model
{
use IsRole;
// custom code
}
หากคุณใช้คุณลักษณะแทนการขยายโมเดลของ Bouncer อย่าลืมตั้งชื่อ $table
และฟิลด์ $fillable
ด้วยตนเอง
ไม่ว่าคุณจะใช้วิธีใด ขั้นตอนต่อไปคือการบอกให้ Bouncer ใช้โมเดลที่คุณกำหนดเอง:
Bouncer:: useAbilityModel ( App Models Ability::class);
Bouncer:: useRoleModel ( App Models Role::class);
หมายเหตุ : Eloquent กำหนดคีย์ต่างประเทศของความสัมพันธ์ตามชื่อรุ่นหลัก (ดูเอกสาร Eloquent) เพื่อให้ทุกอย่างง่ายขึ้น ให้ตั้งชื่อคลาสที่คุณกำหนดเองเหมือนกับ Bouncer's:
Ability
และRole
ตามลำดับหากคุณจำเป็นต้องใช้ชื่ออื่น โปรดอัปเดตไฟล์การย้ายข้อมูลหรือแทนที่วิธีความสัมพันธ์เพื่อตั้งค่าคีย์ต่างประเทศอย่างชัดเจน
ตามค่าเริ่มต้น Bouncer จะใช้โมเดลผู้ใช้ของตัวป้องกันการตรวจสอบเริ่มต้นโดยอัตโนมัติ
หากคุณใช้ Bouncer กับตัวป้องกันที่ไม่ใช่ค่าเริ่มต้น และใช้รุ่นผู้ใช้อื่น คุณควรแจ้งให้ Bouncer ทราบเกี่ยวกับรุ่นผู้ใช้ที่คุณต้องการใช้:
Bouncer:: useUserModel ( App Admin::class);
ใน Bouncer แนวคิดเรื่องการเป็นเจ้าของจะใช้เพื่อให้ผู้ใช้สามารถดำเนินการกับโมเดลที่พวกเขา "เป็นเจ้าของ" ได้
ตามค่าเริ่มต้น Bouncer จะตรวจสอบ user_id
ของโมเดลกับคีย์หลักของผู้ใช้ปัจจุบัน หากจำเป็น คุณสามารถตั้งค่าเป็นแอตทริบิวต์อื่นได้:
Bouncer:: ownedVia ( ' userId ' );
หากโมเดลที่ต่างกันใช้คอลัมน์ในการเป็นเจ้าของที่แตกต่างกัน คุณสามารถลงทะเบียนแยกกันได้:
Bouncer:: ownedVia (Post::class, ' created_by ' );
Bouncer:: ownedVia (Order::class, ' entered_by ' );
เพื่อการควบคุมที่ดียิ่งขึ้น คุณสามารถส่งผ่านการปิดด้วยตรรกะที่คุณกำหนดเองได้:
Bouncer:: ownedVia (Game::class, function ( $ game , $ user ) {
return $ game -> team_id == $ user -> team_id ;
});
มีแนวคิดบางอย่างใน Bouncer ที่ผู้คนมักถามถึง ดังนั้นนี่คือรายการสั้นๆ ของหัวข้อเหล่านั้น:
การกำหนดบทบาทและความสามารถเริ่มต้นสามารถทำได้ในคลาส Seeder ของ Laravel ปกติ เริ่มต้นด้วยการสร้างไฟล์ seeder เฉพาะสำหรับ Bouncer:
php artisan make:seeder BouncerSeeder
วางโค้ดบทบาทและความสามารถการเพาะทั้งหมดของคุณไว้ในวิธี run
ของ seeder นี่คือตัวอย่างสิ่งที่อาจมีลักษณะดังนี้:
use Bouncer ;
use Illuminate Database Seeder ;
class BouncerSeeder extends Seeder
{
public function run ()
{
Bouncer:: allow ( ' superadmin ' )-> everything ();
Bouncer:: allow ( ' admin ' )-> everything ();
Bouncer:: forbid ( ' admin ' )-> toManage (User::class);
Bouncer:: allow ( ' editor ' )-> to ( ' create ' , Post::class);
Bouncer:: allow ( ' editor ' )-> toOwn (Post::class);
// etc.
}
}
หากต้องการรันจริง ให้ส่งชื่อคลาสของ seeder ไปยังตัวเลือก class
ของคำสั่ง db:seed
:
php artisan db:seed --class=BouncerSeeder
scope
ของ Bouncer สามารถใช้เพื่อแบ่งส่วนต่างๆ ของไซต์ออกได้ โดยสร้างไซโลสำหรับแต่ละส่วนด้วยชุดบทบาทและความสามารถของตัวเอง:
สร้างมิดเดิลแวร์ ScopeBouncer
ที่จะรับ $identifier
และตั้งเป็นขอบเขตปัจจุบัน:
use Bouncer , Closure ;
class ScopeBouncer
{
public function handle ( $ request , Closure $ next , $ identifier )
{
Bouncer:: scope ()-> to ( $ identifier );
return $ next ( $ request );
}
}
ลงทะเบียนมิดเดิลแวร์ใหม่นี้เป็นมิดเดิลแวร์เส้นทางในคลาส HTTP Kernel ของคุณ:
protected $ routeMiddleware = [
// Keep the other route middleware, and add this:
' scope-bouncer ' => App Http Middleware ScopeBouncer::class,
];
ในผู้ให้บริการเส้นทางของคุณ ให้ใช้มิดเดิลแวร์นี้กับตัวระบุอื่นสำหรับเส้นทางสาธารณะและเส้นทางแดชบอร์ด ตามลำดับ:
Route:: middleware ([ ' web ' , ' scope-bouncer:1 ' ])
-> namespace ( $ this -> namespace )
-> group ( base_path ( ' routes/public.php ' ));
Route:: middleware ([ ' web ' , ' scope-bouncer:2 ' ])
-> namespace ( $ this -> namespace )
-> group ( base_path ( ' routes/dashboard.php ' ));
แค่นั้นแหละ. ตอนนี้บทบาทและความสามารถทั้งหมดจะถูกกำหนดขอบเขตแยกกันสำหรับแต่ละส่วนของไซต์ของคุณ หากต้องการปรับแต่งขอบเขตของขอบเขต โปรดดูที่ การปรับแต่งขอบเขตของ Bouncer
เริ่มต้นด้วย Laravel 5.4 ชุดอักขระฐานข้อมูลเริ่มต้นคือ utf8mb4
หากคุณใช้ฐานข้อมูลเวอร์ชันเก่า (MySQL ต่ำกว่า 5.7.7 หรือ MariaDB ต่ำกว่า 10.2.2) กับ Laravel 5.4+ คุณจะได้รับข้อผิดพลาด SQL เมื่อพยายามสร้างดัชนีในคอลัมน์สตริง หากต้องการแก้ไขปัญหานี้ ให้เปลี่ยนความยาวสตริงเริ่มต้นของ Laravel ใน AppServiceProvider
ของคุณ :
use Illuminate Support Facades Schema ;
public function boot ()
{
Schema:: defaultStringLength ( 191 );
}
คุณสามารถอ่านเพิ่มเติมได้ในบทความ Laravel News นี้
คอลัมน์ JSON เป็นส่วนเสริมที่ค่อนข้างใหม่สำหรับ MySQL (5.7.8) และ MariaDB (10.2.7) หากคุณใช้ฐานข้อมูลเวอร์ชันเก่า คุณจะใช้คอลัมน์ JSON ไม่ได้
ทางออกที่ดีที่สุดคืออัปเกรดฐานข้อมูลของคุณ หากไม่สามารถทำได้ในขณะนี้ คุณสามารถเปลี่ยนไฟล์การโยกย้ายที่เผยแพร่ไปใช้คอลัมน์ text
แทนได้:
- $table->json('options')->nullable();
+ $table->text('options')->nullable();
bouncer:clean
คำสั่ง bouncer:clean
จะลบความสามารถที่ไม่ได้ใช้ การรันคำสั่งนี้จะลบความสามารถที่ไม่ได้ใช้ 2 ประเภท:
ความสามารถที่ไม่ได้มอบหมาย - ความสามารถที่ไม่ได้มอบหมายให้กับใครเลย ตัวอย่างเช่น:
Bouncer:: allow ( $ user )-> to ( ' view ' , Plan::class);
Bouncer:: disallow ( $ user )-> to ( ' view ' , Plan::class);
ณ จุดนี้ ความสามารถ "ดูแผน" ไม่ได้ถูกกำหนดให้กับใครก็ตาม ดังนั้นจะถูกลบออกไป
หมายเหตุ : คุณอาจไม่ต้องการลบสิ่งเหล่านี้ ทั้งนี้ขึ้นอยู่กับบริบทของแอปของคุณ หากคุณอนุญาตให้ผู้ใช้จัดการความสามารถใน UI ของแอป คุณอาจ ไม่ ต้องการลบความสามารถที่ยังไม่ได้มอบหมาย ดูด้านล่าง
ความสามารถที่ถูกละเลย - ความสามารถของโมเดลที่โมเดลถูกลบไปแล้ว:
Bouncer:: allow ( $ user )-> to ( ' delete ' , $ plan );
$ plan -> delete ();
เนื่องจากแผนไม่มีอยู่แล้ว ความสามารถจึงไม่มีประโยชน์อีกต่อไป ดังนั้นจะถูกลบออก
หากคุณต้องการลบความสามารถที่ไม่ได้ใช้เพียงประเภทเดียว ให้รันด้วยหนึ่งในแฟล็กต่อไปนี้:
php artisan bouncer:clean --unassigned
php artisan bouncer:clean --orphaned
หากคุณไม่ส่งแฟล็กใดๆ ให้กับมัน มันจะลบความสามารถที่ไม่ได้ใช้ทั้งสองประเภท
หากต้องการรันคำสั่งนี้โดยอัตโนมัติเป็นระยะ ให้เพิ่มลงในกำหนดการของเคอร์เนลคอนโซลของคุณ:
$ schedule -> command ( ' bouncer:clean ' )-> weekly ();
// Adding abilities for users
Bouncer:: allow ( $ user )-> to ( ' ban-users ' );
Bouncer:: allow ( $ user )-> to ( ' edit ' , Post::class);
Bouncer:: allow ( $ user )-> to ( ' delete ' , $ post );
Bouncer:: allow ( $ user )-> everything ();
Bouncer:: allow ( $ user )-> toManage (Post::class);
Bouncer:: allow ( $ user )-> toManage ( $ post );
Bouncer:: allow ( $ user )-> to ( ' view ' )-> everything ();
Bouncer:: allow ( $ user )-> toOwn (Post::class);
Bouncer:: allow ( $ user )-> toOwnEverything ();
// Removing abilities uses the same syntax, e.g.
Bouncer:: disallow ( $ user )-> to ( ' delete ' , $ post );
Bouncer:: disallow ( $ user )-> toManage (Post::class);
Bouncer:: disallow ( $ user )-> toOwn (Post::class);
// Adding & removing abilities for roles
Bouncer:: allow ( ' admin ' )-> to ( ' ban-users ' );
Bouncer:: disallow ( ' admin ' )-> to ( ' ban-users ' );
// You can also forbid specific abilities with the same syntax...
Bouncer:: forbid ( $ user )-> to ( ' delete ' , $ post );
// And also remove a forbidden ability with the same syntax...
Bouncer:: unforbid ( $ user )-> to ( ' delete ' , $ post );
// Re-syncing a user's abilities
Bouncer:: sync ( $ user )-> abilities ( $ abilities );
// Assigning & retracting roles from users
Bouncer:: assign ( ' admin ' )-> to ( $ user );
Bouncer:: retract ( ' admin ' )-> from ( $ user );
// Assigning roles to multiple users by ID
Bouncer:: assign ( ' admin ' )-> to ([ 1 , 2 , 3 ]);
// Re-syncing a user's roles
Bouncer:: sync ( $ user )-> roles ( $ roles );
// Checking the current user's abilities
$ boolean = Bouncer:: can ( ' ban-users ' );
$ boolean = Bouncer:: can ( ' edit ' , Post::class);
$ boolean = Bouncer:: can ( ' delete ' , $ post );
$ boolean = Bouncer:: cannot ( ' ban-users ' );
$ boolean = Bouncer:: cannot ( ' edit ' , Post::class);
$ boolean = Bouncer:: cannot ( ' delete ' , $ post );
// Checking a user's roles
$ boolean = Bouncer:: is ( $ user )-> a ( ' subscriber ' );
$ boolean = Bouncer:: is ( $ user )-> an ( ' admin ' );
$ boolean = Bouncer:: is ( $ user )-> notA ( ' subscriber ' );
$ boolean = Bouncer:: is ( $ user )-> notAn ( ' admin ' );
$ boolean = Bouncer:: is ( $ user )-> a ( ' moderator ' , ' editor ' );
$ boolean = Bouncer:: is ( $ user )-> all ( ' moderator ' , ' editor ' );
Bouncer:: cache ();
Bouncer:: dontCache ();
Bouncer:: refresh ();
Bouncer:: refreshFor ( $ user );
ฟังก์ชั่นบางอย่างนี้มีให้ใช้งานโดยตรงบนรุ่นผู้ใช้:
$ user -> allow ( ' ban-users ' );
$ user -> allow ( ' edit ' , Post::class);
$ user -> allow ( ' delete ' , $ post );
$ user -> disallow ( ' ban-users ' );
$ user -> disallow ( ' edit ' , Post::class);
$ user -> disallow ( ' delete ' , $ post );
$ user -> assign ( ' admin ' );
$ user -> retract ( ' admin ' );
$ boolean = $ user -> isAn ( ' admin ' );
$ boolean = $ user -> isAn ( ' editor ' , ' moderator ' );
$ boolean = $ user -> isAll ( ' moderator ' , ' editor ' );
$ boolean = $ user -> isNotAn ( ' admin ' , ' moderator ' );
// Querying users by their roles
$ users = User:: whereIs ( ' superadmin ' )-> get ();
$ users = User:: whereIs ( ' superadmin ' , ' admin ' )-> get ();
$ users = User:: whereIsAll ( ' sales ' , ' marketing ' )-> get ();
$ abilities = $ user -> getAbilities ();
$ forbidden = $ user -> getForbiddenAbilities ();
ในบรรดาแพ็คเกจมูลค่าหลายพันล้านที่ Spatie มอบให้กับชุมชนอย่างสง่างาม คุณจะพบกับแพ็คเกจการอนุญาต laravel ที่ยอดเยี่ยม เช่นเดียวกับ Bouncer มันผสานรวมอย่างดีกับประตูในตัวและการตรวจสอบสิทธิ์ของ Laravel แต่มีตัวเลือกการออกแบบที่แตกต่างกันเมื่อพูดถึงไวยากรณ์ โครงสร้าง DB และคุณสมบัติ
Bouncer เป็นซอฟต์แวร์โอเพ่นซอร์สที่ได้รับอนุญาตภายใต้ใบอนุญาต MIT