การ Allow และ Deny

บทแทรก 8.5

แปลไปแล้ว

ในบทนี้ คุณจะได้

  • เรียนรู้เกี่ยวกับฟังก์ชัน callback แบบ Allow และ Deny
  • เข้าใจลำดับการเรียกใช้ฟังก์ชัน callback
  • ระบบรักษาความปลอดภัยของ Meteor นั้น ยอมให้เราทำการเปลี่ยนแปลงกับฐานข้อมูลโดยไม่จำเป็นต้องสร้างเมธอดขึ้นมาใหม่ทุกครั้ง ในขณะที่เราทำการเปลี่ยนแปลงนั้น

    เนื่องจากเราอาจจำเป็นต้องทำงานบางอย่างเพิ่มเติม เช่น ปรับแต่งข้อมูลข่าวด้วยฟิลด์พิเศษ และดำเนินการบางอย่างเมื่อ URL ของข่าวซ้ำกับที่มีอยู่แล้ว การใช้เมธอด post ในขณะที่กำลังสร้างข่าวก็ดูเหมาะสมดี

    หรืออีกนัยหนึ่งคือ เราไม่มีความจำเป็นต้องสร้างเมธอดใหม่เพื่ออัพเดทและลบข่าว เราแค่ตรวจสอบว่าผู้ใช้มีสิทธิในการทำแบบนั้นหรือไม่ ซึ่งทำได้ง่ายมากๆด้วยการใช้ฟังก์ชัน callback แบบ allow และ deny

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

    ฟังก์ชัน callback หลายตัว

    เราสามารถกำหนดฟังก์ชัน callback แบบ allow กี่ตัวก็ได้เท่าที่จำเป็น ขอแค่ให้มี ตัวใดตัวหนึ่ง คืนค่าเป็น true การเปลี่ยนแปลงที่รออยู่ก็จะเกิดขึ้นได้ โดยเมื่อ Posts.insert ถูกเรียกใช้จากเบราว์เซอร์ (ไม่ว่าจากในแอพหรือจากคอนโซล) เซิร์ฟเวอร์จะทำการตรวจค่า insert จากฟังก์ชัน allow ทั้งหมดจนกว่าจะพบตัวนึงที่มีค่าเป็นจริง และถ้าหาไม่พบเลย ก็จะไม่ยอมให้มีการทำงานเกิดขึ้น ทั้งยังคืนค่าผิดพลาด 403 กลับมาที่ไคลเอนต์ด้วย

    ในทำนองเดียวกัน เราก็สามารถกำหนดฟังก์ชัน callback แบบ deny ได้หลายตัวเช่นกัน ซึ่งถ้ามี ตัวใดตัวนึง คืนค่าเป็น true การเปลี่ยนแปลงก็จะถูกยกเลิก และค่าความผิดพลาด 403 ก็จะถูกส่งกลับมา ตรรกะแบบนี้หมายความได้ว่า การ insert ที่สมบูรณ์จะเกิดขึ้นได้ก็ต่อเมื่อฟังก์ชัน callback แบบ allow insert อย่างน้อยหนึ่งตัว กับฟังก์ชัน callback แบบ deny insert ทุกๆตัวถูกตรวจสอบแล้ว

    Note: n/e stands for Not Executed
    Note: n/e stands for Not Executed

    มองได้อีกแบบคือ Meteor จะทำการตรวจสอบฟังก์ชัน callback โดยเริ่มต้นจากแบบ deny แล้วจึงมาที่ allow และตรวจทีละตัวจนกว่าจะพบว่าตัวใดตัวนึงคืนค่าเป็น true

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

    การชดเชยความล่าช้า

    ให้จำไว้เลยว่า เมธอดที่เปลี่ยนแปลงฐานข้อมูล (เช่น .update()) จะทำงานแบบชดเชยความล่าช้าเหมือนกับเมธอดอื่นๆด้วย อย่างเช่น ถ้าคุณพยายามลบข่าวที่ไม่ใช่ของคุณผ่านคอนโซลของเบราว์เซอร์ คุณจะเห็นว่าข่าวที่ลบจะหายไปแว้บนึงเพราะคอลเลคชั่นที่ไคลเอนต์ถูกลบข้อมูลไป แต่แล้วข่าวนั้นก็จะแสดงขึ้นมาใหม่อีกครั้ง เพราะเซิร์ฟเวอร์แจ้งมาว่าข่าวนั้นยังไม่ได้ถูกลบออกไป

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

    ทั้งนี้ต้องขอบคุณ ความสามารถของการแชร์โค้ดให้ใช้งานกันได้ระหว่างไคลเอนต์และเซิร์ฟเวอร์ (อย่างเช่น คุณสามารถเขียนฟังก์ชัน canDeletePost(user, post) และวางมันไว้ในโฟลเดอร์ /lib ที่แชร์ระหว่างสองฝั่ง) ช่วยให้คุณไม่ต้องเขียนโค้ดมากเกินความจำเป็น

    สิทธิการใช้งานบนฝั่งเซิร์ฟเวอร์

    ที่ต้องจำอีกเรื่องคือ สิทธิการใช้งานของระบบจะถูกใช้เมื่อการเปลี่ยนแปลงฐานข้อมูลถูกสั่งจากฝั่งไคลเอนต์เท่านั้น ส่วนบนเซิร์ฟเวอร์ Meteor จะสมมุติว่า การทำงานทุกอย่างได้รับการอนุญาตแล้ว

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