Page 1 of 1

rol to allow user to add, edit and delete own entry only

PostPosted: Mon Feb 16, 2009 12:11 pm
by mikewassil
Hi Steve,

I realize the answer to this question is likely buried in the forum and/or docs someplace. But I can't find it. Perhaps you could implement a more sophisticated search engine. I'd suggest Sphider http://www.sphider.eu/, it's easy to implement and easy to use and because it creates an index and searches the index does a really great job of finding stuff. Anyway, back to my question.

I'd like to modify the USER role such that it allows the user to view all entries, add new entries and edit/delete ONLY the entries added by the user. I've got a permissions.ini in my application directory and it appears to be functioning correctly, ie I can change something and see it take effect. My permissions.ini is just a copy of the permissions.ini in the Xataface directory, with a few minor changes I've attempted so far. Much appreciate your suggestions for what I need here. Thanks.

PostPosted: Mon Feb 16, 2009 1:46 pm
by shannah
Rather than duplicating the entire xataface permissions.ini file for your application, it is better to just override the permissions that you want to change in your application's permissions.ini file. E.g. if you want to override the USER role so that it cannot view records, you would:

Code: Select all
[USER extends USER]
    view=0


etc...

As far as the solution to your problem. You should create separate permissions.ini roles for each case. This can be confusing since we are using the term role to mean two different things:
1. A set of permissions in the permissions.ini file
2. A user's role with respect to the application (as stored in the users table).

You might create two roles:
USER DEFAULT : A role that provides permissions available to a user
USER OWNER : A role that provides permissions for the owner of a record.

Then your getPermissions() method might look something like:

Code: Select all
function getPermissions(&$record){
    // if this is the owner of the record then we give it the USER OWNER
    // permission
    $user = getUser(); // You created the getUser() function elsewhere
    if ( $record and $user and $user->val('role') == 'USER' and $user->val('user_id') == $record->val('owner_id') ){
        return Dataface_PermissionsTool::getRolePermissions('USER OWNER');
    }

    if ( $record and $user and $user->val('role') == 'USER' ){
        return Dataface_PermissionsTool::getRolePermissions('USER DEFAULT');
    }


    // Otherwise just use default permissions
    return null;
}


As for the search engines, I can look into sphider... I've tried quite a few things. Right now i just use a MySQL full-text index and it seems to work pretty well if you know the correct terms to look for. For example if you search for permissions or getPermissions or permissions.ini in this search it will come up with relevant documentation... Your question however is a little specific so it is hard for a search engine to come up with the answer based on just keywords....

PostPosted: Mon Feb 16, 2009 3:55 pm
by mikewassil
shannah wrote:As far as the solution to your problem. You should create separate permissions.ini roles for each case. This can be confusing since we are using the term role to mean two different things:
1. A set of permissions in the permissions.ini file
2. A user's role with respect to the application (as stored in the users table).

You might create two roles:
USER DEFAULT : A role that provides permissions available to a user
USER OWNER : A role that provides permissions for the owner of a record.

Then your getPermissions() method might look something like:

Code: Select all
function getPermissions(&$record){
    // if this is the owner of the record then we give it the USER OWNER
    // permission
    $user = getUser(); // You created the getUser() function elsewhere
    if ( $record and $user and $user->val('role') == 'USER' and $user->val('user_id') == $record->val('owner_id') ){
        return Dataface_PermissionsTool::getRolePermissions('USER OWNER');
    }
    if ( $record and $user and $user->val('role') == 'USER' ){
        return Dataface_PermissionsTool::getRolePermissions('USER DEFAULT');
    }
    // Otherwise just use default permissions
    return null;
}

Code: Select all
$user = getUser(); // You created the getUser() function elsewhere

Thanks, but you lose me here, I did not create "the getUser() function elsewhere" and consequently I'm getting this error:

Fatal error: Call to undefined function getuser()

