DDD CQRS - ต่อการสืบค้นและการอนุญาตตามคำสั่ง


15

สรุป

ควรอนุญาตใน 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 ()" เป็นต้น

  1. สิทธิ์การแมปผู้ใช้ -> บัญชีแยกประเภท -> คำสั่ง / แบบสอบถาม

  2. ผู้ใช้การแมปสิทธิ์-> บัญชีแยกประเภท -> สิทธิ์ -> คำสั่ง / แบบสอบถาม

นั่นเป็นส่วนแรกของคำถาม หรือโดยย่อควรอนุญาตใน CQRS / DDD ต่อคำสั่งหรือต่อแบบสอบถาม? หรือควรให้การอนุมัติแยกออกจากคำสั่งหรือไม่

ประการที่สองเกี่ยวกับการอนุญาตตามสิทธิ์ ผู้ใช้ควรสามารถจัดการการอนุญาตบนบัญชีแยกประเภทของเขาหรือบนบัญชีแยกประเภทที่เขาได้รับอนุญาตให้จัดการ

  1. คำสั่งการจัดการการอนุญาตเกิดขึ้นในบัญชีแยกประเภท

ฉันคิดว่าการเพิ่มเหตุการณ์ / คำสั่ง / ตัวจัดการลงในการรวมบัญชีแยกประเภทเช่น grantPermission (), revokePermission () ฯลฯ ในกรณีนี้การบังคับใช้กฎเหล่านั้นจะเกิดขึ้นในตัวจัดการคำสั่ง แต่สิ่งนี้จะต้องมีคำสั่งทั้งหมดเพื่อรวมรหัสของผู้ใช้ที่ออกคำสั่งนั้น จากนั้นฉันจะตรวจสอบใน TLedger หากมีสิทธิ์สำหรับผู้ใช้นั้นในการดำเนินการคำสั่งนั้น

ตัวอย่างเช่น :

class TLedger{ 
    function addTransactionCmdHandler(cmd){
        if (!this.permissions.exist(user, 'addTransaction')
            throw new Error('Not Authorized');
    }
}
  1. คำสั่งการจัดการการอนุญาตในผู้ใช้

อีกวิธีคือการรวมการอนุญาตเข้าไปใน 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);
    })

}
  1. โดเมนอื่นพร้อมบริการ

ความเป็นไปได้อีกอย่างคือการสร้างแบบจำลองโดเมนการอนุญาตอื่นโดยสมบูรณ์ โดเมนนี้จะมีความสนใจในสิทธิการเข้าถึงการอนุมัติ ฯลฯ 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" มากที่สุด


1
คำถามที่ดี - ฉันพยายามที่จะแก้ไขปัญหาที่คล้ายกันและดูเหมือนว่าไม่มีวรรณกรรมใดที่จะพูดถึงมันโดยตรง ฉันสับสนเล็กน้อยในช่วงครึ่งหลังของคำถามของคุณ ดูเหมือนว่าคุณสงสัยว่าจะจัดการสิทธิ์ใช้งานที่ไหน (เพิ่มหรือลบการอนุญาต) แต่ตัวอย่างที่แสดงมีไว้สำหรับเพิ่มธุรกรรมดังนั้นดูเหมือนว่าครึ่งหลังจะถามว่า "ฉันควรสอบถามสิทธิ์อย่างไร" คุณช่วยอธิบายส่วนนั้นได้มั้ย
emragins

แต่ละธุรกรรมอาจมีนโยบายการดำเนินการ ผู้ใช้แต่ละคนควรอยู่ในกลุ่มแร่มากกว่าหนึ่งกลุ่มแต่ละกลุ่มจะมีโปรไฟล์การเข้าถึงที่ระบุธุรกรรมที่ได้รับอนุญาต ณ รันไทม์ก่อนดำเนินการธุรกรรมนโยบายจะถูกตรวจสอบกับโปรไฟล์รวมสำหรับผู้ใช้ที่ดำเนินการ แน่นอนว่าพูดง่ายกว่าทำ
NoChance

