how use Acl to limit user access - cakephp

I have same login for 3 different type of users, admin/client/user, everyone has different layout and privileges but the issue is after login every one is able to access all pages. after a lot of search on Google and stack overflow i decided to use Acl. I created tables in database via right procedure recommended by Acl given here AccessControlList. I set permission in following way. But still all type of user are accessing all pages.
$this->Acl->allow(
array('model' => 'User', 'foreign_key' => 1),
'admins'
);
$this->Acl->allow(
array('model' => 'User', 'foreign_key' => 2),
'clients'
);
any help will be appreciated.

Related

How to set up HyperDB for WordPress website?

I have a large database which I want to split into several databases but connected to my WordPress site. I searched through internet and came to a solution of using HyperDB class which is provided by WordPress Codex. I downloaded the files and I tried like below
$wpdb->add_database(array(
'host' => 'localhost', // If port is other than 3306, use host:port.
'user' => 'root',
'password' => '',
'name' => 'partitioning',
));
/**
* This adds the same server again, only this time it is configured as a slave.
* The last three parameters are set to the defaults but are shown for clarity.
*/
$wpdb->add_database(array(
'host' => 'localhost', // If port is other than 3306, use host:port.
'user' => 'root',
'password' => '',
'name' => 'slave',
'write' => 0,
'read' => 1,
'dataset' => 'global',
'timeout' => 0.2,
));
I am using xampp for the development version. After WordPress site installation I put the db-config.php along with wp-config.php file directory and db.php in wp-content folder. Doing this I get the blank page.
Can any one elaborate the process step by step how to set up the database and HyperDB scripts? I mean how to make the slave database or HyperDB will automatically make the slave database? How can I split any table to slave database? The whole process I mean.
If you're building a high-volume Wordpress site, and the database is the bottleneck (as it often is), HyperDB is absolutely the correct Wordpress solution. HyperDB is authored by Automattic, is used on Wordpress.com, and is designed as a proper Wordpress drop-in.
HyperDB supports MySQL read-replicas and partitioning, and which you use depends on your use-case.
These configuration options are actually reasonably well documented in the HyperDB Config file, which looks like this:
https://plugins.trac.wordpress.org/browser/hyperdb/trunk/db-config.php
This won't precisely work for your situation; you'll have to adjust this to fit your setup.
// This is the default database configuration
//
$wpdb->add_database(array(
'host' => 'localhost',
'user' => 'root',
'password' => '',
'name' => 'regular_db',
));
// This is your secondary database.
//
$wpdb->add_database(array(
'host' => 'localhost',
'user' => 'root',
'password' => '',
'name' => 'product_db',
'dataset' => 'products',
));
// This magic detects which database table is being read from/written to, and switches
// hyperdb connection based on that.
$wpdb->add_callback('my_db_product_detector');
function my_db_product_detector($query, $wpdb) {
// This makes the assumption that you've only got one relevant table, wp_products.
// Update this to whatever your table name(s) are.
if ( preg_match('^wp_products$', $wpdb->table) ) {
return 'products';
}
}
To begin with, to test that this works on your existing database, you should change product_db to regular_db, and go from there.
At this point, you have architectural decisions to make. If you simply want to reduce the size of your DB, then this now writes your products to a second DB. Alternatively, you might have a second database server entirely to share the load across different databases.
Creating a read replica is also worth considering, but that depends on what ecosystem you're working with. If you're using AWS, then RDS will create read replicas quite simply.

Multiple sessions for different instances of Cakephp in the same domain

