سطح دسترسی Cdbauthmanager

[font="Tahoma"][right]

توی کتاب آجیل، برای سطح دسترسی، سه تا جدول به اسم های

AuthItem

AuthItemChild

AuthAssignment

میسازه

که نقش،وظیفه و عمل رو تعریف میکنه و به کاربر اختصاص میده

حالا سوال من اینجاست که برای اعمال این سطح دسترسی،باید بصورت دستی توی همه اکشن های یک کنترلر

شرط زیر رو بنویسیم؟

بافرض داشتن رکوردی با نام

createArticle

توی جدول

authitem

[left]




if(!Yii::app()->user->checkAccess('createArticle'))

{

   throw new CHttpException(403,'شما به صفحه ارسال مقاله دسترسی ندارید');

}



[/left]

نمیشه اینو یه جوری توی

accessRules

قرار داد؟

با داشتن نقش های

admin

owner

member

reader

میشه توی کد زیر

[left]




public function accessRules()

	{

		return array(

			array('allow',  // allow all users to perform 'index' and 'view' actions

				'actions'=>array('index','view'),

				'users'=>array('*'),

			),

			array('allow', // allow authenticated user to perform 'create' and 'update' actions

				'actions'=>array('create','update'),

				'users'=>array('@'),

			),

			array('allow', // allow admin user to perform 'admin' and 'delete' actions

				'actions'=>array('admin','delete'),

				'users'=>array('admin'),

			),

			array('deny',  // deny all users

				'users'=>array('*'),

			),

		);

	}



[/left]

قسمت

[left]




array('allow', // allow admin user to perform 'admin' and 'delete' actions

	'actions'=>array('admin','delete'),

	'users'=>array('admin'),

),



[/left]

به حالت زیر تغییر بدیم؟

[left]




'users'=>array('admin','owner','member'),



[/left]

چطور میشه ابه این صورت کلی

سطح دسترسی داد

اصلا این اسم

admin

مربوط به جدولی میشه یا بصورت پیشفرضه؟

[/right][/font]

[rtl]

[size="2"][font="Tahoma"]برای سطح دسترسی که به طور عام و در سطح کل برنامه تعریف میشه میتونید از همون فیلتر accessControl استفاده کنید

فقط اینکه در تعریف accessRules باید از پراپرتی roles استفاده کنید که البته شامل Tasks ، Roles و Operations میشه

برای توضیح کامل به اینجا مراجعه کنید.

به عنوان مثال[/font][/size]

[/rtl]




array('allow',

                'actions'=>array('admin'),

                'roles'=>array('admin','owner','member'),

            ),



[rtl][size="2"][font="Tahoma"]

که البته اگه سطح member زیر مجموعه admin و owner باشه نیاز به نوشتن اونها نیست و فقط با نوشتن member در اینجا این اکشن شامل سطوح بالاتر هم میشه

اما توجه کنید که بسیاری موارد سطح دسترسی باید در شرایط خاص بررسی بشه که در این موارد از business rules استفاده میکنند. که معمولا نیاز به پارامترهای اضافه داره

مثلا در مورد این کتاب مالک فقط باید در پروژه های خودش سطح دسترسی مدیر داشته باشه بنابر این در زمان بررسی سطح دسترسی object پروژه به عنوان پارامتر اضافه به متد checkAccess فرستاده میشه که در این حالتها معمولا دسترسی با شرطی که خودتون تعریف میکنید بررسی میشه ، البته در شرایط پیشرفته تر و برای جلوگیری از کپی کاری میتونید فیلترهای خاص خودتون رو تعریف کنید.

در مورد سوال آخر هم اینکه اون یوزر admin به صورت hardcode در UserIdentity درون یک آرایه تعریف شده که اصلا متد مناسبی برای سیستم کاربری نیست و البته وقتی در کتاب به این قسمت رسیدید یعنی اون سیستم رو به دیتابیس تغییر دادید و در این مرحله از کتاب دیگه یوز Admin وجود نداره بنابراین اون قوانینی هم که تعریف شده بی استفاده میشن

[/font][/size]

[/rtl]

[right]

ممنون از توجه و پاسختون

توی جدول

authitem

یه رکورد به اسم

createArticle

ثبت کردم

در جدول

authitemchild

یک ارتباط بین

owner

و

createArticle

دادم

accessRules

به این شکل تغییر دادم

[left]




array('allow', // allow admin user to perform 'admin' and 'delete' actions

	'actions'=>array('admin','delete'),

	'roles'=>array('admin','owner'),

),



[/left]

در جدول

authassignment

فیلد

itemname

رو برای کاربر خودم

member

تعریف کردم

