PDA

View Full Version : جلسه هشتم، گنگ و گیج کننده( البته واسه من)



desatir7316
چهارشنبه 28 اسفند 1392, 15:23 عصر
سلام
چند سوال از جلسه هشتم داشتم
اولیش اینه که مثلا توی Project این تابع رو داریم که id کاربر رو بهش می دیم:


public function isUserInProject($userId)
{
$sql = 'SELECT user_id FROM tbl_project_user_assignment WHERE user_id=:userId AND project_id=:projectId';
$command = Yii::app()->db->createCommand($sql);
$command->bindValue(':userId', $userId, PDO::PARAM_INT);
$command->bindValue(':projectId', $this->id, PDO::PARAM_INT);
return $command->execute() == 1;
}


حالا توی ProjectUserFrom که صداش می زنیم یه AR براش می فرستیم(توی شرط if) در حالی که باید id کاربر رو براش می فرستادیم، می خواستم ببینم این چظوری کار می کنه؟


public function verify($attribute, $params)
{
if(!$this->hasError())
{
$user = User::model()->findByAttributes(array('username'=>$this->username));
if($this->project->isUserInProject($user))
{
$this->addError('username', 'This user is alread in the project');
}
else
{
$this->_user = $user;
}
}
}





-----------------------------------------------------------------------------------------------------------------------------------------------
دومی اینکه توی ProjectUserForm اونجایی که داریم یه مدل از user$ می سازیم ، مقدار this->username$ از کجا میاد؟ خوب ما username$ رو به عنوان یه صفت توی این کلاس تغریف کردیم و هیچ جا بهش مقدار ندادیم!



public function verify($attribute, $params)
{
if(!$this->hasError())
{
$user = User::model()->findByAttributes(array('username'=>$this->username));
if($this->project->isUserInProject($user))
{
$this->addError('username', 'This user is alread in the project');
}
else
{
$this->_user = $user;
}
}
}


-----------------------------------------------------------------------------------------------------------------------------------------------
این یکی رو دیگه اگه کامل توضیح بدین ممنون می شم که اصلا هیچی نمی فهمم ازش:


public function assign()
{
if($this->_user instanceof User)
{
$this->project->assignUser($this->_user->id, $this->role);
$auth = Yii::app()->authManager;
if(!$auth->isAssigned($this->role, $this->_user->id))
{
$bizRole = 'return isset($params["project"]) && $params["project"]->allowCurrentUser("'.$this->role.'");';
$auth->assign($this->role, $this->_user->id, $bizRole);
}
return true;
}
else
{
$this->addError('username', 'Error when attempting to assign this user to the project');
return false;
}
}




ممنون

desatir7316
چهارشنبه 28 اسفند 1392, 20:59 عصر
مسئولین لدفا...

