الموضوع السابق   الموضوع التالي 

مراقبة صلاحيات المستخدم

Function: UserAuthorized

الغرض
التأكد مما إذا كانت المهمة التي يحاول المستخدم القيام بها في البرنامج هي من صلاحياته أم لا.


الصيغة

function UserAuthorized(Authorities: LongInt; Authority: TIntBitCount; ShowNonAuthorizedMsg: Boolean = False; NonAuthorizedMsg: string = ''): Boolean;


الوسائط (Parameters)

Authorities عدد صحيح طويل يمثل مجموع صلاحيات المستخدم.
Authority عدد صحيح بين 0 و 31 يمثل رقم الصلاحية المطلوب اختبارها.
ShowNonAuthorizedMsg بارامتر اختياري يحدد ما إذا سيتم عرض رسالة تنبيه إذا لم تكن الصلاحية المحددة في Authority من ضمن الصلاحيات. القيمة الافتراضية هي False و تعني أن الدالة لن تعرض رسالة تنبيه.
NonAuthorizedMsg بارامتر اختياري يحدد نص الرسالة التي سيتم عرضها إذا لم تكن الصلاحية المحددة من ضمن الصلاحيات، و كانت قيمة البارامتر ShowNonAuthorizedMsg هي True. القيمة الافتراضية نص فارغ (Empty String) و يعني أن الدالة ستعرض نصاً افتراضياً كرسالة.

الشرح
إذا كانت الصلاحية المحدد رقمها في البارامتر Authority واحدة من الصلاحيات المحددة في البارامتر Authorities فإن الدالة تعيد True، و إلا فإنها تعيد False. في حالة لم تكن الصلاحية من ضمن الصلاحيات (الدالة تعيد False) فإنه يمكن جعل الدالة تعرض رسالة تنبيه و ذلك بضبط البارامتر ShowNonAuthorizedMsg على True. في هذه الحالة، إذا أهملت قيمة البارامتر NonAuthorizedMsg (أو جعلت قيمته نصاً فارغاً Empty String) فإن الدالة تعرض رسالة تنبيه افتراضية هي "عفواً... ليس من صلاحياتك إنجاز هذه المهمة."، أما إذا قمت بتمرير أي نص آخر فإن الدالة ستعرض ذلك النص في الرسالة. عنوان الرسالة سيكون دائماً هو عنوان تطبيقك (Application.Title).

من واقع تجربتي وجدت أن أفضل طريقة لمراقبة صلاحيات المستخدمين في برنامج متعدد المستخدمين هو تمثيل الصلاحيات بعدد صحيح طويل يستخدم كقناع من البتات (Bit Mask). عندما نقول قناع بتات فذلك يعني أن كل قيمة فردية هي القيمة المقابلة لخانة واحدة فقط في الصورة الثنائية للعدد. أي أن القيم المسموح بها كقيم فردية هي 0, 1, 2, 4, 8, 16, 32,..., 2147483648 (و بالترقيم الستعشري: $00000000, $00000001, $00000002, $00000004, $00000008, $00000010, $00000020,..., $80000000) و بالتالي فإن كل بت واحدة تمثل صلاحية واحدة. فإذا كانت قيمة البت هي 1 فذلك يعني أن تلك الصلاحية هي من ضمن الصلاحيات، و إذا كانت قيمتها 0 فإن تلك الصلاحية ليست جزءاً من الصلاحيات. و من ذلك يتضح أن الأعداد التي تمثلها أكثر من بت واحدة تعني أن للمستخدم أكثر من صلاحية واحدة، فالعدد 9 مثلاً يعني أن للمستخدم صلاحيتان هما الصلاحية الأولى (البت 0 و قيمتها 1) و الصلاحية الرابعة (البت 3 و قيمتها 8). إذا كان للمستخدم جميع الصلاحيات فإن العدد الذي يمثل ذلك هو دائماً -1 (ناقص 1) حيث تكون قيم جميع البتات 1.