با توجه به اینکه

owner

بالاتر از

member

هستش

و به عنوان

parent

ثبت شده

اماوقتی این آدرس رو میزنم

article/admin

با این کاربر، بهم خطا دسترسی میده مگر اینکه

داخل

accessRules

که بالا نوشتم

member

یا

reader

هم اضافه بشه

‘roles’=>array(‘admin’,‘owner’,‘reader’,‘member’),

دراین صورت خطای دسترسی نمیده

[/right]

[rtl][size="2"][font="Tahoma"]

role ای که بالاتر باشه به تمام اوپریشنها و تسکهای role پایین تر دسترسی داره نه برعکس، یعنی در این مورد هر چیزی که زیرمجموعه member باشه برای owner هم قابل دسترسی هست

اینطور که به نظر میاد شما میخواین task یا operation ای به اسم createArticle ایجاد کنید که member و owner و admin بتونن اکشنهای اون رو انجام بدن در شرایطی که owner زیرمجموعه admin و member زیر مجموعه owner و createArticle زیر مجموعه member باشه rule شما به صورت زیر تعریف میشه[/font][/size]

[/rtl]




array('allow', 

        'actions'=>array('admin','delete'),

        'roles'=>array('createArticle'),

),



[font=“Tahoma”][right]خیلی ممنونم از راهنماییت :)

:یه سوال دیگه

الان من فرضا سه نوع کاربر دارم که هر کدوم فیلدهای متمایز از هم دارن،که قطعا باید برای هر کدوم یه جدول ساخت

برای این موضوع باید چکار کنم تا بشه ازین سطح دسترسی استفاده کرد؟

[/right][/font]

[rtl]

سوال واضح نیست، لطفا بیشتر توضیح بدید

[/rtl]

[font="Tahoma"][right]

فرضا استاد و دانشجو ومدیر سیستم رو در نظر بگیرید

هر کدومشون اطلاعاتمخصوص به خودشونو دارن

حالا اگه بخوایم از جدولی به اسم

user

استفاده کنیم و همرو داخلش قرار بدیم کدنویسیمون چه تغییری باید بکنه

و یا اگه برای هر کدوم یه جدول لحاظ کنیم اونوقت سطح دسترسیو چجوری باید لحاظ کرد

اینجور مواقع چجوری عمل کنیم بهتره؟

[/right][/font]

[rtl][size="2"][font="Tahoma"]

معمولا جدول اطلاعات اولیه کاربرها یکسانه مثل نام ، نام خانوادگی ، ایمیل و… بنابراین برای نگهداری این قبیل اطلاعات لازم نیست برای هر گروه کاربری یک جدول مجزا تشکیل بشه، و معمولا با یک فیلد نوع میشه اونها رو از هم تفکیک کرد. اما بسته به سیستمی که تصمیم به طراحیش دارید ممکنه هر گروه کاربری اطلاعاتی اضافه بر اطلاعات پایه داشته باشه که میشه در جداول مجزا ذخیرشون کرد ، که البته مربوط به این بحث نیست.

اما در مورد سطح دسترسی کاربرها اگه از schema موجود در framework استفاده کرده باشید، یک جدول به اسم authassignment داره که میتونین به هر کاربر با استفاده از شناسه کاربر یک یا چند Role بدید.

و اگه در قستمهایی از برنامه لازم هست که این سطح دسترسی در شرایط خاص بررسی بشه، از business rule استفاده میکنید.

مثلا در یک سیستم آموزشگاه که نوع کاربری مدیر، معلم و دانش آموز داشته باشیم ، یک جدول برای کاربر و یک جدول برای دروس داریم، یک ارتباط چند به چند (many to many) بین جدول کاربر و درس ایجاد میکنیم. بنابر نوع کاربرها سه تا Role در جدول Authitem تعریف میکنیم و سطوح دسترسی رو برای اونها مشخص میکنیم

برای معلم امکان مشاهده و ثبت نمره

برای دانش آموز امکان مشاهده نمره

و برای مدیر امکان تعریف درس، مشاهده دروس و …

تا اینجا سطح دسترسی برای هر گروه کاربری مشخص شده، اما هر دانش آموز یا معلم در سطح کل سیستم به تمام درسها این دسترسی رو دارن، پس اینجا برای محدود کردن دسترسی معلم و دانش آموز به درسهای خودشون شناسه درس رو به عنوان پارامتر برای بررسی دسترسی میفرستیم و شرطی در فیلد bizrull قرار میدیم که بررسی کنه آیا این درس مربوط به این کاربر میشه یا نه

[/font][/size][/rtl]

[right][font="Tahoma"]

ببخشید بعضی جاهاش برام کمی گنگ بود

