Is this the correct way of iterating through users and check if they have a determined permission? I'm developing a module where I need to retrieve all users of a website and check if they have a specific permission.

&lt;?php
$reviewers = array();

$result = db_query('SELECT uid, name FROM {users} ORDER BY uid');

while ($record = db_fetch_object($result)) {

    if ($record-&gt;uid != 0) {
        if (user_access('review article', user_load($record-&gt;uid), TRUE)) {

            $reviewers[$record-&gt;uid] = (string) $record-&gt;name . '@domain.com';

        }
    }   
}


I'm using this code and it works but it can become quite slow. I've tested in a site with 5.000 bogus users and it takes about 30 secs to complete.
That code works, but as you found out, it needs to load each user completely and is therefore very slow.

Unfortunately, the database schema of permissions/roles in D6 is really crappy. It stores all permissions of a role in a single role, separated with a comma.

But still, it should be possible to query that information directly. What you want to query is  which roles have a specific permission and then which users that have at least one of these roles.

Something like this:

db_query("SELECT u.uid, u.name FROM {users} u INNER JOIN {users_roles} ur ON u.uid = ur.uid INNER JOIN {permission} p ON p.rid = ur.rid WHERE p.perm LIKE '%s'", '%, $permission_name_here,%');


There are a few special cases where this doesn't work/needs additional checks:


uid 1 does have all permissions
all users automatically have the authenticated user role (rid 2) but that is not stored in the users_roles table. So if a permission could possibly be assigned to that role, then you need to explicitly check that and if yes, return all users.
It is possible to dynamically assign roles to users based on some conditions. In this case, the query won't work for that...