السلام عليكم...
استعمال حقل من النوع Boolean (نعم/لا في Access) لكل صلاحية من الصلاحيات في جدول المستخدمين (Users) أو المشغلين قد يكون مقبولاً إذا كان عدد الصلاحيات 4 أو 5، مع عدم احتمال زيادة تلك الصلاحيات.
لكن ماذا لو كان عدد الصلاحيات 15 أو 20 أو 30 صلاحية؟؟!! من غير المعقول أن يكون لدي 20 أو 30 حقلاً من أجل معالجة الصلاحيات!!! بالإضافة إلى أننا سنضطر لتعديل الجدول في قاعدة البيانات كلما تم تعديل عدد الصلاحيات.
من واقع التجربة وجدت أن أفضل طريقة هي استعمال فكرة قناع البتات (BitMask) و ذلك باستعمال حقل رقمي من النوع الصحيح الطويل (Long) و هذا سيعطينا المجال للتعامل مع 32 صلاحية إذا استعملنا Access. و إذا كنا نستعمل SQL Server فإننا نستطيع استعمال حقل من النوع bigint للتعامل مع 64 صلاحية.
لتوضيح الفكرة - و هي بسيطة جداً - سنستعمل البايت (Byte) كمثال. نعرف أن البايت تتكون من 8 بتات (من 0 عند اليمين إلى 7 عند أقصى اليسار. لكننا سنتعامل معها على أنها مرقمة من 1 إلى 8)، و بالتالي فإن قيم هذه البتات هي:
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
إذن مع البايت يمكنني أن أتعامل مع 8 صلاحيات. كيف؟ نعطي للصلاحيات أرقام البتات، و يستحسن استخدام الثوابت حتى لا نضطر إلى حفظ القيم، مثلاً:
- ' Module في
- Public Const AUTH_ADD = 1& ' إضافة سجلات جديدة
- Public Const AUTH_MODIFY = 2& ' تعديل بيانات
- Public Const AUTH_DELETE = 3& ' حذف سجلات
- Public Const AUTH_BACKUP = 4& ' حفظ نسخة احتياطية
- Public Const AUTH_PRINT = 5& ' طباعة التقارير
لاحظ أننا نضع العلامة & مع الأرقام ليعاملها البرنامج على أنه من النوع Long.
إذا كان من حق المستخدم مثلاً أن يضيف سجلات فقط فإننا نضبط قيمة البايت على 1، و إذا كان من صلاحياته أن يقوم بالنسخ الاحتياطي فقط فإننا نضبط قيمة البايت على 8.
ماذا لو كان من صلاحياته أن يقوم بالعملين معاً؟؟ نضبط قيمة البايت على 9 (1 و 8) و إذا كان من حقه أيضاً أن يطبع التقارير فإننا نضبط القيمة على 25 (1 و 8 و 16) ... إلخ.
و إذا أردنا منح المستخدم كافة الصلاحيات فيجب ضبط جميع البتات على 1 أي ستكون قيمة البايت 255.
إذا قمنا بتكبير العدد من بايت إلى عدد صحيح طويل (Long) فذلك يعني أننا سنتعامل مع 4 بايت، و بالتالي 4 × 8 = 32 صلاحية.
نأتي إلى الجانب العملي:
نفرض أن لدينا جدول المستخدمين اسمه Users و يتكون من الحقول التالية:
رقم المستخدم UserID
اسم المستخدم UserName
كلمة المرور Password
الصلاحيات Authority (من النوع الرقمي Number و حجمه عدد صحيح طويل Long).
و ربما يكون لديك حقول أخرى. لا يهم.
لن أتحدث هنا عن كيفية الربط مع الجدول من داخل VB و كيفية التأكد من وجود اسم المستخدم و صحة كلمة المرور! لكني سأفترض أننا نستعمل مكون ADO data control باسم Adodc1 مرتبط بالجدول Users و أننا وجدنا الاسم في الجدول و أن كلمة المرور المدخلة صحيحة.
علينا الآن أن نحتفظ بقيمة الحقل Authority (الذي يمثل الصلاحيات) في متغير عام مصرح عنه في Module كالتالي (يمكنك اختيار أي اسم له). سنحتاج أيضاً للحصول على رقم المستخدم لحفظ الصلاحيات فيما بعد
- Public UserAuthority As Long
- Public Uid As Long
إذن بعد التأكد من وجود الاسم و صحة كلمة المرور سيكون لدينا السطران التاليان:
- UserAuthority = Adodc1.Recordset("Authority")
- Uid = Adodc1.Recordset("UserID")
أيضاً في الـ Module سنكتب 4 إجراءات و دالة واحدة:
- ' إجراء لإضافة صلاحية إلى مجموعة الصلاحيات
- Public Sub AddAuthority(ByRef Authorities As Long, ByVal Authority As Long)
- Dim AuthorityValue As Long
- If (Authority >= 1) And (Authority <= 32) Then
- AuthorityValue = 2 ^ (Authority - 1)
- Authorities = (Authorities Or AuthorityValue)
- End If
- End Sub
- ' إجراء لمنح المستخدم كافة الصلاحيات
- Public Sub AddAllAuthorities(ByRef Authorities As Long)
- Authorities = -1&
- End Sub
- ' إجراء لحذف صلاحية من المستخدم
- Public Sub RemoveAuthority(ByRef Authorities As Long, ByVal Authority As Integer)
- Dim AuthorityValue As Long
- If (Authority >= 1) And (Authority <= 32) Then
- AuthorityValue = 2 ^ (Authority - 1)
- Authorities = (Authorities And (Not AuthorityValue))
- End If
- End Sub
- ' إجراء لحذف كافة الصلاحيات
- Public Sub RemoveAllAuthorities(ByRef Authorities As Long)
- Authorities = 0&
- End Sub
- ' دالة للتحقق من وجود صلاحية معينة ضمن الصلاحيات
- Public Function UserAuthorized(ByVal Authorities As Long, ByVal Authority As Long) As Boolean
- Dim AuthorityValue As Long
- If (Authority < 1) Or (Authority > 32) Then
- UserAuthorized = False
- Else
- AuthorityValue = 2 ^ (Authority - 1)
- If (Authorities And AuthorityValue) = AuthorityValue Then
- UserAuthorized = True
- Else
- UserAuthorized = False
- End If
- End If
- End Function
في كل الإجراءات السابقة، البارامتر Authorities هو مجموع صلاحيات المستخدم (الذي يمثله المتغير UserAuthority) و Authority هو أحد أرقام الصلاحيات المطلوبة (و التي قمنا بتعريفها كثوابت في البداية).
و الآن لنفرض أن المستخدم يريد أن يضيف سجلاً جديداً، و نريد أن نتأكد أنه من صلاحياته أن يفعل ذلك:
- If UserAuthorized(UserAuthority, AUTH_ADD) Then
- ' ...
- ' إجراءات تنفيذ الإضافة
- ' ...
- Else
- MsgBox "المعذرة. ليس من صلاحياتك إضافة سجلات جديدة"
- End If
و إذا أردنا أن نمنح المستخدم صلاحية طباعة التقارير:
- AddAuthority UserAuthority, AUTH_PRINT
و لمنحه كافة الصلاحيات:
- AddAllAuthorities UserAuthority
لتعديل صلاحيات مستخدم آخر غير المستخدم الحالي - و هو ما يحدث غالباً - احتفظ برقمه و قيمة صلاحياته في متغيرين (من Adocdc1.Recordset) ثم استعمل الإجراءات المذكورة أعلاه لتعديل قيمة الصلاحيات، ثم لا تنس أن تحفظ القيمة الجديدة للصلاحيات في الجدول:
- Adodc1.Recordset("Authority") = UserAuthority
- Adodc1.Recordset.Update
طبعاً بدل المتغير UserAuthority ستستعمل اسم المتغير لديك، بالإضافة إلى أنك قد تحتاج إلى البحث عن المستخدم برقمه في Adodc1.Recordset.
نرجو الاستفادة و السلام.