I think Yii is the best framework I have used until now. Great work!
I’m working with Role-Based Access Control at the moment and find – when using a database-based system – it requires quite a lot of work to perform a checkAccess() on a user ID instead of a username, as Yii::app()->user->checkAccess($role) uses the username. I could of course use that, but when a user changes his or her username either he or she loses her rights or I have to perform an UPDATE SET oldname=newname on the AuthAssignment table.
The RBAC implemented by Yii allows you to use either user ID or username for access assignment and checking. The default implementation of CWebUser::checkAccess() uses its 'id' property to check the access. If you like, you can extend it and change to use 'name' property to do access checking.
Of course, you would need to adjust your DB schema accordingly.
Also, if you design your DB schema well, you don't have to do UPDATE…SET explicitly. The FK referential integrity will ensure the consistency should a PK is changed.
I'm also currently struggling with this. I want getId() to return the pk, not the username. I guess, i have to store the Pk somewhere in UserIdentity::authenticate(). I don't want to use get/setState() as i don't want the id to be stored in cookies (might be forged…). Maybe someone has a basic example, how to store persistent user data without using set/getState().
UserIdentity represents a way to authenticate a user. So we can have form-based identity, SSO identity, and so on. CWebUser represents persistent data relevant to the current user. It is more like $_SESSION.
It is serialized and saved in session or cookie, depending on CWebUser setting.
Saving in $_SESSION doesn't ensure the data is available next time you open the browser.
The cookie is equipped with a hash code that can prevent it from being tampered.
Jonah: what you did is as expected. The data stored using setState() is saved in $_SESSION or cookie (if auto-login is enabled). The main purpose of doing so is to save one DB query for each request. It has the drawback that the data may be outdated. For example, an admin user changed the rank of a user, while the old rank was still in use by its user (because it was read from session/cookie instead of DB). Therefore, you should not put too much data into identity states. Also note, it is possible that you save the whole user AR object into state. However, you need to make sure the data can be properly unserialized and it doesn't contain sensitive information like password.
It has the drawback that the data may be outdated. For example, an admin user changed the rank of a user, while the old rank was still in use by its user (because it was read from session/cookie instead of DB).
Yeah, I noticed that when changing the user rankings via phpMyAdmin. But I will not be doing that when in production mode, so I won't worry about that. And I don't want it to perform a user quarry on every request (not worth it).
Also note, it is possible that you save the whole user AR object into state. However, you need to make sure the data can be properly unserialized and it doesn't contain sensitive information like password.
Really? That's interesting… I will keep that in mind if I need to have many more persistent attributes.
I mostly wanted to know if you approved of the way I was doing that and that is was not more of a hack. (I wasn't sure if CWebUser was meant to be extended either). Thanks!
Well, the rank could be changed by an admin user of the application, not necessarily through phpmyadmin. This is quite normal in production mode, assuming the application provides a way to change rank.
Yes, CWebUser can also be extended. As a matter of fact, you can override any application component if needed.