Did you know that if you run multiple instances of the same application in Cakephp in the same domain, they will share the same Session? For example, suppose you have instances running at:
www.example.com/instance1 and www.example.com/instance2
If you login in the first instance and access instance2, you’ll see that you will already be logged in. This happens because Cakephp, per default, uses the PHP Session storage mechanism.
If this is not the behaviour you expect, Cakephp allows you to choose from three options for the Session handling method: php (default), cake and database. The current method is stored in the Session.save variable in app/config/core.php.
Changing the method from php to cake will make Cakephp store the Session variables in the app/tmp/sessions directory. If you do it, remember to create and give the appropriate permissions to this directory.
Voilá, that’s all you need to do have separate Sessions for each of your Cakephp instances.
Please open the core.php & change the application cookie path then session will be store according to application cookie path
For www.example.com/instance1
Configure::write('Session', array(
'defaults' => 'database',
'ini' => array(
'session.cookie_path' => '/instance1',
),
'cookie' => 'instance1',
'cookieTimeout' => 0,
'checkAgent' => false
));
For www.example.com/instance2
Configure::write('Session', array(
'defaults' => 'database',
'ini' => array(
'session.cookie_path' => '/instance2',
),
'cookie' => 'instance2',
'cookieTimeout' => 0,
'checkAgent' => false
));

Custom non-username/password based login with CakePHP

The jist of this question is about how to override CakePHP's auth component login function to log a user in based on something other than the default username and password.
So, we're developing a custom login function for one of our partners. Basically, the solution provides online courses to a number of companies who want to provide their clients and/or employees with in house training material.
This particular solution takes a home loan account number and personal identification number and does some algorithm validation and logs the user in. Or at least - that's what it should do.
Currently, the auth component tries to user a particular model to compare username and hashed password. Is there anyway to override this particular behaviour and get the Authcomponent to log the user in using the algorithm (glorified regex check) in a custom function? It should completely ignore the need for a username and password. In addition we won't actually have these account numbers and ID numbers stored anywhere. They will each be checked for certain related patterns.
Cheers
Custom your login with authenticate property :
In your appController
public $components = array(
'Session',
'Auth' => array(
'authError' => "You don't have accès",
'authorize' => array('Controller'),
authenticate' => array(
'Form' => array('userModel' => 'MyUserModel',
'fields' => array('username' => 'numberuser','password' => 'personnalId'),
)
)
);

logged in user can access data of other users

Please bear with me, as I'm a programming/cakephp noob, but I do not know how to restrict the user from access to other user data. When a user logs in, they get a dashboard of their listings (which come from several models....restaurants, hotels, golf courses, images for each listing, location information, coupons, etc..).
Depending on the model/controller, I could have user '3' (who has hotel listings) type into the browser bar /restaurants/edit/1 and edit the restaurant information of user '17' who has a restaurant with ID='1'. Worse, they can even access /users/dashboard/17. How do I limit a user to only access their own data? I was hoping there was some sort of 'beforeAllow()' part of the AuthComponent I could use in the AppController that checks user id beforehand and kicks them back out to their dashboard if they try to perform a CRUD action on other users' data.
Even if I was using ACL (I know I should but it's frankly a little too over my head at this stage of learning), I'd still have to know the right code to limit user access, correct?
Below is my AppController:
class AppController extends Controller {
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'users', 'action' => 'view'),
'logoutRedirect' => array('controller' => 'docs', 'action' => 'index'),
'authError' => 'Sorry, you are not authorized to view this page.'
)
);
function beforeFilter() {
$this->Auth->userModel = 'User';
$this->Auth->allow('join_now','debug','index', 'condos', 'houses', 'hotels_and_motels', 'print_all_coupons', 'print_coupon', 'search', 'golf', 'charters', 'events', 'nightlife', 'shopping', 'visitors_info', 'contact_us', 'view', 'results');
}
}
and here is a sample edit function (the edit function from my UnitsController):
function edit($id) {
$this->set('title', 'Edit your property');
$this->Unit->id = $id;
if (empty($this->request->data)) {
$this->request->data = $this->Unit->read();
} else {
if ($this->Unit->saveAll($this->request->data)) {
$this->Session->setFlash('Your property has been updated.', 'success');
}
}
}
I will say that every one of my db tables has a user_id field so the logged in user can be matched with the user_id of each model.
I thought that this SO question was what I was looking for but they ended up getting off on a tangent in it and never answered the original question the user asked.
If you where using cakes acl and auth, then no, you wouldn't have to write a bunch of code, checking the user ids for each action, but you'd have to write the code to tie together the acl's. You'd tell the Component that your controller and actions require acl privelages. And it doesnt the look ups in the aros and acos tables to make sure that your object requesting the content has the proper permissions.
I HIGHLY recommend you take a look at the tutorial and figure out how to get it to work
If you don't go that route, then you will have to add in the checking to every action that loads dependent content. Basically you'll, when a action is requested, you'll feature the object, then get the user associated to that object and check to see if the id of the user the same as the id as the requesting the object.
if ( $this->Unit->User->uid != $this->Session->User->uid ) {
throw new NotFoundException('Could not find that Unit');
} else {
...
}
The other thing you can do, for pages that are the same, but customized, is not use the url /user/dashboard/17 and instead just use /user/dashboard then in the dashboard action, pull the user id from the session data and load the profile for the user that is authenticated
I think you will need to use CRUD authorization for adding EditOwn actions. The answer described in CakePHP ACL Database Setup: ARO / ACO structure? handles much of the logic that you need.
Please note that the solution is still not complete and you will get access to actions that can render other users' data. Example: scaffold 'index' methods. To restrict access to other users' data here, you can modify the query to add filters based on User ID that you get from Session.