طبق نوشته های شما اومدم یه جدول به اسم

person

ساختم که مشخصات

نام کاربری،کلمه عبور،نوع کاربر،وشناسه کاربر از جدول مربوطش

بعد یه جدول برای مثلا دانش آموز ساختم،یه جدول هم برای مدیر سیستم،و یه جدول برای معلم

الان داخل جدول

person

سه تا رکورد ثبت کردم

که به ترتیب،نوعشون

admin

student

teacher

هستش و برای هرکدوم،شناسه کاربر رو از جدول مربوطش میارم

الان برای کد نویسی و ارتباطشون باید چکار کرد؟

توی جستجویی که داشتم

!به یه کلاس برخوردم نمیدونم این چیکار میکنه دقیقا

کجا باید نوشته بشه؟

و میتونه راهکاری برای مشکل من باشه؟

[left]




protected function instantiate($attributes){

        switch($attributes['user_type']){

            case 'admin':

                $class='AdminModel';

            break;

            case 'user':

                $class='studentModel';

            break;

            case 'doctor':

                $class='teacherModel';

            break;

            default:

                $class=get_class($this);

        }

        $model=new $class(null);

        

		return $model;

    }



[/left]

ممنون از راهنماییتون

[/font][/right]

[rtl]

[font="Tahoma"]دوست عزیز ممنون میشم در این مورد بیشتر توضیح بدید[/font][/rtl]

[right][font="Tahoma"]

طبق روشی که دوستمون پیشنهاد دادن و

سبک جداولی که توی پست قبلی توضیح دادم

با کمی کدنویسی ظاهرا تونستم این سطح دسترسی رو ایجاد کنم

روشش به این شکله که

داخل

UserIdentity

اومدم

این مقدارو قرار دادم


$this->setState('user_type', $person->user_type);

متغیر

$person->user_type

حاوی مقدار رکوردی از جدول

person

که با نام کاربری و کلمه عبور،لاگین کردیم

فیلد

user_type

هستش

که نوع کاربر منو مشخص میکنه که میخواد مدیرباشه،معلم باشه یا دانش آموز

حالا هرجای پروژه میتونیم با کد زیر به نوع کاربرمون دسترسی داشته باشیم


Yii::app()->user->user_type

بعدش اومدم توی مدل

PersonModel

در متد

relations()

هر سه تا ارتباطی که با جداول داره رو نوشتم

[left]




return array(

	'admin' => array(self::BELONGS_TO, 'AdminModel', 'id_person_user'),

	'teacher' => array(self::BELONGS_TO, 'TeacherModel', 'id_person_user'),

	'student' => array(self::BELONGS_TO, 'StudentModel', 'id_person_user'),

		);	



[/left]

حالا میشه راحت به اطلاعات کاربر در هر کدوم از جداول دسترسی داشت

مثلا


CHtml::encode($data->admin->lastname)

دوستان اگه پیشنهاد یا روش جدیدتری در این مورد دارید، بگید ممنون میشم

[/font][/right]

[rtl]

[font="Tahoma"]

برای توضیح بیشتر این قسمت عملیات مشاهده درس رو به صورت ساده مثال میزنم

در model درس یک متد به اسم checkUserAccess و به سورت static برای بررسی ارتباط بین درس و کاربر ایجاد مکنیم.

در جدول AuthItem یک operation به اسم lessonview ایجاد میکنیم و در فیلد bizzrule متد ایجاد شده رو فراخوانی میکنیم و در جدول AuthItemChild این operation رو به عنوان child برای role دانش آموز قرار میدیم.

در کنترلر درس و در اکشن مشاهده درس یک شرط با استفاده از متد checkAccess برای بررسی دسترسی کاربر به این اکشن میگذاریم lessionview رو به عنوان پارامتر اول و شناسه درس رو به عنوان پارامتر اضافه به این متد میفرستیم.

در فیلد bizzrule

[/font]

[/rtl]




return isset($params) && Lesson::checkUserAccess($params["lessonId"]);



[rtl]

[font="Tahoma"]

در اکشن مشاهده درس

[/font]

[/rtl]




if(!Yii::app()->user->checkAccess(lessonview,array('lessonId'=>$id)))

        throw new CHttpException(403);



[rtl]

[font="Tahoma"]

من از سیستمی که طراحی میکنید اطلاعی ندارم، اما برام جای سواله که چرا برای هر کدوم از انواع کاربر یک جدول درست کردید، چه اطلاعاتی در اون جداول ذخیره میشه که برای هر کاربر انقدر متفاوته که نیاز به یک جدول مجزا داشته باشه؟

[/font]

[/rtl]