$rows = db_execute_all("SELECT $project_users_table.project_id, $project_users_table.role_id, $project_users_table.permissions, $projects_table.leader_id FROM $project_users_table, $projects_table WHERE $project_users_table.user_id = ? AND $project_users_table.project_id = $projects_table.id AND $projects_table.status IN (?)", $user->getId(), $project_statuses);// Administrators and Project Managers can see all projects
if($user->isAdministrator() || $user->isProjectManager()) {
$rows = db_execute_all("SELECT $projects_table.id AS project_id FROM $projects_table WHERE $projects_table.status IN (?)", $project_statuses);
} else {
$rows = db_execute_all("SELECT $project_users_table.project_id, $project_users_table.role_id, $project_users_table.permissions, $projects_table.leader_id FROM $project_users_table, $projects_table WHERE $project_users_table.user_id = ? AND $project_users_table.project_id = $projects_table.id AND $projects_table.status IN (?)", $user->getId(), $project_statuses);
}
HOW TO enable any employee access to any project
The first step is to define just what an employee is and enable the system to detect this. The most obvious direction would be to just check if the user was created under the owner company. However, we decided to add an additional requirement: the user had to also be part of a system role with the can_see_private_objects permission enabled. This additional requirement meant we could still have contractors, temps, interns, etc. under the owner corp, but without giving them access to everything that a true employee had. (*)
Once you've got your requirements defined you can now create a new method in the User model class:
# User.class.php /** * Returns true if this user is member of owner company and an actual employee. * Employee status is based on whether their system role has the * can_see_private_objects permission enabled. This allows us to create non- * employee roles under the owner company, such as might be required for * an intern or contractor. * * @param void * @return boolean */ function isEmployee() { if($this->is_employee === null) { $this->is_employee = ($this->isOwner() && $this->canSeePrivate()); } // if return $this->is_employee; } // isEmployeeNow we can test any user object to see if it's an employee:
if ($user->isEmployee()) { ... }The next step is to decide what level of access you want all of your employees to have? By default, non-admin users have PROJECT_PERMISSION_NONE access to projects they aren't assigned to. The other available permissions are as follows:
[list]
[*]PROJECT_PERMISSION_ACCESS - employees will be able to view existing project objects, but not create any new ones (including timerecords)
[*]PROJECT_PERMISSION_CREATE - employees can create new project objects such as tickets, tasks and timerecords, but won't be able to edit them (including changing the status or completing them)
[*]PROJECT_PERMISSION_MANAGE - employees will have the same level of access as a project manager. They can create, complete and edit all project objects.
[/list]
Now we need to modify two files to make sure our employees can access any project object. (As you can see below, we decided to use the MANAGE permission, but just replace with whatever permission level you feel is appropriate.)
First, go back into your User model and alter the getProjectPermission function to the following:
# User.class.php function getProjectPermission($name, $project) { if($this->isAdministrator() || $this->isProjectManager() || $this->isProjectLeader($project)) { return PROJECT_PERMISSION_MANAGE; } elseif ($this->isEmployee()) { return PROJECT_PERMISSION_MANAGE; } else { $project_user = $this->getProjectUserInstance($project); return instance_of($project_user, 'ProjectUser') ? $project_user->getPermissionValue($name) : PROJECT_PERMISSION_NONE; } // if } // getProjectPermissionSecond, go into your ProjectUsers model and find the isProjectMember function. Change the following lines:
# ProjectUsers.class.php::isProjectMember if($user->isAdministrator() || $user->isProjectManager()) { $cache[$project_id][$user_id] = true; } else {To:
# ProjectUsers.class.php::isProjectMember if($user->isAdministrator() || $user->isProjectManager() || $user->isEmployee()) { $cache[$project_id][$user_id] = true; } else {And then.... That's it! Now any employee can access any project object without having to explicitly assign them!
Oh, there's one caveat: If a client clicks on the the name of an employee that's not explicitly assigned to one of their projects (such as if said employee leaves a comment or subscribes to an object) then they will get an HTTP_ERR_NOT_FOUND error message. You can handle this in one of two ways:
[list=1]
[*]Change it to a HTTP_ERR_FORBIDDEN error, which is more intuitive, though still not helpful
[*]Or, make sure any user can see any employee profile
[/list]
Either solution can be addressed by modifying the __construct function of the UsersController class. For the first approach, simply replace the former error code constant with the latter. For the second approach, modify the lines:
# UsersController.class.php if(!in_array($this->active_user->getId(), $this->logged_user->visibleUserIds())) { $this->httpError(HTTP_ERR_NOT_FOUND); } // ifTo:
# UsersController.class.php if(!$this->active_user->isEmployee() && !in_array($this->active_user->getId(), $this->logged_user->visibleUserIds())) { $this->httpError(HTTP_ERR_FORBIDDEN); } // ifAs you can see, we went with both solutions. (I believe the use of the original error code was just an oversight on the A51's end.)
And that is REALLY it!
Extras
So now that your application is employee-aware, you can start coding up features just for employees. Here are some of the things that we've done:
[list]
[*]Add a new checkbox to the assignment filter form that lets us override the default assignment filters for employees. (i.e. let employees see project objects from from across ALL projects. Handy for "unassigned" filters, so any employee can take any unassigned tickets)
[*]Show additional elements that only employees can see, such as a select box to change the status of a ticket when submitting a comment.
[*]Hide elements from non-employees, such as "complete" buttons (i.e. only employees can complete an object.)
[/list]
(*) You could also approach this by creating an new system permission such as "and_is_employee" which wouldn't limit you to users in the owner company, but we didn't have that requirement.