I tried adding the following right above the function getPermissions(&$record):
Code: Select all
function getUser(){
    $auth =& Dataface_AuthenticationTool::getInstance();
    $user =& $auth->getLoggedInUser();
    if ( $user and $user->val('role') == 'ADMIN' ) return true;
    return false;
}

But it doesn't help, still get the same error (Fatal error: Call to undefined function getuser()) so I guess it or something similar has to go somewhere else.

I realize this is probably pretty simple stuff for you, but for me it's very complicated and confusing. I had similar issues a bit over a year ago when I attempted to implement authentication on another project and basically gave up on it then. At least now, I've got the basic authentication working OK, and I just need to get the permissions as I originally outlined. Am I the first person to ask about this type of permissions for a user? It seems this would be a fairly common requirement.

PostPosted: Mon Feb 16, 2009 6:14 pm
by shannah
Hi Mike,

Sorry for being unclear. The getUser() function is a mythical function that you might create (I usually create one for my apps) to get the current user. It would look similar to the one that you defined.

The reason that the one you defined can't be called as getUser() is because you defined it inside a class. Hence yours would be called as $this->getUser();

The idea is you just need to get the currently logged in user.... What I gave you was pseudo code.

-Steve

role to allow user to add, edit and delete own entry only

PostPosted: Tue Feb 17, 2009 1:50 pm
by mikewassil
Steve, thanks for your help with the authentication. I must admit I'm kinda overwhelmed by it all. Although what you've been trying to convey to me seems like it will be useful at some point, I'm just going to put it on hold for now.

Instead, it looks like "security filters" per the wiki http://www.xataface.com/documentation/how-to/security_filters will do what I need right now and I actually think I understand the php. Anyway, I've added the following to my class conf_ApplicationDelegate immediately after the function getPermissions(&$record):

Code: Select all
    function getPreferences(){
        $Records =& Dataface_Table::loadTable('Records') ; // load the table named 'Records'
        $auth =& Dataface_AuthenticationTool::getInstance();
        $user =& $auth->getLoggedInUser();
        if ( $user and  $user->val('rol') != 'ADMIN' ){
            // We apply the security filter to non admin users.
        $Records->setSecurityFilter(array('owner_id'=>$user->val('user_id')));
        }
    return array();  // Mandatory!! getPreferences() must return array.
    }

I get the login prompt normally, however, users other than role "ADMIN" still see all the records. I'm wondering if I've put this function in the wrong place or if I have to add some .ini file, or if I have to have a database field for "owner_id" or "user_id" and if so what kind of field and how does it get updated with the record?

PostPosted: Tue Feb 17, 2009 2:41 pm
by shannah
Well I don't think this stuff is over your head. If you're having difficulty it must be the way that I am explaining it.

Your strategy of using filters instead will work also. You can place this inside the getPreferences() method like you have.. or you could place it inside the init() method of the delegate class for the table that you want to filter.

e.g.

Code: Select all
class tables_Records {
    function init(&$table){
        if ( user is an administrator ){
            $table->setSecurityFilter(.....);
        }
    }
}



This method is actually preferable because it guarantees that the filter will be set as soon as the table is loaded. And it is more efficient because it won't load the table when it is unneeded.

PostPosted: Tue Feb 17, 2009 4:42 pm
by mikewassil
Steve,

You didn't advise as to why it's not working in the getPreferences() method as I'm using it. Do I need to add something to an .ini file or a database field? If I can get it working with getPreferences() I'll then try the init() method as you suggest. Thanks very much.

PostPosted: Tue Feb 17, 2009 8:13 pm
by shannah
There are many reasons why it might not be working. It's hard for me to say which it is. Here are some reasons:

1. You have defined the getPreferences() method outside the application delegate class.
2. The application delegate class is mis-named and not being picked up.
3. Your condition (if ( $user and $user->val('rol') != 'ADMIN' ){ ) is not evaluating to what you expected it to.
4. You were intending that the security filter should also apply to tables other than the 'Records' table.
...
something else I haven't thought of here.

-Steve