في البرامج التجارية و الإدارية، غالباً ما سيتم تخزين صلاحيات المستخدمين مع بياناتهم في الجدول الخاص بهم في قاعدة البيانات، و ليس من المنطقي أن نجعل لكل صلاحية حقلاً خاصاً بها (من النوع المنطقي Boolean) بحيث تكون قيمته True إذا كانت تلك الصلاحية من ضمن صلاحيات المستخدم، و تكون قيمته False إذا لم تكن تلك الصلاحية من ضمن صلاحيات المستخدم. تصور لو أن البرنامج الذي تقوم بتصميمه يحتوي على 20 أو 30 صلاحية - ستحتاج إلى 20 أو 30 حقلاً للصلاحيات (يا للهول!!!). و ماذا لو احتجت إلى تعديل البرنامج لزيادة صلاحياته؟ إن ذلك لن يجعلك تعدل في برنامجك فقط، بل سيضطرك إلى تعديل قاعدة البيانات أيضاً.

أما بالطريقة التي أستعملها فإن للصلاحيات حقلاً واحداً فقط نوعه عدد صحيح طويل (Long Integer) أخزن فيه العدد الذي يمثل مجموع صلاحيات المستخدم. القيد الوحيد على هذه الطريقة هو أن عدد الصلاحيات المتوفرة هو 32 صلاحية (4 بايت × 8 بتات)، و لكن من النادر جداً في معظم البرامج أن يصل عدد الصلاحيات إلى هذا العدد أو يتجاوزه. (إذا احتجت إلى أكثر من 32 صلاحية فحاول تصميم طريقة أو دالة تستعمل النوع Int64 بدلاً من النوع LongInt).

و إذا وجدت صعوبة في تذكر الأعداد التي تمثل الصلاحيات و احتمال الخطأ في كتابتها، فإن مما يسهل ذلك كثيراً هو تعريف تلك القيم كثوابت، مثلاً:

const
  AUTH_ADD_STUDENT = 0; // إضافة سجل طالب جديد
  AUTH_MODIFY_STUDENT = 1; // تعديل سجل طالب
  AUTH_REMOVE_STUDENT = 2; // حذف سجل طالب
  AUTH_ADD_SECTION = 3; // إضافة قسم جديد
  AUTH_MODIFY_SECTION = 4; // إضافة بيانات قسم
  AUTH_REMOVE_SECTION = 5; // حذف قسم
  AUTH_SHOW_REPORT = 6; // عرض تقرير
  AUTH_PRINT_REPORT = 7; // طباعة تقرير
  AUTH_DO_BACKUP = 8; // إنشاء نسخة احتياطية

أيضاً مما يسهل العمل في هذه المسألة تعريف سجل (record) يمثل بيانات المستخدم و تحميل بيانات المستخدم - الذي قام بتشغيل البرنامج - في ذلك السجل عند بدء تشغيل البرنامج، مثلاً:

type
 TAppUserData = record
  ID: Integer;
  Name: string;
  Password: string;
  Authority: LongInt;
 end;
.
.
.
 var
  CurrentUser: TAppUserData;
.
.
.
 CurrentUser.ID := Table1['UID'];
 CurrentUser.Name := Table1['UName'];
 CurrentUser.Password := Table1['Password'];
 CurrentUser.Authority := Table1['Authority'];
.
.
.
 if UserAuthorized(CurrentUser.Authority, AUTH_PRINT_REPORT, True) then begin

لإزالة كافة الصلاحيات اضبط المتغير الممثل للصلاحيات على 0، مثلاً:

CurrentUser.Authority := 0;

و لإعطاء كافة الصلاحيات اضبط المتغير الممثل للصلاحيات على -1، مثلاً:

CurrentUser.Authority := -1;

أما لإضافة صلاحية إلى مجموع الصلاحيات فاستعمل الدالة AddAuthority (إضافة صلاحية للمستخدم)، و لإزالة واحدة من الصلاحيات استعمل الدالة RemoveAuthority (إزالة صلاحية من المستخدم).


 أعلى الصفحة
 الموضوع السابق   الموضوع التالي