5 * Copyright 2004, GForge, LLC
6 * Copyright 2009-2010, Roland Mas
8 * This file is part of FusionForge.
10 * FusionForge is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published
12 * by the Free Software Foundation; either version 2 of the License,
13 * or (at your option) any later version.
15 * FusionForge is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with FusionForge; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 require_once $gfcommon.'include/rbac_texts.php' ;
27 require_once $gfcommon.'include/RBAC.php' ;
29 class Role extends RoleExplicit implements PFO_RoleExplicit {
37 * Role($group,$id) - CONSTRUCTOR.
39 * @param object The Group object.
40 * @param int The role_id.
42 function Role($Group, $role_id = false) {
45 if (!$Group || !is_object($Group) || $Group->isError()) {
49 if (!$Group || !is_object($Group) || $Group->isError()) {
50 $this->setError('Role::'.$Group->getErrorMessage());
54 $this->Group =& $Group;
56 $hook_params = array();
57 $hook_params['role'] =& $this;
58 plugin_hook("role_get", $hook_params);
60 if (isset ($GLOBALS['default_roles'])) {
61 $this->defaults = array_merge_recursive($this->defaults,
62 $GLOBALS['default_roles']);
63 foreach ($this->defaults as $k => $v) {
64 if (!array_key_exists($GLOBALS['default_roles'], $k)) {
65 unset($this->defaults[$k]);
71 //setting up an empty object
72 //probably going to call create()
75 return $this->fetchData($role_id);
79 * setName - set the name of this role.
81 * @param string The new name of this role.
82 * @return boolean True if updated OK
84 function setName($role_name) { // From the PFO spec
85 if ($role_name == '') {
86 $this->setError('Cannot set a role name to empty');
89 if ($this->getName() != stripslashes($role_name)) {
92 if ($this->Group == NULL) {
93 $res = db_query_params('SELECT role_name FROM pfo_role WHERE home_group_id IS NULL AND role_name=$1',
94 array(htmlspecialchars($role_name)));
95 if (db_numrows($res)) {
96 $this->setError('Cannot create a role with this name (already used)');
101 $res = db_query_params('SELECT role_name FROM pfo_role WHERE home_group_id=$1 AND role_name=$2',
102 array($this->Group->getID(), htmlspecialchars($role_name)));
103 if (db_numrows($res)) {
104 $this->setError('Cannot create a role with this name (already used)');
109 $res = db_query_params('UPDATE pfo_role SET role_name=$1 WHERE role_id=$2',
110 array(htmlspecialchars($role_name),
112 if (!$res || db_affected_rows($res) < 1) {
113 $this->setError('update::name::'.db_error());
118 // Check if role_name is not already used.
119 $res = db_query_params('SELECT role_name FROM role WHERE group_id=$1 AND role_name=$2',
120 array($this->Group->getID(), htmlspecialchars($role_name)));
121 if (db_numrows($res)) {
122 $this->setError('Cannot create a role with this name (already used)');
126 $res = db_query_params('UPDATE role SET role_name=$1 WHERE group_id=$2 AND role_id=$3',
127 array(htmlspecialchars($role_name),
128 $this->Group->getID(),
130 if (!$res || db_affected_rows($res) < 1) {
131 $this->setError('update::name::'.db_error());
140 * isPublic - is this role public (accessible from projects
141 * other than its home project)?
143 * @return boolean True if public
145 function isPublic() { // From the PFO spec
146 return $this->data_array['is_public'];
150 * setPublic - set the public flag for this role.
152 * @param boolean The new value of the flag.
153 * @return boolean True if updated OK
155 function setPublic($flag) { // From the PFO spec
156 $res = db_query_params('UPDATE pfo_role SET is_public=$1 WHERE role_id=$2',
157 array($flag?'true':'false',
159 if (!$res || db_affected_rows($res) < 1) {
160 $this->setError('update::is_public::'.db_error());
166 function getHomeProject() { // From the PFO spec
171 * create - create a new role in the database.
173 * @param string The name of the role.
174 * @param array A multi-dimensional array of data in this format: $data['section_name']['ref_id']=$val
175 * @return integer The id on success or false on failure.
177 function create($role_name,$data,$newproject=false) {
179 if ($this->Group == NULL) {
180 if (!forge_check_global_perm ('forge_admin')) {
181 $this->setPermissionDeniedError();
186 if (!forge_check_global_perm ('approve_projects')) {
187 $this->setPermissionDeniedError();
190 } elseif (!forge_check_perm ('project_admin', $this->Group->getID())) {
191 $this->setPermissionDeniedError();
194 if ($role_name == '') {
195 $this->setError('Cannot create a role with an empty name');
200 if ($this->Group == NULL) {
201 $res = db_query_params('SELECT role_name FROM pfo_role WHERE home_group_id IS NULL AND role_name=$1',
202 array (htmlspecialchars($role_name)));
203 if (db_numrows($res)) {
204 $this->setError('Cannot create a role with this name (already used)');
209 $res = db_query_params('SELECT role_name FROM pfo_role WHERE home_group_id=$1 AND role_name=$2',
210 array ($this->Group->getID(), htmlspecialchars($role_name)));
211 if (db_numrows($res)) {
212 $this->setError('Cannot create a role with this name (already used)');
218 if ($this->Group == NULL) {
219 $res = db_query_params ('INSERT INTO pfo_role (role_name) VALUES ($1)',
220 array (htmlspecialchars($role_name))) ;
222 $res = db_query_params ('INSERT INTO pfo_role (home_group_id, role_name) VALUES ($1, $2)',
223 array ($this->Group->getID(),
224 htmlspecialchars($role_name))) ;
227 $this->setError('create::'.db_error());
231 $role_id=db_insertid($res,'pfo_role','role_id');
233 $this->setError('create::db_insertid::'.db_error());
237 $this->data_array['role_id'] = $role_id ;
238 $this->data_array['role_name'] = $role_name ;
240 $this->update ($role_name, $data) ;
242 $this->normalizeData () ;
244 $perm =& $this->Group->getPermission ();
245 if (!$perm || !is_object($perm) || $perm->isError() || !$perm->isAdmin()) {
246 $this->setPermissionDeniedError();
250 // Check if role_name is not already used.
251 $res = db_query_params('SELECT role_name FROM role WHERE group_id=$1 AND role_name=$2',
252 array ($this->Group->getID(), htmlspecialchars($role_name)));
253 if (db_numrows($res)) {
254 $this->setError('Cannot create a role with this name (already used)');
259 $res = db_query_params ('INSERT INTO role (group_id, role_name) VALUES ($1, $2)',
260 array ($this->Group->getID(),
261 htmlspecialchars($role_name))) ;
263 $this->setError('create::'.db_error());
267 $role_id=db_insertid($res,'role','role_id');
269 $this->setError('create::db_insertid::'.db_error());
274 $arr1 = array_keys($data);
275 for ($i=0; $i<count($arr1); $i++) {
276 // array_values($Report->adjust_days)
277 $arr2 = array_keys($data[$arr1[$i]]);
278 for ($j=0; $j<count($arr2); $j++) {
279 $usection_name=$arr1[$i];
281 $uvalue=$data[$arr1[$i]][$arr2[$j]];
288 $res = db_query_params ('INSERT INTO role_setting (role_id,section_name,ref_id,value) VALUES ($1,$2,$3,$4)',
294 $this->setError('create::insertsetting::'.db_error());
301 if (!$this->fetchData($role_id)) {
309 function createDefault($name) {
310 if ($this->Group == NULL) {
311 return $this->create($name,array(),true);
314 if (array_key_exists ($name, $this->defaults)) {
315 $arr =& $this->defaults[$name];
319 $keys = array_keys($arr);
321 for ($i=0; $i<count($keys); $i++) {
323 if ($keys[$i] == 'forum') {
324 $res = db_query_params('SELECT group_forum_id FROM forum_group_list WHERE group_id=$1',
325 array($this->Group->getID()));
327 $this->setError('Error: Forum'.db_error());
330 for ($j=0; $j<db_numrows($res); $j++) {
331 $data[$keys[$i]][db_result($res,$j,'group_forum_id')]= $arr[$keys[$i]];
333 } elseif ($keys[$i] == 'pm') {
334 $res = db_query_params('SELECT group_project_id FROM project_group_list WHERE group_id=$1',
335 array($this->Group->getID()));
337 $this->setError('Error: TaskMgr'.db_error());
340 for ($j=0; $j<db_numrows($res); $j++) {
341 $data[$keys[$i]][db_result($res, $j, 'group_project_id')]= $arr[$keys[$i]];
343 } elseif ($keys[$i] == 'tracker') {
344 $res = db_query_params('SELECT group_artifact_id FROM artifact_group_list WHERE group_id=$1',
345 array($this->Group->getID()));
347 $this->setError('Error: Tracker'.db_error());
350 for ($j=0; $j<db_numrows($res); $j++) {
351 $data[$keys[$i]][db_result($res, $j, 'group_artifact_id')]= $arr[$keys[$i]];
354 $data[$keys[$i]][0]= $arr[$keys[$i]];
358 return $this->create($name,$data,true);
362 * delete - delete a role in the database.
364 * @return boolean True on success or false on failure.
368 if ($this->Group == NULL) {
369 if (!forge_check_global_perm ('forge_admin')) {
370 $this->setPermissionDeniedError();
373 } elseif (!forge_check_perm('project_admin', $this->Group->getID())) {
374 $this->setPermissionDeniedError();
378 $res=db_query_params('SELECT user_id FROM pfo_user_role WHERE role_id=$1',
379 array($this->getID()));
381 if (db_numrows($res) > 0) {
382 $this->setError(_('Cannot remove a non empty role.'));
386 $res=db_query_params('DELETE FROM pfo_user_role WHERE role_id=$1',
387 array($this->getID())) ;
388 if (!$res || db_affected_rows($res) < 1) {
389 $this->setError('delete::name::'.db_error());
394 $res=db_query_params('DELETE FROM role_project_refs WHERE role_id=$1',
395 array($this->getID()));
396 if (!$res || db_affected_rows($res) < 1) {
397 $this->setError('delete::name::'.db_error());
402 $res=db_query_params('DELETE FROM pfo_role_setting WHERE role_id=$1',
403 array($this->getID()));
404 if (!$res || db_affected_rows($res) < 1) {
405 $this->setError('delete::name::'.db_error());
410 $res=db_query_params('DELETE FROM pfo_role WHERE role_id=$1',
411 array($this->getID()));
412 if (!$res || db_affected_rows($res) < 1) {
413 $this->setError('delete::name::'.db_error());
418 if (!is_numeric($this->getID())) {
419 $this->setError('Role::delete() role_id is not an integer');
423 // Cannot delete role_id=1
424 if ($this->getID() == 1) {
425 $this->setError(_('Cannot Delete Default Role.'));
428 $perm =& $this->Group->getPermission();
429 if (!$perm || !is_object($perm) || $perm->isError() || !$perm->isAdmin()) {
430 $this->setPermissionDeniedError();
434 $res=db_query_params('SELECT user_id FROM user_group WHERE role_id=$1',
435 array($this->getID()));
437 if (db_numrows($res) > 0) {
438 $this->setError(_('Cannot remove a non empty role.'));
444 $res=db_query_params('DELETE FROM role WHERE group_id=$1 AND role_id=$2',
445 array($this->Group->getID(), $this->getID()));
446 if (!$res || db_affected_rows($res) < 1) {
447 $this->setError('delete::name::'.db_error());
462 * @return boolean True on success or false on failure.
464 function setUser($user_id) {
467 if ($this->Group == NULL) {
468 if (!forge_check_global_perm ('forge_admin')) {
469 $this->setPermissionDeniedError();
472 } elseif (!forge_check_perm ('project_admin', $this->Group->getID())) {
473 $this->setPermissionDeniedError();
477 return $this->addUser (user_get_object($user_id)) ;
479 $perm =& $this->Group->getPermission ();
480 if (!$perm || !is_object($perm) || $perm->isError() || !$perm->isAdmin()) {
481 $this->setPermissionDeniedError();
487 // See if role is actually changing
489 $res = db_query_params('SELECT role_id FROM user_group WHERE user_id=$1 AND group_id=$2',
491 $this->Group->getID()));
492 $old_roleid=db_result($res,0,0);
493 if ($this->getID() == $old_roleid) {
498 // Get the old role so we can compare new values to old
500 $oldrole= new Role($this->Group, $old_roleid);
501 if (!$oldrole || !is_object($oldrole) || $oldrole->isError()) {
502 $this->setError($oldrole->getErrorMessage());
508 // Iterate each setting to see if it's changing
509 // If not, no sense updating it
511 $arr1 = array_keys($this->setting_array);
512 for ($i = 0; $i < count($arr1); $i++) {
513 // array_values($Report->adjust_days)
514 $arr2 = array_keys($this->setting_array[$arr1[$i]]);
515 for ($j=0; $j<count($arr2); $j++) {
516 $usection_name=$arr1[$i];
517 $uref_id = $arr2[$j];
518 $uvalue = $this->setting_array[$usection_name][$uref_id];
526 // See if this setting changed. If so, then update it
528 // if (($this->getVal($usection_name,$uref_id) != $oldrole->getVal($usection_name,$uref_id)) || ($old_roleid == 1)) {
529 if ($usection_name == 'frs') {
530 $update_usergroup=true;
531 } elseif ($usection_name == 'scm') {
532 //TODO - Shell should be separate flag
533 // If user acquired admin access to CVS,
534 // one to be given normal shell on CVS machine,
535 // else - restricted.
537 $cvs_flags=$this->getVal('scm',0);
538 $res2 = db_query_params ('UPDATE user_group SET cvs_flags=$1 WHERE user_id=$2 AND group_id=$3',
541 $this->Group->getID())) ;
543 $this->setError('update::scm::'.db_error());
547 // I have doubt the following is usefull
548 // This is probably buggy if used
550 if (!$SYS->sysUserSetAttribute($user_id,"debGforgeCvsShell","/bin/bash")) {
551 $this->setError($SYS->getErrorMessage());
556 if (!$SYS->sysUserSetAttribute($user_id,"debGforgeCvsShell","/bin/cvssh")) {
557 $this->setError($SYS->getErrorMessage());
564 // If user acquired at least commit access to CVS,
565 // one to be promoted to CVS group, else, demoted.
566 // When we add the user we also check he has a shell as a group member
567 // When we remove we only check for SCM (cvs_only=1)
570 if (!$SYS->sysGroupAddUser($this->Group->getID(),$user_id,0)) {
571 $this->setError($SYS->getErrorMessage());
576 if (!$SYS->sysGroupRemoveUser($this->Group->getID(),$user_id,1)) {
577 $this->setError($SYS->getErrorMessage());
583 } elseif ($usection_name == 'docman') {
584 $update_usergroup=true;
585 } elseif ($usection_name == 'forumadmin') {
586 $update_usergroup=true;
587 } elseif ($usection_name == 'trackeradmin') {
588 $update_usergroup=true;
589 } elseif ($usection_name == 'projectadmin') {
590 $update_usergroup=true;
591 } elseif ($usection_name == 'pmadmin') {
592 $update_usergroup=true;
597 // if ($update_usergroup) {
598 $res = db_query_params ('UPDATE user_group
607 WHERE user_id=$9 AND group_id=$10',
608 array($this->getVal('projectadmin', 0),
609 $this->getVal('forumadmin', 0),
610 $this->getVal('pmadmin', 0),
611 $this->getVal('docman', 0),
612 $this->getVal('scm', 0),
613 $this->getVal('frs', 0),
614 $this->getVal('trackeradmin', 0),
617 $this->Group->getID()));
619 $this->setError('::update::usergroup::'.db_error());
626 $hook_params = array();
627 $hook_params['role'] =& $this;
628 $hook_params['role_id'] = $this->getID();
629 $hook_params['user_id'] = $user_id;
630 plugin_hook("role_setuser", $hook_params);
642 // c-file-style: "bsd"