สรุป
ควรอนุญาตใน CQRS / DDD ต่อคำสั่ง / แบบสอบถามหรือไม่?
ฉันกำลังพัฒนาเป็นครั้งแรกที่แอปพลิเคชันออนไลน์ที่ใช้รูปแบบ DDD CQRS มากหรือน้อยอย่างเคร่งครัด ฉันเจอปัญหาบางอย่างซึ่งฉันไม่สามารถไปไหนมาไหนได้
แอปพลิเคชันที่ฉันสร้างเป็นแอปพลิเคชันบัญชีแยกประเภทที่อนุญาตให้ผู้ใช้สร้างบัญชีแยกประเภทเช่นเดียวกับการอนุญาตให้บุคคลอื่นดู / แก้ไข / ลบพวกเขาเช่นพนักงาน ผู้สร้างบัญชีแยกประเภทควรสามารถแก้ไขสิทธิ์การเข้าถึงของบัญชีแยกประเภทที่เขาสร้างขึ้น สามารถเปลี่ยนความเป็นเจ้าของได้ โดเมนมีสองมวลTLedgerและTUser
ฉันอ่านบทความจำนวนมากที่มีคำหลัก DDD / CQRS เกี่ยวกับความปลอดภัยการอนุญาต ฯลฯ ส่วนใหญ่ระบุว่าการอนุญาตเป็นGeneric Subdomainเว้นแต่มีใครกำลังสร้างแอปพลิเคชันความปลอดภัย
ในกรณีนี้โดเมนหลักคือโดเมนการบัญชีที่มีความสนใจในการทำธุรกรรมการสร้างสมดุลและการบัญชี แต่ฟังก์ชั่นของความสามารถในการจัดการการเข้าถึงเม็ดเล็กที่ละเอียดไปยังบัญชีแยกประเภทก็จำเป็น ฉันสงสัยว่าจะออกแบบมันอย่างไรในเงื่อนไข DDD / CQRS
มันระบุไว้ในบทเรียน DDD รอบ ๆ สถานที่ที่คำสั่งเป็นส่วนหนึ่งของภาษาที่แพร่หลาย พวกเขามีความหมาย พวกมันเป็นการกระทำที่เป็นรูปธรรมซึ่งเป็นตัวแทนของ
เพราะคำสั่งและแบบสอบถามเหล่านั้นทั้งหมดเป็นการกระทำที่เกิดขึ้นจริงที่ผู้ใช้จะดำเนินการใน "ชีวิตจริง" การดำเนินการอนุญาตควรจะควบคู่ไปกับ "คำสั่ง" และ "แบบสอบถาม" เหล่านี้ทั้งหมด ผู้ใช้จะมีสิทธิ์ในการดำเนินการ TLedger.addTransaction () แต่ไม่ใช่ TLedger.removeTransaction () หรือผู้ใช้จะได้รับอนุญาตให้ดำเนินการค้นหา "getSummaries ()" แต่ไม่ใช่ "getTransactions ()"
การแม็พสามมิติจะมีอยู่ในรูปแบบของ user-ledger-command หรือ user-ledger-query เพื่อกำหนดสิทธิ์การเข้าถึง
หรือในทางแยกคู่กันชื่อ "สิทธิ์" จะถูกลงทะเบียนสำหรับผู้ใช้ สิทธิ์ที่จะถูกแมปสำหรับคำสั่งเฉพาะ ตัวอย่างเช่นการอนุญาต "ManageTransactions" จะอนุญาตให้ผู้ใช้เรียกใช้งาน "AddTransaction ()", "RemoveTransaction ()" เป็นต้น
สิทธิ์การแมปผู้ใช้ -> บัญชีแยกประเภท -> คำสั่ง / แบบสอบถาม
ผู้ใช้การแมปสิทธิ์-> บัญชีแยกประเภท -> สิทธิ์ -> คำสั่ง / แบบสอบถาม
นั่นเป็นส่วนแรกของคำถาม หรือโดยย่อควรอนุญาตใน CQRS / DDD ต่อคำสั่งหรือต่อแบบสอบถาม? หรือควรให้การอนุมัติแยกออกจากคำสั่งหรือไม่
ประการที่สองเกี่ยวกับการอนุญาตตามสิทธิ์ ผู้ใช้ควรสามารถจัดการการอนุญาตบนบัญชีแยกประเภทของเขาหรือบนบัญชีแยกประเภทที่เขาได้รับอนุญาตให้จัดการ
- คำสั่งการจัดการการอนุญาตเกิดขึ้นในบัญชีแยกประเภท
ฉันคิดว่าการเพิ่มเหตุการณ์ / คำสั่ง / ตัวจัดการลงในการรวมบัญชีแยกประเภทเช่น grantPermission (), revokePermission () ฯลฯ ในกรณีนี้การบังคับใช้กฎเหล่านั้นจะเกิดขึ้นในตัวจัดการคำสั่ง แต่สิ่งนี้จะต้องมีคำสั่งทั้งหมดเพื่อรวมรหัสของผู้ใช้ที่ออกคำสั่งนั้น จากนั้นฉันจะตรวจสอบใน TLedger หากมีสิทธิ์สำหรับผู้ใช้นั้นในการดำเนินการคำสั่งนั้น
ตัวอย่างเช่น :
class TLedger{
function addTransactionCmdHandler(cmd){
if (!this.permissions.exist(user, 'addTransaction')
throw new Error('Not Authorized');
}
}
- คำสั่งการจัดการการอนุญาตในผู้ใช้
อีกวิธีคือการรวมการอนุญาตเข้าไปใน TUser TUser จะมีชุดของสิทธิ์ จากนั้นในเครื่องมือจัดการคำสั่ง TLedger ฉันจะเรียกข้อมูลผู้ใช้และตรวจสอบว่าเขามีสิทธิ์ในการดำเนินการคำสั่งหรือไม่ แต่สิ่งนี้ต้องการให้ฉันดึงข้อมูลรวมของ TUser สำหรับทุกคำสั่ง TLedger
class TAddTransactionCmdHandler(cmd) {
this.userRepository.find(cmd.userId)
.then(function(user){
if (!user.can(cmd)){
throw new Error('Not authorized');
}
return this.ledgerRepository.find(cmd.ledgerId);
})
.then(function(ledger){
ledger.addTransaction(cmd);
})
}
- โดเมนอื่นพร้อมบริการ
ความเป็นไปได้อีกอย่างคือการสร้างแบบจำลองโดเมนการอนุญาตอื่นโดยสมบูรณ์ โดเมนนี้จะมีความสนใจในสิทธิการเข้าถึงการอนุมัติ ฯลฯ AuthorizationService.isAuthorized(user, command)
โดเมนย่อยบัญชีจากนั้นก็จะใช้บริการในการเข้าถึงโดเมนอนุมัตินี้ในรูปแบบของ
class TAddTransactionCmdHandler(cmd) {
authService.isAuthorized(cmd)
.then(function(authorized){
if (!authorized) throw new Error('Not authorized');
return this.ledgerRepository.find(cmd.ledgerId)
})
.then(function(){
ledger.addTransaction(cmd);
})
}
การตัดสินใจแบบใดที่เป็น "DDD / CQRS" มากที่สุด