DataObjects/Core_watch.php
[Pman.Core] / DataObjects / Person.php
1 <?php
2 /**
3  * Table Definition for Person
4  */
5 require_once 'DB/DataObject.php';
6
7 class Pman_Core_DataObjects_Person extends DB_DataObject 
8 {
9     ###START_AUTOCODE
10     /* the code below is auto generated do not remove the above tag */
11
12     public $__table = 'Person';                          // table name
13     public $id;                              // int(11)  not_null primary_key auto_increment
14     public $email;                           // string(128)  not_null
15     
16     public $company_id;                      // int(11)  
17     public $office_id;                       // int(11)  
18     
19     public $name;                            // string(128)  not_null
20     public $firstname;                            // string(128)  not_null
21     public $lastname;                            // string(128)  not_null
22     public $phone;                           // string(32)  not_null
23     public $fax;                             // string(32)  not_null
24     
25     public $role;                            // string(32)  not_null
26     public $remarks;                         // blob(65535)  not_null blob
27     public $passwd;                          // string(64)  not_null
28     public $owner_id;                        // int(11)  not_null
29     public $lang;                            // string(8)  
30     public $no_reset_sent;                   // int(11)  
31     public $action_type;                     // string(32)  
32     public $project_id;                      // int(11)
33
34     
35     public $active;                          // int(11)  not_null
36     public $deleted_by;                      // int(11)  not_null
37     public $deleted_dt;                      // datetime(19)  binary
38
39     
40     /* the code above is auto generated do not remove the tag below */
41     ###END_AUTOCODE
42     /**
43      *
44      * Build an email to sent do user
45      *
46      * key 'args'
47      *
48      * no_auth => disable authentication check on
49      * templateDir => alternative template directory.
50      * HTTP_HOST
51      *
52      * expects mail/TMPLATE.txt (if .html exists, it will be the html body version)
53      * 
54      * @param {String} $templateFile  (mail/XXXXXXX.txt) exclude the mail and .txt bit.
55      * @param {Array|Object} $args   data to send out..
56      * @return {Array|PEAR_Error} array of $recipents, $header, $body 
57      */
58     function buildMail($templateFile, $args)
59     {
60           
61         $args = (array) $args;
62         $content  = clone($this);
63         
64         foreach((array)$args as $k=>$v) {
65             $content->$k = $v;
66         }
67         
68         $ff = HTML_FlexyFramework::get();
69         
70         
71         //?? is this really the place for this???
72         if (
73                 !$ff->cli && 
74                 empty($args['no_auth']) &&
75                 !in_array($templateFile, array(
76                     // templates that can be sent without authentication.
77                      'password_reset' ,
78                      'password_welcome'
79                  ))
80             ) {
81             
82             $content->authUser = $this->getAuthUser();
83             if (!$content->authUser) {
84                 return PEAR::raiseError("Not authenticated");
85             }
86         }
87         
88         // should handle x-forwarded...
89         
90         $content->HTTP_HOST = isset($_SERVER["HTTP_HOST"]) ?
91             $_SERVER["HTTP_HOST"] :
92             (isset($ff->HTTP_HOST) ? $ff->HTTP_HOST : 'localhost');
93             
94         /* use the regex compiler, as it doesnt parse <tags */
95         
96         $tops = array(
97             'compiler'    => 'Flexy',
98             'nonHTML' => true,
99             'filters' => array('SimpleTags','Mail'),
100             //     'debug'=>1,
101         );
102         
103         
104         
105         if (!empty($args['templateDir'])) {
106             $tops['templateDir'] = $args['templateDir'];
107         }
108         
109         
110         
111         require_once 'HTML/Template/Flexy.php';
112         $template = new HTML_Template_Flexy( $tops );
113         $template->compile("mail/$templateFile.txt");
114         
115         /* use variables from this object to ouput data. */
116         $mailtext = $template->bufferedOutputObject($content);
117         
118         $htmlbody = false;
119         // if a html file with the same name exists, use that as the body
120         // I've no idea where this code went, it was here before..
121         if (false !== $template->resolvePath ( "mail/$templateFile.html" )) {
122             $tops['nonHTML'] = false;
123             $template = new HTML_Template_Flexy( $tops );
124             $template->compile("mail/$templateFile.html");
125             $htmlbody = $template->bufferedOutputObject($content);
126             
127         }
128         
129         
130         
131         //echo "<PRE>";print_R($mailtext);
132         //print_R($mailtext);exit;
133         /* With the output try and send an email, using a few tricks in Mail_MimeDecode. */
134         require_once 'Mail/mimeDecode.php';
135         require_once 'Mail.php';
136         
137         $decoder = new Mail_mimeDecode($mailtext);
138         $parts = $decoder->getSendArray();
139         
140         if (PEAR::isError($parts)) {
141             return $parts;
142             //echo "PROBLEM: {$parts->message}";
143             //exit;
144         } 
145         list($recipents,$headers,$body) = $parts;
146         $recipents = array($this->email);
147         if (!empty($content->bcc) && is_array($content->bcc)) {
148             $recipents =array_merge($recipents, $content->bcc);
149         }
150         $headers['Date'] = date('r');
151         
152         if ($htmlbody !== false) {
153             require_once 'Mail/mime.php';
154             $mime = new Mail_mime(array('eol' => "\n"));
155             $mime->setTXTBody($body);
156             $mime->setHTMLBody($htmlbody);
157             // I think there might be code in mediaoutreach toEmail somewhere
158             // h embeds images here..
159             $body = $mime->get();
160             $headers = $mime->headers($headers);
161             
162         }
163         
164          
165         
166         return array(
167             'recipients' => $recipents,
168             'headers'    => $headers,
169             'body'      => $body
170         );
171         
172         
173     }
174     
175     
176     /**
177      * send a template
178      * - user must be authenticate or args[no_auth] = true
179      *   or template = password_[reset|welcome]
180      * 
181      */
182     function sendTemplate($templateFile, $args)
183     {
184         
185         $ar = $this->buildMail($templateFile, $args);
186       
187         
188         //print_r($recipents);exit;
189         $mailOptions = PEAR::getStaticProperty('Mail','options');
190         $mail = Mail::factory("SMTP",$mailOptions);
191         
192         if (PEAR::isError($mail)) {
193             return $mail;
194         } 
195         $oe = error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT);
196         $ret = $mail->send($ar['recipients'],$ar['headers'],$ar['body']);
197         error_reporting($oe);
198        
199         return $ret;
200     
201     }
202     
203   
204     
205     
206     function getEmailFrom()
207     {
208         return '"' . addslashes($this->name) . '" <' . $this->email . '>';
209     }
210     function toEventString() 
211     {
212         return empty($this->name) ? $this->email : $this->name;
213     } 
214     function verifyAuth()
215     { 
216         $ff= HTML_FlexyFramework::get();
217         if (!empty($ff->Pman['auth_comptype']) && $ff->Pman['auth_comptype'] != $this->company()->comptype) {
218             $ff->page->jerr("Login not permited to outside companies");
219         }
220         return true;
221         
222     }    
223    
224    
225     //   ---------------- authentication / passwords and keys stuff  ----------------
226     function isAuth()
227     {
228         $db = $this->getDatabaseConnection();
229         // we combine db + project names,
230         // otherwise if projects use different 'auth' objects
231         // then we get unserialize issues.
232         $sesPrefix = get_class($this) .'-'.$db->dsn['database'] ;
233         
234         
235         @session_start();
236         if (!empty($_SESSION[__CLASS__][$sesPrefix .'-auth'])) {
237             // in session...
238             $a = unserialize($_SESSION[__CLASS__][$sesPrefix .'-auth']);
239             
240             $u = DB_DataObject::factory('Person');
241             if ($u->get($a->id)) { //&& strlen($u->passwd)) {
242                 $u->verifyAuth();
243                 
244                 return true;
245             }
246             
247             $_SESSION[__CLASS__][$sesPrefix .'-auth'] = '';
248             
249         }
250         // local auth - 
251         $u = DB_DataObject::factory('Person');
252         $ff = HTML_FlexyFramework::get();
253         if (!empty($ff->Pman['local_autoauth']) && 
254             (!empty($_SERVER['SERVER_ADDR'])) &&
255             ($_SERVER['SERVER_ADDR'] == '127.0.0.1') &&
256             ($_SERVER['REMOTE_ADDR'] == '127.0.0.1') &&
257             $u->get('email', $ff->Pman['local_autoauth'])
258         ) {
259             $_SESSION[__CLASS__][$sesPrefix .'-auth'] = serialize($u);
260             return true;
261         }
262            
263         // http basic auth..
264         $u = DB_DataObject::factory('Person');
265
266         if (!empty($_SERVER['PHP_AUTH_USER']) 
267             &&
268             !empty($_SERVER['PHP_AUTH_PW'])
269             &&
270             $u->get('email', $_SERVER['PHP_AUTH_USER'])
271             &&
272             $u->checkPassword($_SERVER['PHP_AUTH_PW'])
273            ) {
274             $_SESSION[__CLASS__][$sesPrefix .'-auth'] = serialize($u);
275             return true; 
276         }
277         
278         
279         
280         
281         // not in session or not matched...
282         $u = DB_DataObject::factory('Person');
283         $u->whereAdd(' LENGTH(passwd) > 0');
284         $n = $u->count();
285         $error =  PEAR::getStaticProperty('DB_DataObject','lastError');
286         if ($error) {
287             die($error->toString()); // not really a good thing to do...
288         }
289         if (!$n){ // authenticated as there are no users in the system...
290             return true;
291         }
292         
293         return false;
294         
295     }
296     function getAuthUser()
297     {
298         if (!$this->isAuth()) {
299             return false;
300         }
301         $db = $this->getDatabaseConnection();
302         $sesPrefix = get_class($this) .'-'.$db->dsn['database'] ;
303         
304         if (!empty($_SESSION[__CLASS__][$sesPrefix .'-auth'])) {
305             $a = unserialize($_SESSION[__CLASS__][$sesPrefix .'-auth']);
306             
307             $u = DB_DataObject::factory('Person');
308             if ($u->get($a->id)) { /// && strlen($u->passwd)) {
309                 return clone($u);
310             }
311              
312         }
313         
314         $u = DB_DataObject::factory('Person');
315         $u->whereAdd(' LENGTH(passwd) > 0');
316         if (!$u->count()){
317             $u = DB_DataObject::factory('Person');
318             $u->id = -1;
319             return $u;
320             
321         }
322         return false;
323     }     
324     function login()
325     {
326         $this->isAuth(); // force session start..
327         $this->verifyAuth();
328         $db = $this->getDatabaseConnection();
329         // refresh admin group if we are logged in as one..
330         //DB_DataObject::debugLevel(1);
331         $g = DB_DataObject::factory('Groups');
332         $g->type = 0;
333         $g->get('name', 'Administrators');
334         $gm = DB_DataObject::Factory('group_members');
335         if (in_array($g->id,$gm->listGroupMembership($this))) {
336             // refresh admin groups.
337             $gr = DB_DataObject::Factory('group_rights');
338             $gr->applyDefs($g, 0);
339         }
340              
341         $sesPrefix = get_class($this) .'-'.$db->dsn['database'] ;
342         $_SESSION[__CLASS__][$sesPrefix .'-auth'] = serialize($this);
343         
344     }
345     function logout()
346     {
347         $this->isAuth(); // force session start..
348          $db = $this->getDatabaseConnection();
349         $sesPrefix = get_class($this) .'-'.$db->dsn['database'] ;
350         $_SESSION[__CLASS__][$sesPrefix .'-auth'] = "";
351         
352     }    
353     function genPassKey ($t) 
354     {
355         return md5($this->email . $t. $this->passwd);
356     }
357     function simpleAuthKey($m = 0)
358     {
359         $month = $m > -1 ? date('Y-m') : date('Y-m', strtotime('LAST MONTH'));
360         
361         return md5(implode(',' ,  array($month, $this->email , $this->passwd, $this->id)));
362     } 
363     function checkPassword($val)
364     {
365         
366         if (substr($this->passwd,0,1) == '$') {
367             return crypt($val,$this->passwd) == $this->passwd ;
368         }
369         // old style md5 passwords...- cant be used with courier....
370         return md5($val) == $this->passwd;
371     }
372     function setPassword($value) 
373     {
374         $salt='';
375         while(strlen($salt)<9) {
376             $salt.=chr(rand(64,126));
377             //php -r var_dump(crypt('testpassword', '$1$'. (rand(64,126)). '$'));
378         }
379         $this->passwd = crypt($value, '$1$'. $salt. '$');
380        
381        
382     }      
383     
384     function company()
385     {
386         $x = DB_DataObject::factory('Companies');
387         $x->get($this->company_id);
388         return $x;
389     }
390     function loadCompany()
391     {
392         $this->company = $this->company();
393     }
394     
395     function active()
396     { 
397         return $this->active;
398     }
399     function authUserName($n) // set username prior to acheck user exists query.
400     {
401         
402         $this->whereAdd('LENGTH(passwd) > 1'); 
403         $this->email = $n;
404     }
405     function lang($val)
406     {
407         if ($val == $this->lang) {
408             return;
409         }
410         $uu = clone($this);
411         $this->lang = $val;
412         $this->update($uu);
413
414     }
415             
416     
417     function authUserArray()
418     {
419         
420         $aur = $this->toArray();
421         
422         if ($this->id < 1) {
423             return $aur;
424         }
425         
426         
427         //DB_DataObject::debugLevel(1);
428         $c = DB_Dataobject::factory('Companies');
429         $im = DB_Dataobject::factory('Images');
430         $c->joinAdd($im, 'LEFT');
431         $c->selectAdd();
432         $c->selectAs($c, 'company_id_%s');
433         $c->selectAs($im, 'company_id_logo_id_%s');
434         $c->id = $this->company_id;
435         $c->limit(1);
436         $c->find(true);
437         
438         $aur = array_merge( $c->toArray(),$aur);
439         
440         if (empty($c->company_id_logo_id_id))  {
441                  
442             $im = DB_Dataobject::factory('Images');
443             $im->ontable = 'Companies';
444             $im->onid = $c->id;
445             $im->imgtype = 'LOGO';
446             $im->limit(1);
447             $im->selectAdd();
448             $im->selectAs($im,  'company_id_logo_id_%s');
449             if ($im->find(true)) {
450                     
451                 foreach($im->toArray() as $k=>$v) {
452                     $aur[$k] = $v;
453                 }
454             }
455         }
456       
457         // perms + groups.
458         $aur['perms']  = $this->getPerms();
459         $g = DB_DataObject::Factory('group_members');
460         $aur['groups']  = $g->listGroupMembership($this, 'name');
461         
462         $aur['passwd'] = '';
463         $aur['dailykey'] = '';
464         
465         
466         
467         return $aur;
468     }
469     
470     //   ----------PERMS------  ----------------
471     function getPerms() 
472     {
473          //DB_DataObject::debugLevel(1);
474         // find out all the groups they are a member of.. + Default..
475         
476         // ------ INIITIALIZE IF NO GROUPS ARE SET UP.
477         
478         $g = DB_DataObject::Factory('group_rights');
479         if (!$g->count()) {
480             $g->genDefault();
481         }
482         
483         if ($this->id < 0) {
484             return $g->adminRights(); // system is not set up - so they get full rights.
485         }
486         //DB_DataObject::debugLevel(1);
487         $g = DB_DataObject::Factory('group_members');
488         $g->whereAdd('group_id is NOT NULL AND user_id IS NOT NULL');
489         if (!$g->count()) {
490             // add the current user to the admin group..
491             $g = DB_DataObject::Factory('Groups');
492             if ($g->get('name', 'Administrators')) {
493                 $gm = DB_DataObject::Factory('group_members');
494                 $gm->group_id = $g->id;
495                 $gm->user_id = $this->id;
496                 $gm->insert();
497             }
498             
499         }
500         
501         // ------ STANDARD PERMISSION HANDLING.
502         $isOwner = $this->company()->comptype == 'OWNER';
503         $g = DB_DataObject::Factory('group_members');
504         $grps = $g->listGroupMembership($this);
505        //var_dump($grps);
506         $isAdmin = $g->inAdmin;
507         //echo '<PRE>'; print_r($grps);var_dump($isAdmin);
508         // the load all the perms for those groups, and add them all together..
509         // then load all those 
510         $g = DB_DataObject::Factory('group_rights');
511         $ret =  $g->listPermsFromGroupIds($grps, $isAdmin, $isOwner);
512         //echo '<PRE>';print_r($ret);
513         return $ret;
514          
515         
516     }
517     /**
518      *Basic group fetching - probably needs to filter by type eventually.
519      *
520      *@param String $what - fetchall() argument - eg. 'name' returns names of all groups that they are members of.
521      */
522     
523     function groups($what=false)
524     {
525         $g = DB_DataObject::Factory('group_members');
526         $grps = $g->listGroupMembership($this);
527         $g = DB_DataObject::Factory('Groups');
528         $g->whereAddIn('id', $grps, 'int');
529         return $g->fetchAll($what);
530         
531     }
532     
533     function hasPerm($name, $lvl) 
534     {
535         static $pcache = array();
536         
537         if (!isset($pcache[$this->id])) {
538             $pcache[$this->id] = $this->getPerms();
539         }
540        // echo "<PRE>";print_r($pcache[$au->id]);
541        // var_dump($pcache[$au->id]);
542         if (empty($pcache[$this->id][$name])) {
543             return false;
544         }
545         
546         return strpos($pcache[$this->id][$name], $lvl) > -1;
547         
548     }    
549     
550     //  ------------ROO HOOKS------------------------------------
551     function applyFilters($q, $au, $roo)
552     {
553         //DB_DataObject::DebugLevel(1);
554         if (!empty($q['query']['person_not_internal'])) {
555             $this->whereAdd(" join_company_id_id.isOwner = 0 ");
556         }
557         
558         
559         if (!empty($q['query']['person_internal_only_all'])) {
560             
561             
562             // must be internal and not current user (need for distribution list)
563             // user has a projectdirectory entry and role is not blank.
564             //DB_DataObject::DebugLevel(1);
565             $pd = DB_DataObject::factory('ProjectDirectory');
566             $pd->whereAdd("role != ''");
567             $pd->selectAdd();
568             $pd->selectAdd('distinct(person_id) as person_id');
569             $roled = $pd->fetchAll('person_id');
570             $rs = $roled  ? "  OR
571                     {$this->tableName()}.id IN (".implode(',', $roled) . ") 
572                     " : '';
573             $this->whereAdd(" join_company_id_id.comptype = 'OWNER' $rs ");
574             
575         }
576         // -- for distribution
577         if (!empty($q['query']['person_internal_only'])) {
578             // must be internal and not current user (need for distribution list)
579             $this->whereAdd(" join_company_id_id.comptype = 'OWNER'");
580             
581             //$this->whereAdd(($this->tableName() == 'Person' ? 'Person' : "join_person_id_id") .
582             //    ".id  != ".$au->id);
583             $this->whereAdd("Person.id != {$au->id}");
584         } 
585         
586         if (!empty($q['query']['comptype_or_company_id'])) {
587            // DB_DataObject::debugLevel(1);
588             $bits = explode(',', $q['query']['comptype_or_company_id']);
589             $id = (int) array_pop($bits);
590             $ct = $this->escape($bits[0]);
591             
592             $this->whereAdd(" join_company_id_id.comptype = '$ct' OR Person.company_id = $id");
593             
594         }
595         
596         
597         // staff list..
598         if (!empty($q['query']['person_inactive'])) {
599            // DB_Dataobject::debugLevel(1);
600             $this->active = 1;
601         }
602         $tn_p = $this->tableName();
603         $tn_gm = DB_DataObject::Factory('group_members')->tableName();
604         $tn_g = DB_DataObject::Factory('Groups')->tableName();
605
606         ///---------------- Group views --------
607         if (!empty($q['query']['in_group'])) {
608             // DB_DataObject::debugLevel(1);
609             $ing = (int) $q['query']['in_group'];
610             if ($q['query']['in_group'] == -1) {
611              
612                 // list all staff who are not in a group.
613                 $this->whereAdd("Person.id NOT IN (
614                     SELECT distinct(user_id) FROM $tn_gm LEFT JOIN
615                         $tn_g ON $tn_g.id = $tn_gm.group_id
616                         WHERE $tn_g.type = ".$q['query']['type']."
617                     )");
618                 
619                 
620             } else {
621                 
622                 $this->whereAdd("$tn_p.id IN (
623                     SELECT distinct(user_id) FROM $tn_gm
624                         WHERE group_id = $ing
625                     )");
626                }
627             
628         }
629         
630         if (!empty($q['query']['not_in_directory'])) { 
631             // it's a Person list..
632             // DB_DATaobjecT::debugLevel(1);
633             
634             // specific to project directory which is single comp. login
635             //
636             $owncomp = DB_DataObject::Factory('Companies');
637             $owncomp->get('comptype', 'OWNER');
638             if ($q['company_id'] == $owncomp->id) {
639                 $this->active =1;
640             }
641             
642             
643
644             if ( $q['query']['not_in_directory'] > -1) {
645                 $tn_pd = DB_DataObject::Factory('ProjectDirectory')->tableName();
646                 // can list current - so that it does not break!!!
647                 $this->whereAdd("$tn_p.id NOT IN 
648                     ( SELECT distinct person_id FROM $tn_pd WHERE
649                         project_id = " . $q['query']['not_in_directory'] . " AND 
650                         company_id = " . $this->company_id . ')');
651             }
652         }
653            
654         if (!empty($q['query']['role'])) { 
655             // it's a Person list..
656             // DB_DATaobjecT::debugLevel(1);
657             
658             // specific to project directory which is single comp. login
659             //
660             $tn_pd = DB_DataObject::Factory('ProjectDirectory')->tableName();
661                 // can list current - so that it does not break!!!
662             $this->whereAdd("$tn_p.id IN 
663                     ( SELECT distinct person_id FROM $tn_pd WHERE
664                         role = '". $this->escape($q['query']['role']) ."'
665             )");
666         
667         }
668         
669         
670         if (!empty($q['query']['project_member_of'])) {
671                // this is also a flag to return if they are a member..
672             //DB_DataObject::debugLevel(1);
673             $do = DB_DataObject::factory('ProjectDirectory');
674             $do->project_id = $q['query']['project_member_of'];
675             $tn_pd = DB_DataObject::Factory('ProjectDirectory')->tableName();
676             $this->joinAdd($do,array('joinType' => 'LEFT', 'useWhereAsOn' => true));
677             $this->selectAdd("IF($tn_pd.id IS NULL, 0,  $tn_pd.id )  as is_member");
678                 
679                 
680             if (!empty($q['query']['project_member_filter'])) {
681                 $this->having('is_member !=0');
682             
683             }
684             
685         }
686         
687         
688         if (!empty($q['query']['search'])) {
689             $s = $this->escape($q['query']['search']);
690                     $this->whereAdd("
691                         $tn_p.name LIKE '%$s%'  OR
692                         $tn_p.email LIKE '%$s%'  OR
693                         $tn_p.role LIKE '%$s%'  OR
694                         $tn_p.remarks LIKE '%$s%' 
695                         
696                     ");
697         }
698         
699         //
700     }
701     function setFromRoo($ar, $roo)
702     {
703         $this->setFrom($ar);
704         if (!empty($ar['passwd1'])) {
705             $this->setPassword($ar['passwd1']);
706         }
707         
708         
709         if (    $this->id &&
710                 ($this->email == $roo->old->email)&&
711                 ($this->company_id == $roo->old->company_id)
712             ) {
713             return true;
714         }
715         if (empty($this->email)) {
716             return true;
717         }
718         $xx = DB_Dataobject::factory('Person');
719         $xx->setFrom(array(
720             'email' => $this->email,
721            // 'company_id' => $x->company_id
722         ));
723         
724         if ($xx->count()) {
725             return "Duplicate Email found";
726         }
727         return true;
728     }
729     /**
730      *
731      * before Delete - delete significant dependancies..
732      * this is called after checkPerm..
733      */
734     
735     function beforeDelete()
736     {
737         
738         $e = DB_DataObject::Factory('Events');
739         $e->whereAdd('person_id = ' . $this->id);
740         $e->delete(true);
741         
742         // anything else?  
743         
744     }
745     
746     
747     /***
748      * Check if the a user has access to modify this item.
749      * @param String $lvl Level (eg. Core.Projects)
750      * @param Pman_Core_DataObjects_Person $au The authenticated user.
751      * @param boolean $changes alllow changes???
752      *
753      * @return false if no access..
754      */
755     function checkPerm($lvl, $au, $changes=false) //heck who is trying to access this. false == access denied..
756     {
757          
758        // do we have an empty system..
759         if ($au && $au->id == -1) {
760             return true;
761         }
762         
763         // determine if it's staff!!!
764          
765         if ($au->company()->comptype != 'OWNER') {
766             
767             // - can not change company!!!
768             if ($changes && 
769                 isset($changes['company_id']) && 
770                 $changes['company_id'] != $au->company_id) {
771                 return false;
772             }
773             // can only set new emails..
774             if ($changes && 
775                     !empty($this->email) && 
776                     isset($changes['email']) && 
777                     $changes['email'] != $this->email) {
778                 return false;
779             }
780             
781             // edit self... - what about other staff members...
782             
783             return $this->company_id == $au->company_id;
784         }
785          
786          
787         // yes, only owner company can mess with this...
788         $owncomp = DB_DataObject::Factory('Companies');
789         $owncomp->get('comptype', 'OWNER');
790         
791         $isStaff = ($this->company_id ==  $owncomp->id);
792         
793     
794         switch ($lvl) {
795             // extra case change passwod?
796             case 'P': //??? password
797                 // standard perms -- for editing + if the user is dowing them selves..
798                 $ret = $isStaff ? $au->hasPerm("Core.Staff", "E") : $au->hasPerm("Core.Person", "E");
799                 return $ret || $au->id == $this->id;
800             
801             default:                
802                 return $isStaff ? $au->hasPerm("Core.Staff", $lvl) : $au->hasPerm("Core.Person", $lvl);
803         
804         }
805         return false;
806     }
807     function onInsert($req, $roo)  
808     {
809         
810         if ($roo->authUser->id < 0) {
811             $g = DB_DataObject::factory('Groups');
812             $g->type = 0;
813             $g->get('name', 'Administrators');
814             
815             $p = DB_DataObject::factory('group_members');
816             $p->group_id = $g->id;
817             $p->user_id = $this->id;     
818             if (!$p->count()) {
819                 $p->insert();
820                 $roo->addEvent("ADD", $p, $g->toEventString(). " Added " . $this->toEventString());
821             }
822             $this->login();
823         }
824         if (!empty($req['project_id_addto'])) {
825             $pd = DB_DataObject::factory('ProjectDirectory');
826             $pd->project_id = $req['project_id_addto'];
827             $pd->person_id = $this->id; 
828             $pd->ispm =0;
829             $pd->office_id = $this->office_id;
830             $pd->company_id = $this->company_id;
831             $pd->insert();
832         }
833         
834     }
835  }