desatir7316
چهارشنبه 28 اسفند 1392, 21:33 عصر
public function actionAddUser($id)
{
$project = $this->loadModel($id);
if(!Yii::app()->user->checkAccess('createUser', array('project'=>$project)))
{
throw new CHttpException(403, 'You are not authorized to perform this action');
}

. . . .


فکر کنم توی این دستور شرطی باشه که خودبه خود میره مقدار فیلد bizrule رو از db می خونه و اون رو اعمال می کنه؟ درسته ؟

MMSHFE
چهارشنبه 28 اسفند 1392, 22:00 عصر
public function isUserInProject($userId)
{
$sql = 'SELECT user_id FROM tbl_project_user_assignment WHERE user_id=:userId AND project_id=:projectId';
$command = Yii::app()->db->createCommand($sql);
$command->bindValue(':userId', $userId, PDO::PARAM_INT);
$command->bindValue(':projectId', $this->id, PDO::PARAM_INT);
return $command->execute() == 1;
}


البته کدی که توی فیلم آموزشی هست اینطوریه:


public function isUserInProject($user)
{
$sql = "SELECT user_id FROM tbl_project_user_assignment WHERE project_id=:projectId AND user_id=:userId";
$command = Yii::app()->db->createCommand($sql);
$command->bindValue(":projectId", $this->id, PDO::PARAM_INT);
$command->bindValue(":userId", $user->id, PDO::PARAM_INT);
return $command->execute()==1;
}

خوب این متد که کارش مشخصه: توی جدول project_user_assignment چک میکنه ببینه کاربری که مدل ActiveRecord اون رو بعنوان پارامتر به این متد میدیم، توی پروژه جاری عضو هست یا نه.

حالا توی ProjectUserFrom که صداش می زنیم یه AR براش می فرستیم(توی شرط if) در حالی که باید id کاربر رو براش می فرستادیم، می خواستم ببینم این چظوری کار می کنه؟
نه دیگه، اگه id رو میفرستادیم دیگه توی کد نمیتونستیم بگیم user->id$ و باید میگفتیم id$ (البته میشد اون کار رو هم انجام بدیم و اشتباه نیست ولی شاید توی پروژه خاصی نیاز به بقیه فیلدهای مدل هم توی متد پیدا کنید که دراینصورت بهتره همون مدل رو بعنوان پارامتر بفرستین نه فقط id اون رو)

دومی اینکه توی ProjectUserForm اونجایی که داریم یه مدل از user$ می سازیم ، مقدار this->username$ از کجا میاد؟ خوب ما username$ رو به عنوان یه صفت توی این کلاس تغریف کردیم و هیچ جا بهش مقدار ندادیم!
خوب به این تکه های کد توی همون فایل ProjectUserForm.php دقت کنید:


...
public $username;
...
public function rules()
{
return array(
...
array('username', 'verify'),
);
}
...
public function verify($attribute,$params) {
...
}
...

خوب خط اول داره فیلد username$ رو برای این مدل تعریف میکنه.
خط بعدی داره یک validator دستی براش تعریف میکنه. توی Yii همه validatorهای تعریف شده در متد rules بطور خودکار وقتی فرم submit میشه و فرضاً میگیم $model->attributes = $_POST['ProjectUser']; بطور خودکار صدا زده میشن و مقداردهیها انجام میشه. ولیدیتورهای دستی (که خودمون میسازیم - مثل همین verify) دو تا پارامتر میگیرن که اولی، فیلدی هست که باید validate بشه (در اینجا username) و دومی هم پارامترهای جانبی که اگه لازم داشتیم براش میفرستیم و خودش عمل انتساب رو انجام میده.

این یکی رو دیگه اگه کامل توضیح بدین ممنون می شم که اصلا هیچی نمی فهمم ازش:
این کد داره میگه اگه فیلد user_ از شئ جاری (پروژه) از نوع کلاس User بود (null نبود و شئ ایجاد شده بود - یعنی کاربر پیدا شده بود)، متد assignUser رو از مدل project شئ ActiveRecord مربوط به پروژه جاری صدا بزنه و id کاربر و نقش موردنظر رو براش بعنوان پارامتر بفرسته تا توی جدول project_user_assignment درج بشه.
بعد میاد کامپوننت authManager فریمورک Yii رو که مسئول بررسی نقشهاست (RBAC) صدا میزنه و با کمک bizRule که تعریف کردیم، متد assign کامپوننت مذکور رو فراخوانی میکنه و نقش و id کاربر رو بهش میده تا توی جدول auth_assignment مربوط به RBAC درج بشه.
اگه باز هم ابهامی بود، توصیه میکنم یکبار دیگه دقیقاً فیلم آموزشی رو (بخصوص جلسه مربوط به RBAC) مشاهده کنید و مرحله به مرحله هرجا رو متوجه نشدین، بپرسین و نگذارین چند تا موضوع روی هم انباشته بشه و اینجوری سردرگم بشین.

desatir7316
چهارشنبه 28 اسفند 1392, 22:50 عصر
خوب خط اول داره فیلد username$ رو برای این مدل تعریف میکنه.
خط بعدی داره یک validator دستی براش تعریف میکنه. توی Yii همه validatorهای تعریف شده در متد rules بطور خودکار وقتی فرم submit میشه و فرضاً میگیم $model->attributes = $_POST['ProjectUser']; بطور خودکار صدا زده میشن و مقداردهیها انجام میشه. ولیدیتورهای دستی (که خودمون میسازیم - مثل همین verify) دو تا پارامتر میگیرن که اولی، فیلدی هست که باید validate بشه (در اینجا username) و دومی هم پارامترهای جانبی که اگه لازم داشتیم براش میفرستیم و خودش عمل انتساب رو انجام میده.


یه کم یه گنگه!
ببینید الان به جز اینکه ما خودمون توی actionAddUser میایم مقدار زیر رو ست می کنیم:
$form->attributes = $_POST['ProjectUserForm']; دیگه مگه لازمه خودش بیاد به صورت خودکار این کار رو انجام بده؟

MMSHFE
پنج شنبه 29 اسفند 1392, 00:21 صبح
نه دیگه همون موقع Mass Assignment کار ولیدیشنها انجام میشه.

desatir7316
جمعه 01 فروردین 1393, 10:47 صبح
$role=$this->_authManager->createRole("reader");
$role->addChild("readUser");
$role->addChild("readProject");
$role->addChild("readIssue");

$role=$this->_authManager->createRole("member");
$role->addChild("reader");
....
$role=$this->_authManager->createRole("owner");
$role->addChild("reader");
$role->addChild("member");
...


وقتی member دسترسی های reader رو داره و owner دسترسی های member، دیگه چرا توی ساختن نقش owner بازم نقش reader رو صریحا بهش دادیم؟ مگه خودش از member نمی گیرش؟

MMSHFE
جمعه 01 فروردین 1393, 11:40 صبح
به ترتیبشون دقت کنید. اول reader اضافه شده. راستش تست نکردم ببینم وقتی مستقیماً فقط member رو اضافه میکنیم، reader هم اضافه میشه یا نه. میتونید تست کنید ببینید اضافه میکنه یا خیر و نتیجه رو همینجا اعلام کنید.

desatir7316
جمعه 01 فروردین 1393, 13:10 عصر
فعلا کامل بفهمم چی به چیه، تازه به این مبحث رسیدم، بعدش چشم حتما می نویسمش

desatir7316
جمعه 01 فروردین 1393, 21:36 عصر
سلام
می گم mass Assignment جه موقع هست؟ همون موقع که اطلاعات ارسال می شن و rule ها اعمال می شن؟
اگه اینجوریه یه نگاهی به این بندازید:



class ProjectUserForm extends CFormModel
{
/**
* @var string username of the user being added to the project
*/
public $username;

/**
* @var string the role to which the user will be associated within the project
*/
public $role;

/**
* @var object an instance of the Project AR model class
*/
public $project;

private $_user;

/**
* Declares the validation rules.
* The rules state that username and password are required,
* and password needs to be authenticated using the verify() method
*/
public function rules()
{
return array(
// username and role are required
array('username, role', 'required'),
//username needs to be checked for existence
array('username', 'exist', 'className'=>'User'),
array('username', 'verify'),
);
}


/**
* Authenticates the existence of the user in the system.
* If valid, it will also make the association between the user, role and project
* This is the 'verify' validator as declared in rules().
*/
public function verify($attribute,$params)
{
if(!$this->hasErrors()) // we only want to authenticate when no other input errors are present
{
$user = User::model()->findByAttributes(array('username'=>$this->username));
if($this->project->isUserInProject($user))
{
$this->addError('username','This user has already been added to the project.');
}
else
{
$this->_user = $user;
}
}
}

...


تابع verify خودش یکی از rule هاست و موقع ای که همه rule ها اعمال می شن این هم استفاده می شه، از طرفی داخلش project$ استفاده شده، حالا مقدار دهی project$ کجاست و به چه صورت انجام شده، مگه خودش همون موقع در حال استفاده شدن نیست؟

desatir7316
جمعه 01 فروردین 1393, 22:05 عصر
public function actionAdduser($id)
{
$project = $this->loadModel($id);
if(!Yii::app()->user->checkAccess('createUser', array('project'=>$project)))
{
throw new CHttpException(403,'You are not authorized to perform this action.');
}

$form=new ProjectUserForm;
// collect user input data
if(isset($_POST['ProjectUserForm']))
{
$form->attributes=$_POST['ProjectUserForm'];
$form->project = $project;
// validate user input
if($form->validate())
...


این شرطی form->validate$ منظورش همون اعمال شدن rule ها توی ProjectUserForm هست؟

MMSHFE
شنبه 02 فروردین 1393, 03:02 صبح
نه ببینید، اگه مدل شما از CActiveRecord مشتق شده باشه، فرضاً وقتی شما مینویسید:

$model->attributes = $_POST['Register'];
در همین زمان که بهش میگیم Massive Assignment (مقداردهی انبوه)، عمل Validation طبق ruleهایی که نوشتین انجام میشه و فرضاً اگه ایمیل با ساختار استاندارد ایمیل وارد نشده باشه، خطا تولید میشه که میتونید با ()model->hasErrors$ چک کنید ببینید خطا وجود داره یا نه و با ()model->getErrors$ همه خطاها و با ('model->getError('email$ خطای خاصی (مثل ایمیل) رو بدست بیارین.
اما اگه مدل شما از کلاس دیگری (مثل CFormModel) مشتق شده باشه، خودتون باید با ()model->validate$ اعتبارسنجیها رو فراخوانی کنید (فقط شما فراخوانی میکنید و باز هم طبق ruleهای تعریف شده، اعتبارسنجی انجام میشه). بطور کلی به ساختار زیر:

$model->attributes = $_POST['Register'];
میگیم Mass Assignment که باعث میشه بطور خودکار مقادیر اعتبارسنجی بشن و یکی یکی توی خونه های متناظر خودشون در مدل قرار بگیرن. مثلاً اگه اسم یک عنصر فرمتون باشه Register[name] و توی مدلتون هم فیلد name داشته باشین، دستور بالا باعث میشه مقدار واردشده توی اون عنصر توی فیلد model->name$ قرار بگیره (بعد از اعتبارسنجی) و به همین شکل همه فیلدها با عناصر متناظر خودشون توی فرم، مقداردهی بشن.

desatir7316
شنبه 02 فروردین 1393, 22:35 عصر
سلام
می گم تابع checkAccess هیچوقت برام مقدار true برنمی گردونه
مشکل از کجاست؟
برای اینکه مطمئن بشم مقدار bizRule هم موقتا با مقدار return true تغییر دادم ولی بازم false هست
چیز خاصی رو باید از جایی تنظیم کنم؟
وقتی پروژه های خودتون رو تست می کنم روی همین دیتابیس کار می کنه، ولی کدی رو که خودم تمرین کردم خیر، نمی تونم پیداش کنم

راستی ()Yii::app()->authManager->getRoles این هم یه آرایه خالی برمیگردونه ولی توی قسمت برنامه نویسی console هیچ مشکلی نبود
ممنون می شم راهنمایی کنید

MMSHFE
یک شنبه 03 فروردین 1393, 01:01 صبح
تنظیمات کامپوننت رو توی هر دو فایل main و console به درستی انجام دادین یا نه؟ میتونید TeamViewer بدین؟

desatir7316
یک شنبه 03 فروردین 1393, 09:52 صبح
درست شد، توی هردوتاش باید انجام می شد، باید یه کم بیشتر دقت می کردم، ببخشید که وقتتونو گرفتم
ممنون

desatir7316
یک شنبه 03 فروردین 1393, 10:51 صبح
فعلا کامل بفهمم چی به چیه، تازه به این مبحث رسیدم، بعدش چشم حتما می نویسمش


به ترتیبشون دقت کنید. اول reader اضافه شده. راستش تست نکردم ببینم وقتی مستقیماً فقط member رو اضافه میکنیم، reader هم اضافه میشه یا نه. میتونید تست کنید ببینید اضافه میکنه یا خیر و نتیجه رو همینجا اعلام کنید.

تابع allowCurrentUser مقدار یه role خاص رو برای یه کاربر خاص توی یه پروژه خاص چک می کنه، خوب وقتی من می خوام checkAccess رو اینجا برای اون کاربری که owner هست برای read صدا بزنم، تابع allowCurrentUser همیشه مقدار false بر می گردونه!! چون قبلا برای owner توی tbl_project_user_assignment یه مقدار شبیه زیر ریختم:


project_id
user_id
role



1
1
owner



فکر می کنم مشکل اینجاست که کسی که به عنوان owner هست دیگه به عنوان member و reader عمل نمی کنه در حال که نباید اینجوری می شد و سلسله مراتب توی رابطه ها حفظ می شد!
چیکارش باید کرد؟

ProjectController.php:


public function actionView($id)
{
$project = $this->loadModel($id);
if(!Yii::app()->authManager->checkAccess('readProject',Yii::app()->user->getId(), array('project'=>$project)))
{
throw new CHttpException(403, 'You\'re not authorized');
}

$this->render('view',array(
'model'=>$this->loadModel($id),
));
}


ولی وقتی توی tbl_auth_assignment سطر دوم هم اضافه می کنم دیگه درست می شه:


itemname
bizrule
userid
data



createUser
return isset($params["project"]) && $params["project"]->allowCurrentUser("owner");
1
NULL


readProject
return isset($params["project"]) && $params["project"]->allowCurrentUser("owner");
1
NULL



آیا باید این سطر اضافه بشه؟ مگه ما نگفیم کسی که owner هست reader , member هم هست، دوباره اینجا داریم صریحا می گیم کاربر 1 باید readProject رو داشته باشه

MMSHFE
یک شنبه 03 فروردین 1393, 15:21 عصر
احتمالاً bizRule ها رو درست تنظیم نکردین که این مشکلات پیش میاد چون من امتحان کردم مشکلی نداشت و درست عمل میکرد. اگه درست انجام شده باشه نیازی به درج دستی سطر دوم نیست.

desatir7316
یک شنبه 03 فروردین 1393, 15:42 عصر
احتمالاً bizRule ها رو درست تنظیم نکردین که این مشکلات پیش میاد چون من امتحان کردم مشکلی نداشت و درست عمل میکرد. اگه درست انجام شده باشه نیازی به درج دستی سطر دوم نیست.

پس در هر صورت نیاز به درج هست، ولی نیاز به درج دستی نیست، درسته؟

راستی مطمئنا نمونه extention های مختلفی برای rbac هست، ممنون می شم شمایی که شناخت بهتری دارید چند تاشونو معرفی کنید که قدرت بالاتر و کاربری راحت تری داشته باشن، چیزی که من سرچ کردم ظاهرا rights , srbac چیزای خوبی هستن ولی اطالاعت کاملی نتونستن به دست بیارم، در حد پیشنهاد بودن

MMSHFE
سه شنبه 05 فروردین 1393, 01:06 صبح
راستشو بخواین چون توی پروژه های خودم نیاز زیادی به RBAC نداشتم، خیلی وارد جزئیاتش نشدم و دقیقاً نمیدونم چطوریه ولی قاعدتاً باید خودش انجام بده و وقتی نقش owner داده میشه دیگه حتی خودکار هم نباید سطرهای reader و... درج بشه وگرنه ساختار سلسله مراتبی معنا پیدا نمیکنه. اگه میشد TeamViewer بدین خیلی خوب بود ولی چندبار گفتم و تمایلی نشون ندادین و من هم دیگه اصراری ندارم که به این روش مشکلتون برطرف بشه و سعی میکنم درموردش تحقیق کنم و عملی هم تست کنم ببینم میتونم بفهمم مشکل کار شما از کجاست یا نه و همینجا نتیجه رو میگذارم. فقط ممکنه دو سه روزی طول بکشه.