คำตอบ:


5

สำหรับคำถามแรกฉันต้องดิ้นรนกับสิ่งที่คล้ายกัน มากขึ้นเรื่อย ๆ ฉันกำลังมุ่งหน้าไปยังรูปแบบการให้สิทธิ์สามขั้นตอน:

1) การอนุญาตที่ระดับคำสั่ง / แบบสอบถามของ "ผู้ใช้รายนี้เคยได้รับอนุญาตให้ใช้คำสั่งนี้หรือไม่" ในแอป MVC สิ่งนี้อาจจัดการได้ในระดับตัวควบคุม แต่ฉันเลือกใช้ตัวจัดการล่วงหน้าทั่วไปที่จะสอบถามที่เก็บสิทธิ์ตามผู้ใช้ปัจจุบันและคำสั่งการดำเนินการ

2) การอนุญาตภายในบริการแอปพลิเคชันของ "ผู้ใช้รายนี้" เคยมีสิทธิ์ในการเข้าถึงเอนทิตีนี้หรือไม่ "ในกรณีของฉันนี่อาจจะเป็นการตรวจสอบโดยนัยเพียงแค่ใช้ตัวกรองในพื้นที่เก็บข้อมูล - ในโดเมนของฉัน โดยพื้นฐานแล้วผู้เช่ามีรหัสองค์กรเล็ก ๆ น้อย ๆ

3) การอนุญาตที่อาศัยคุณสมบัติชั่วคราวของเอนทิตีของคุณ (เช่นสถานะ) จะได้รับการจัดการภายในโดเมน (เช่น "มีเพียงบางคนเท่านั้นที่สามารถแก้ไขบัญชีแยกประเภทที่ปิด") ฉันกำลังเลือกที่จะใส่สิ่งนั้นไว้ในโดเมนเพราะมันต้องอาศัยโดเมนและตรรกะทางธุรกิจเป็นอย่างมากและฉันไม่สะดวกที่จะเปิดเผยสิ่งนั้นในที่อื่น

ฉันชอบที่จะได้ยินการตอบสนองของผู้อื่นต่อความคิดนี้ - ฉีกเป็นชิ้นเล็กชิ้นน้อยถ้าคุณต้องการ (เพียงแค่ให้ทางเลือกบางอย่างถ้าคุณทำ :))


ฉันคิดว่าคุณมีคะแนนที่ถูกต้องเกี่ยวกับ "เลเยอร์" ที่แตกต่างกันของการให้สิทธิ์ ระบบที่ฉันใช้งานมีผู้ใช้หลายประเภททั้งผู้ใช้ที่ลงทะเบียนและพนักงาน สิทธิ์ของตัวจัดการคำสั่ง / แบบสอบถามทำการตรวจสอบเบื้องต้นเกี่ยวกับประเภทผู้ใช้ ถ้าเป็นพนักงานมันจะผ่านไปเสมอ ถ้ามันเป็นผู้ใช้ที่ลงทะเบียนแล้วมันจะได้รับอนุญาตเฉพาะในกรณีที่เงื่อนไขบางประการ (เช่นสิทธิ์ในการรวม)
แมกนัส

0

ฉันจะใช้การอนุญาตเป็นส่วนหนึ่งของการอนุญาต BC ของคุณ แต่ปรับใช้เป็นตัวกรองการดำเนินการในระบบบัญชีแยกประเภทของคุณ ด้วยวิธีนี้พวกเขาสามารถแยกทางตรรกะออกจากกันได้ - รหัสบัญชีแยกประเภทของคุณไม่ควรเรียกรหัสอนุญาต - แต่คุณยังคงได้รับประสิทธิภาพสูงในกระบวนการอนุมัติคำขอที่เข้ามาแต่ละครั้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.