How to: CakePHP logging in without password?

I'm trying to find a way to log in user without password.
The reason is that I have phpBB3 forums in my site and the users already log in there. So I'm now building an expansion to the site to have more than just the forum (Using CakePHP). I thought that I could attach automatic account creation to CakePHP when user creates an account to forums (And ofcourse other link for the existing users). So the users would get CakePHP account that has the same username that they have registered in forums. That means that the only way to register to CakePHP part of the site would be to register to the forums first.
Now I'd like to handle the whole logging thing by phpBB3 login so users would still login to forums, and then I'd attach a piece of code that would also login them to CakePHP part of the site with the username they used to login to forums.
This way I could do also put users to their own ACL groups by their status in forums.
Thats what I'm after and I need to know the way to login users this way. I'm not looking for complete code I'm just looking for an answer that explains how I log in users in CakePHP without them having passwords at all.
I have also looked http://bakery.cakephp.org/articles/wilsonsheldon/2009/01/13/phpbb3-api-bridge but it just doesn't quite look what I'm looking for...
As far as I recall, Auth requires two pieces of info for a login.
You can change which fields in the users table are checked by auth with.
$Auth->fields = array(
'username' => 'username',
'password' => 'password'
);
So if you you want to be able to log in users according to their nickname and shoesize:
$Auth->fields = array(
'username' => 'nickname',
'password' => 'shoesize'
);
IMPORTANT:
The AuthComponent expects the password value stored in the database to be hashed instead of being stored in plaintext.
(I think it is a sha1 of the password and Security.salt)
In the above example, if any entries already existed in the database you'd have to overwrite the shoesize field for each of them with hashed versions of the shoesizes.
To generate a hashed password yourself you can use $Auth->password('A Password');
Quick and Dirty
If you fill the password fields in your users table with the return value of:
$Auth->password(null);
Then you can use the following:
$Auth->login(
array(
'User'=>array(
'username'=> USERNAME_FROM_PHPBB3,
'password'=>null
)
)
);
Less Quick and Dirty
When creating a new user.
Set the password field to the md5 hash of some random input.
$this->authUser[$this->User->alias][$Auth->fields['password']] = $Auth->password(md5(rand().rand()));
Use the Username from phpBB3 to retrieve the relevant record
from the users table in the database.
$this->authUser = $this->User->findByUsername( USERNAME_FROM_PHPBB3 );
If the query was successful Log in the user
if($this->authUser){
if($Auth->login($this->authUser)){
// Login Successful
}
}
From your cakephp app you can check if a user exist in the phpbb forums table and you can use the phpbb session to check if a user is logged in.
This function will solve your problem:
public function forceLogin($userName = NULL) {
$this->_setDefaults();
$this->User = ClassRegistry::init('User');
$this->User->recursive = 0;
$user = $this->User->findByUsername($userName);
if (!empty($user['User'])) {
$this->Session->renew();
$user['User']['id'] = null;
$user['User']['password'] = null;
$this->Session->write(self::$sessionKey, $user['User']);
}
return $this->loggedIn();
}

Resources