0013342: allow to configure default user/admin role names
[tine20] / tine20 / Setup / Frontend / Cli.php
1 <?php
2 /**
3  * Tine 2.0
4  * @package     Tinebase
5  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
6  * @author      Philipp Schüle <p.schuele@metaways.de>
7  * @copyright   Copyright (c) 2008-2012 Metaways Infosystems GmbH (http://www.metaways.de)
8  * 
9  * @todo        add ext check again
10  */
11
12 /**
13  * cli server
14  *
15  * This class handles all requests from cli scripts
16  *
17  * @package     Tinebase
18  *
19  * TODO extend TFCliAbstract
20  */
21 class Setup_Frontend_Cli
22 {
23     /**
24      * the internal name of the application
25      *
26      * @var string
27      */
28     protected $_appname = 'Setup';
29
30     /**
31      * authentication
32      *
33      * @param string $_username
34      * @param string $_password
35      * 
36      * @return boolean
37      */
38     public function authenticate($_username, $_password)
39     {
40         return false;
41     }
42     
43     /**
44      * handle request (call -ApplicationName-_Cli.-MethodName- or -ApplicationName-_Cli.getHelp)
45      *
46      * @param Zend_Console_Getopt $_opts
47      * @param boolean $exitAfterHandle
48      * @return void
49      */
50     public function handle(Zend_Console_Getopt $_opts, $exitAfterHandle = true)
51     {
52         // always set real setup user if Tinebase is installed
53         if (Setup_Controller::getInstance()->isInstalled('Tinebase')) {
54             $setupUser = Setup_Update_Abstract::getSetupFromConfigOrCreateOnTheFly();
55             if (!Setup_Core::getUser() instanceof Tinebase_Model_User) {
56                 Setup_Core::set(Tinebase_Core::USER, $setupUser);
57             }
58         } else {
59             Setup_Core::set(Setup_Core::USER, 'setupuser');
60         }
61
62         $result = 0;
63         if (isset($_opts->install)) {
64             $result = $this->_install($_opts);
65         } elseif(isset($_opts->update)) {
66             $result = $this->_update($_opts);
67         } elseif(isset($_opts->uninstall)) {
68             $this->_uninstall($_opts);
69         } elseif(isset($_opts->install_dump)) {
70             $this->_installDump($_opts);
71         } elseif(isset($_opts->list)) {
72             $result = $this->_listInstalled();
73         } elseif(isset($_opts->sync_accounts_from_ldap)) {
74             $this->_importAccounts($_opts);
75         } elseif(isset($_opts->sync_passwords_from_ldap)) {
76             $this->_syncPasswords($_opts);
77         } elseif(isset($_opts->egw14import)) {
78             $this->_egw14Import($_opts);
79         } elseif(isset($_opts->check_requirements)) {
80             $this->_checkRequirements($_opts);
81         } elseif(isset($_opts->setconfig)) {
82             $this->_setConfig($_opts);
83         } elseif(isset($_opts->create_admin)) {
84             $this->_createAdminUser($_opts);
85         } elseif(isset($_opts->getconfig)) {
86             $this->_getConfig($_opts);
87         } elseif(isset($_opts->reset_demodata)) {
88             $this->_resetDemodata($_opts);
89         } elseif(isset($_opts->updateAllImportExportDefinitions)) {
90             $this->_updateAllImportExportDefinitions($_opts);
91         } elseif(isset($_opts->backup)) {
92             $this->_backup($_opts);
93         } elseif(isset($_opts->restore)) {
94             $this->_restore($_opts);
95         } elseif(isset($_opts->compare)) {
96             $this->_compare($_opts);
97         } elseif(isset($_opts->setpassword)) {
98             $this->_setPassword($_opts);
99         }
100         
101         if ($exitAfterHandle) {
102             exit($result);
103         }
104     }
105     
106     /**
107      * install new applications
108      *
109      * @param Zend_Console_Getopt $_opts
110      * @return integer
111      */
112     protected function _install(Zend_Console_Getopt $_opts)
113     {
114         $controller = Setup_Controller::getInstance();
115
116         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
117
118         if ($_opts->install === true) {
119             if (Setup_Controller::getInstance()->isInstalled('Tinebase')) {
120                 // nothing to do
121                 return 0;
122             }
123             $applications = $controller->getInstallableApplications();
124             $applications = array_keys($applications);
125         } else {
126             $applications = array();
127             $applicationNames = explode(',', $_opts->install);
128             if (count($applicationNames) === 1 && strtolower($applicationNames[0]) === 'all') {
129                 $applications = $controller->getInstallableApplications();
130                 $applications = array_keys($applications);
131             } else {
132                 foreach ($applicationNames as $applicationName) {
133                     $applicationName = ucfirst(trim($applicationName));
134                     try {
135                         $controller->getSetupXml($applicationName);
136                         $applications[] = $applicationName;
137                     } catch (Setup_Exception_NotFound $e) {
138                         echo "Application $applicationName not found! Skipped...\n";
139                     }
140                 }
141             }
142         }
143
144         $this->_promptRemainingOptions($applications, $options);
145         $controller->installApplications($applications, $options);
146         
147         if ((isset($options['acceptedTermsVersion']) || array_key_exists('acceptedTermsVersion', $options))) {
148             Setup_Controller::getInstance()->saveAcceptedTerms($options['acceptedTermsVersion']);
149         }
150         
151         echo "Successfully installed " . count($applications) . " applications.\n";
152         return 0;
153     }
154
155     /**
156      * prompt remaining options
157      * 
158      * @param array $_applications
159      * @param array $_options
160      * @return void
161      * 
162      * @todo add required version server side
163      */
164     protected function _promptRemainingOptions($_applications, &$_options)
165     {
166         if (in_array('Tinebase', $_applications)) {
167             
168             if (! isset($_options['acceptedTermsVersion'])) {
169                 fwrite(STDOUT, PHP_EOL . file_get_contents(dirname(dirname(dirname(__FILE__))) . '/LICENSE' ));
170                 $licenseAnswer = Tinebase_Server_Cli::promptInput('I have read the license agreement and accept it (type "yes" to accept)');
171                 
172                 
173                 fwrite(STDOUT, PHP_EOL . file_get_contents(dirname(dirname(dirname(__FILE__))) . '/PRIVACY' ));
174                 $privacyAnswer = Tinebase_Server_Cli::promptInput('I have read the privacy agreement and accept it (type "yes" to accept)');
175             
176                 if (! (strtoupper($licenseAnswer) == 'YES' && strtoupper($privacyAnswer) == 'YES')) {
177                     echo "error: you need to accept the terms! exiting \n";
178                     exit (1);
179                 }
180                 
181                 $_options['acceptedTermsVersion'] = 1;
182             }
183             
184             
185             // initial username
186             if (! isset($_options['adminLoginName'])) {
187                 $_options['adminLoginName'] = Tinebase_Server_Cli::promptInput('Inital Admin Users Username');
188                 if (! $_options['adminLoginName']) {
189                     echo "error: username must be given! exiting \n";
190                     exit (1);
191                 }
192             }
193             
194             // initial password / can be empty => will trigger password change dialogue
195             if (! array_key_exists('adminPassword', $_options)) {
196                 $_options['adminPassword'] = $this->_promptPassword();
197             }
198         }
199     }
200     
201     /**
202      * prompt password
203      * 
204      * @return string
205      */
206     protected function _promptPassword()
207     {
208         $password1 = Tinebase_Server_Cli::promptInput('Admin user password', TRUE);
209         if (! $password1) {
210             echo "Error: Password must not be empty! Exiting ... \n";
211             exit (1);
212         }
213         $password2 = Tinebase_Server_Cli::promptInput('Confirm password', TRUE);
214         if ($password1 !== $password2) {
215             echo "Error: Passwords do not match! Exiting ... \n";
216             exit (1);
217         }
218         
219         return $password1;
220     }
221
222     /**
223      * set system user password
224      *
225      * @param Zend_Console_Getopt $_opts
226      * @return integer
227      */
228     protected function _setPassword(Zend_Console_Getopt $_opts)
229     {
230         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
231         if (empty($options['username']) || empty($options['password'])) {
232             echo "username and password parameters required\n";
233             return 2;
234         }
235
236         $username = $options['username'];
237         $password = $options['password'];
238         if (! in_array($username, Tinebase_User::getSystemUsernames(), /* strict */ true)) {
239             echo "it's only allowed to set system user passwords here\n";
240             return 2;
241         }
242
243         $user = Tinebase_User::getInstance()->getUserByLoginName($username);
244         Tinebase_User::getInstance()->setPassword($user, $password);
245         return 0;
246     }
247
248     /**
249      * update existing applications
250      *
251      * @param Zend_Console_Getopt $_opts
252      * @return integer
253      */
254     protected function _update(Zend_Console_Getopt $_opts)
255     {
256         $maxLoops = 50;
257         do {
258             $result = $this->_updateApplications();
259             if ($_opts->v && ! empty($result['messages'])) {
260                 echo "Messages:\n";
261                 foreach ($result['messages'] as $message) {
262                     echo "  " . $message . "\n";
263                 }
264             }
265             $maxLoops--;
266         } while ($result['updated'] > 0 && $maxLoops > 0);
267         
268         return ($maxLoops > 0) ? 0 : 1;
269     }
270     
271     /**
272      * update all applications
273      * 
274      * @return array
275      */
276     protected function _updateApplications()
277     {
278         $controller = Setup_Controller::getInstance();
279         $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
280         
281         foreach ($applications as $key => &$application) {
282             try {
283                 if (! $controller->updateNeeded($application)) {
284                     unset($applications[$key]);
285                 }
286             } catch (Setup_Exception_NotFound $e) {
287                 Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ 
288                     . ' Failed to check if an application needs an update:' . $e->getMessage());
289                 unset($applications[$key]);
290             }
291         }
292
293         $result = array();
294         if (count($applications) > 0) {
295             $result = $controller->updateApplications($applications);
296             echo "Updated " . $result['updated'] . " application(s).\n";
297         } else {
298             $result['updated'] = 0;
299         }
300         
301         return $result;
302     }
303
304     /**
305      * uninstall applications
306      *
307      * @param Zend_Console_Getopt $_opts
308      */
309     protected function _uninstall(Zend_Console_Getopt $_opts)
310     {
311         $controller = Setup_Controller::getInstance();
312         
313         if($_opts->uninstall === true) {
314             $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
315         } else {
316             $applications = new Tinebase_Record_RecordSet('Tinebase_Model_Application');
317             $applicationNames = explode(',', $_opts->uninstall);
318             foreach($applicationNames as $applicationName) {
319                 $applicationName = ucfirst(trim($applicationName));
320                 try {
321                     $application = Tinebase_Application::getInstance()->getApplicationByName($applicationName);
322                     $applications->addRecord($application);
323                 } catch (Tinebase_Exception_NotFound $e) {
324                 }
325             }
326         }
327         
328         $controller->uninstallApplications($applications->name);
329         
330         echo "Successfully uninstalled " . count($applications) . " applications.\n";
331     }
332     
333     /**
334      * reinstall applications
335      * and reset Demodata
336      * php setup.php --reset_demodata USERNAME
337      * 
338      * @param Zend_Console_Getopt $_opts
339      */
340     protected function _resetDemodata(Zend_Console_Getopt $_opts)
341     {
342         $controller = Setup_Controller::getInstance();
343         $userController = Admin_Controller_User::getInstance();
344         $containerController = Tinebase_Container::getInstance();
345         $cli = new Tinebase_Frontend_Cli();
346         
347         //Don't reset this applications
348         $fixedApplications = array('Tinebase', 'Admin', 'Addressbook');
349         
350         //Log in
351         $opts = $_opts->getRemainingArgs();
352         $username = $opts[0];
353         if (empty($username)) {
354             echo "Username is missing!\n";
355             exit;
356         }
357         $user = Tinebase_User::getInstance()->getUserByLoginName($username);
358         Tinebase_Core::set(Tinebase_Core::USER, $user);
359         
360         //get all applications and remove some
361         $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
362         
363         foreach ($applications as $key => &$application) {
364             if (in_array($application, $fixedApplications)) {
365                 unset($applications[$key]);
366             }
367         }
368         
369         //get set rights
370         $userRoleName = Tinebase_Config::getInstance()->get(Tinebase_Config::DEFAULT_USER_ROLE_NAME);
371         $users = Tinebase_Acl_Roles::getInstance()->getRoleByName($userRoleName);
372         $rights = Tinebase_Acl_Roles::getInstance()->getRoleRights($users->getId());
373         
374         //Uninstall Applications
375         try {
376             $controller->uninstallApplications($applications->name);
377             echo "Successfully uninstalled " . count($applications) . " applications.\n";
378         } catch (Tinebase_Exception_NotFound $e) {
379         }
380         //Install Applications
381         try {
382             $controller->installApplications($applications->name);
383             echo "Successfully installed " . count($applications) . " applications.\n";
384         } catch (Tinebase_Exception_NotFound $e) {
385         }
386         
387         //set rights
388         foreach ($applications as $app) {
389             $newApplicationId = Tinebase_Application::getInstance()->getApplicationByName($app->name)->getId();
390             
391             foreach ($rights as &$right) {
392                 if ($right['application_id'] == $app->id) {
393                     $right['application_id'] = $newApplicationId;
394                 }
395             }
396         }
397         
398         Tinebase_Acl_Roles::getInstance()->setRoleRights($users->getId(), $rights);
399         echo "Successfully restored user rights.\n";
400         
401         //Clean up addressbooks
402         $internalContacts = $userController->getDefaultInternalAddressbook();
403         $containers = $containerController->getAll();
404         foreach ($containers as $key => &$container) {
405             if ($container->id == $internalContacts) {
406                 // Do nothing
407             } else {
408                 try {
409                     $containerController->deleteContainer($container, true);
410                 } catch (Exception $e) {
411                 }
412             }
413         }
414         unset($containers);
415         echo "Successfully cleand up containers.\n";
416         
417         //remove state
418         $db = Tinebase_Core::getDb();
419         $statement = "TRUNCATE TABLE " . $db->quoteIdentifier(SQL_TABLE_PREFIX . 'state');
420         $db->query($statement);
421         echo "Successfully truncated state table.\n";
422         
423         //Get Demodata
424         $cli->createAllDemoData();
425         
426         //clear Cache
427         Tinebase_Core::getCache()->clean(Zend_Cache::CLEANING_MODE_ALL);
428         echo "Successfully cleared Cache.\n";
429         
430         echo "Every thing done!\n";
431     }
432
433     /**
434      * Update Import Export Definitions for all applications
435      */
436     protected function _updateAllImportExportDefinitions(Zend_Console_Getopt $_opts){
437
438         //get all applications
439         $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
440         foreach ($applications as $application) {
441             Setup_Controller::getInstance()->createImportExportDefinitions($application);
442             echo "Update definitions for " . $application->name . "...\n";
443         }
444     }
445     
446     /**
447      * list installed apps
448      */
449     protected function _listInstalled()
450     {
451         try {
452             $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
453         } catch (Zend_Db_Statement_Exception $e) {
454             echo "No applications installed\n";
455             return 1;
456         }
457         
458         echo "Currently installed applications:\n";
459         foreach($applications as $application) {
460             echo "* $application\n";
461         }
462         
463         return 0;
464     }
465     
466     /**
467      * import accounts from ldap
468      *
469      * @param Zend_Console_Getopt $_opts
470      */
471     protected function _importAccounts(Zend_Console_Getopt $_opts)
472     {
473         // disable timelimit during import of user accounts
474         Setup_Core::setExecutionLifeTime(0);
475         
476         // import groups
477         if (! $_opts->onlyusers) {
478             Tinebase_Group::syncGroups();
479         }
480         
481         // import users
482         $options = array('syncContactData' => TRUE);
483         if ($_opts->dbmailldap) {
484             $options['ldapplugins'] = array(
485                 new Tinebase_EmailUser_Imap_LdapDbmailSchema(),
486                 new Tinebase_EmailUser_Smtp_LdapDbmailSchema()
487             );
488         }
489
490         if ($_opts->syncdeletedusers) {
491             $options['deleteUsers'] = true;
492         }
493         if ($_opts->syncaccountstatus) {
494             $options['syncAccountStatus'] = true;
495         }
496         if ($_opts->syncontactphoto) {
497             $options['syncContactPhoto'] = true;
498         }
499
500         Tinebase_User::syncUsers($options);
501     }
502     
503     /**
504      * sync ldap passwords
505      * 
506      * @param Zend_Console_Getopt $_opts
507      */
508     protected function _syncPasswords(Zend_Console_Getopt $_opts)
509     {
510         Tinebase_User::syncLdapPasswords();
511     }
512     
513     /**
514      * import from egw14
515      * 
516      * @param Zend_Console_Getopt $_opts
517      */
518     protected function _egw14Import(Zend_Console_Getopt $_opts)
519     {
520         $args = $_opts->getRemainingArgs();
521         
522         if (count($args) < 1 || ! is_readable($args[0])) {
523             echo "can not open config file \n";
524             echo "see tine20.org/wiki/EGW_Migration_Howto for details \n\n";
525             echo "usage: ./setup.php --egw14import /path/to/config.ini (see Tinebase/Setup/Import/Egw14/config.ini)\n\n";
526             exit(1);
527         }
528         
529         try {
530             $config = new Zend_Config(array(), TRUE);
531             $config->merge(new Zend_Config_Ini($args[0]));
532             $config = $config->merge($config->all);
533         } catch (Zend_Config_Exception $e) {
534             fwrite(STDERR, "Error while parsing config file($args[0]) " .  $e->getMessage() . PHP_EOL);
535             exit(1);
536         }
537         
538         $writer = new Zend_Log_Writer_Stream('php://output');
539         $logger = new Zend_Log($writer);
540         
541         $filter = new Zend_Log_Filter_Priority((int) $config->loglevel);
542         $logger->addFilter($filter);
543         
544         $importer = new Tinebase_Setup_Import_Egw14($config, $logger);
545         $importer->import();
546     }
547     
548     /**
549      * do the environment check
550      *
551      * @return array
552      */
553     protected function _checkRequirements(Zend_Console_Getopt $_opts)
554     {
555         $results = Setup_Controller::getInstance()->checkRequirements();
556         if ($results['success']) {
557           echo "OK - All requirements are met\n";
558         } else {
559           echo "ERRORS - The following requirements are not met: \n";
560           foreach ($results['results'] as $result) {
561             if (!empty($result['message'])) {
562               echo "- " . strip_tags($result['message']) . "\n";
563             }
564           }
565         }
566     }
567     
568     /**
569      * set config
570      *
571      * @return array
572      */
573     protected function _setConfig(Zend_Console_Getopt $_opts)
574     {
575         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
576         $errors = array();
577         if (empty($options['configkey'])) {
578             $errors[] = 'Missing argument: configkey';
579         }
580         if (! isset($options['configvalue'])) {
581             $errors[] = 'Missing argument: configvalue';
582         }
583         $configKey = (string)$options['configkey'];
584         $configValue = self::parseConfigValue($options['configvalue']);
585         $applicationName = (isset($options['app'])) ? $options['app'] : 'Tinebase';
586
587         if (! Tinebase_Application::getInstance()->isInstalled('Tinebase') || ! Tinebase_Application::getInstance()->isInstalled($applicationName)) {
588             $errors[] = $applicationName . ' is not installed';
589         }
590         
591         if (empty($errors)) {
592            Setup_Controller::getInstance()->setConfigOption($configKey, $configValue, $applicationName);
593            echo "OK - Updated configuration option $configKey for application $applicationName\n";
594         } else {
595             echo "ERRORS - The following errors occured: \n";
596             foreach ($errors as $error) {
597                 echo "- " . $error . "\n";
598             }
599         }
600     }
601     
602     /**
603      * get config
604      *
605      */
606     protected function _getConfig(Zend_Console_Getopt $_opts)
607     {
608         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
609         $applicationName = (isset($options['app'])) ? $options['app'] : 'Tinebase';
610
611         $errors = array();
612         if (! Tinebase_Application::getInstance()->isInstalled('Tinebase') || ! Tinebase_Application::getInstance()->isInstalled($applicationName)) {
613             $errors[] = $applicationName . ' is not installed';
614             $config = null;
615         } else {
616             $config = Tinebase_Config_Abstract::factory($applicationName);
617         }
618
619         if (empty($options['configkey'])) {
620             $errors[] = 'Missing argument: configkey';
621             if ($config) {
622                 $errors[] = 'Available config settings:';
623                 $errors[] = print_r($config::getProperties(), true);
624             }
625         }
626         $configKey = (string)$options['configkey'];
627         
628         if (empty($errors)) {
629             $value = $config->get($configKey);
630             $value = is_string($value) ? $value : Zend_Json::encode($value);
631             echo $value . " \n";
632         } else {
633             echo "ERRORS - The following errors occured: \n";
634             foreach ($errors as $error) {
635                 echo "- " . $error . "\n";
636             }
637         }
638     }
639     
640     /**
641      * create admin user / activate existing user / allow to reset password
642      * 
643      * @param Zend_Console_Getopt $_opts
644      * 
645      * @todo check role by rights and not by name
646      * @todo replace echos with stdout logger
647      */
648     protected function _createAdminUser(Zend_Console_Getopt $_opts)
649     {
650         if (! Setup_Controller::getInstance()->isInstalled('Tinebase')) {
651             die('Install Tinebase first.');
652         }
653
654         echo "Please enter a username. An existing user is reactivated and you can reset the password.\n";
655         $username = strtolower(Tinebase_Server_Cli::promptInput('Username'));
656         $tomorrow = Tinebase_DateTime::now()->addDay(1);
657         
658         try {
659             $user = Tinebase_User::getInstance()->getFullUserByLoginName($username);
660             echo "User $username already exists.\n";
661             Tinebase_User::getInstance()->setStatus($user->getId(), Tinebase_Model_User::ACCOUNT_STATUS_ENABLED);
662             echo "Activated admin user '$username'.\n";
663             
664             $expire = Tinebase_Server_Cli::promptInput('Should the admin user expire tomorrow (default: "no", "y" or "yes" for expiry)?');
665             if ($expire === 'y' or $expire === 'yes') {
666                 Tinebase_User::getInstance()->setExpiryDate($user->getId(), $tomorrow);
667                 echo "User expires tomorrow at $tomorrow.\n";
668             }
669             
670             $resetPw = Tinebase_Server_Cli::promptInput('Do you want to reset the password (default: "no", "y" or "yes" for reset)?');
671             if ($resetPw === 'y' or $resetPw === 'yes') {
672                 $password = $this->_promptPassword();
673                 Tinebase_User::getInstance()->setPassword($user, $password);
674                 echo "User password has been reset.\n";
675             }
676
677             try {
678                 Tinebase_User::getInstance()->assertAdminGroupMembership($user);
679                 echo "Added user to default admin group\n";
680             } catch (Exception $e) {
681                 Tinebase_Exception::log($e);
682                 echo "Could not add user to default admin group: " . $e->getMessage();
683             }
684
685             $this->_checkAdminRole($user);
686             
687         } catch (Tinebase_Exception_NotFound $tenf) {
688             // create new admin user that expires tomorrow
689             $password = $this->_promptPassword();
690             Tinebase_User::createInitialAccounts(array(
691                 'adminLoginName' => $username,
692                 'adminPassword'  => $password,
693                 'expires'        => $tomorrow,
694             ));
695             echo "Created new admin user '$username' that expires tomorrow.\n";
696         }
697     }
698
699
700     /**
701      * check admin role membership
702      * 
703      * @param Tinebase_Model_FullUser $user
704      */
705     protected function _checkAdminRole($user)
706     {
707         $roleMemberships = Tinebase_Acl_Roles::getInstance()->getRoleMemberships($user->getId());
708         $adminRoleFound = FALSE;
709         // TODO allow to configure this / pass it as param
710         $adminRoleName = 'admin role';
711
712         foreach ($roleMemberships as $roleId) {
713             $role = Tinebase_Acl_Roles::getInstance()->getRoleById($roleId);
714             if ($role->name === $adminRoleName) {
715                 $adminRoleFound = TRUE;
716                 break;
717             }
718         }
719
720         if (! $adminRoleFound || ! Tinebase_Acl_Roles::getInstance()->hasRight('Admin', $user->getId(), Tinebase_Acl_Rights::ADMIN)) {
721             echo "Admin role not found for user " . $user->accountLoginName . ".\n";
722
723             try {
724                 $adminRole = Tinebase_Acl_Roles::getInstance()->getRoleByName($adminRoleName);
725             } catch (Tinebase_Exception_NotFound $tenf) {
726                 $adminRole = $this->_createNewAdminRoleForAdmin($adminRoleName);
727             }
728
729             Tinebase_Acl_Roles::getInstance()->setRoleMembers($adminRole->getId(), array(
730                 array(
731                     'id'    => $user->getId(),
732                     'type'  => Tinebase_Acl_Rights::ACCOUNT_TYPE_USER, 
733                 )
734             ));
735             
736             echo "Added user " . $user->accountLoginName . " to role '$adminRoleName''.\n";
737             // @todo clear roles/groups cache
738         }
739     }
740
741     protected function _createNewAdminRoleForAdmin($adminRoleName)
742     {
743         $adminRole = new Tinebase_Model_Role(array(
744             'name'                  => $adminRoleName,
745             'description'           => 'admin role for tine. this role has all rights per default.',
746         ));
747
748         $adminRole = Tinebase_Acl_Roles::getInstance()->createRole($adminRole);
749         // add all rights for all apps
750         $enabledApps = Tinebase_Application::getInstance()->getApplicationsByState(Tinebase_Application::ENABLED);
751         $roleRights = array();
752         foreach ($enabledApps as $application) {
753             $allRights = Tinebase_Application::getInstance()->getAllRights($application->getId());
754             foreach ($allRights as $right) {
755                 $roleRights[] = array(
756                     'application_id' => $application->getId(),
757                     'right'          => $right,
758                 );
759             }
760         }
761         Tinebase_Acl_Roles::getInstance()->setRoleRights($adminRole->getId(), $roleRights);
762
763         return $adminRole;
764     }
765
766     /**
767      * @param Zend_Console_Getopt $_opts
768      * @throws Exception
769      */
770     protected function _backup(Zend_Console_Getopt $_opts)
771     {
772         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
773         Setup_Controller::getInstance()->backup($options);
774     }
775
776     /**
777      * @param Zend_Console_Getopt $_opts
778      * @throws Exception
779      */
780     protected function _restore(Zend_Console_Getopt $_opts)
781     {
782         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
783         Setup_Controller::getInstance()->restore($options);
784     }
785
786     /**
787      * install tine20 from a dump (local dir or remote dir)
788      *
789      * @param Zend_Console_Getopt $_opts
790      */
791     protected function _installDump(Zend_Console_Getopt $_opts)
792     {
793         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
794         Setup_Controller::getInstance()->installFromDump($options);
795
796         return 0;
797     }
798
799     /**
800      * parse options
801      * 
802      * @param string $_value
803      * @return array|string
804      */
805     public static function parseConfigValue($_value)
806     {
807         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_value, TRUE));
808         
809         // check value is json encoded
810         if (Tinebase_Helper::is_json($_value)) {
811             return Zend_Json::decode($_value); 
812         }
813         
814         $result = array(
815             'active' => 1
816         );
817
818         // keep spaces, \: and \,
819         $_value = preg_replace(array('/ /', '/\\\:/', '/\\\,/', '/\s*/'), array('§', '@', ';', ''), $_value);
820         
821         $parts = explode(',', $_value);
822         
823         foreach ($parts as $part) {
824             $part = str_replace(';', ',', $part);
825             $part = str_replace('§', ' ', $part);
826             $part = str_replace('@', ':', $part);
827             if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $part);
828             if (strpos($part, '_') !== FALSE) {
829                 list($key, $sub) = preg_split('/_/', $part, 2);
830                 if (preg_match('/:/', $sub)) {
831                     list($subKey, $value) = explode(':', $sub);
832                     $result[$key][$subKey] = $value;
833                 } else {
834                     // might be a '_' in the value
835                     if (preg_match('/:/', $part)) {
836                         $exploded = explode(':', $part);
837                         $key = array_shift($exploded);
838                         $result[$key] = implode(':', $exploded);
839                     } else {
840                         throw new Timetracker_Exception_UnexpectedValue('You have an error in the config syntax (":" expected): ' . $part);
841                     }
842                 }
843             } else {
844                 if (strpos($part, ':') !== FALSE) {
845                     list($key, $value) = preg_split('/:/', $part, 2);
846                     $result[$key] = $value;
847                 } else {
848                     $result = $part;
849                 }
850             }
851         }
852
853         return $result;
854     }
855     
856     /**
857      * parse remaining args
858      * 
859      * @param string $_args
860      * @return array
861      */
862     protected function _parseRemainingArgs($_args)
863     {
864         $options = array();
865         foreach ($_args as $arg) {
866             if (strpos($arg, '=') !== FALSE) {
867                 if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $arg);
868                 list($key, $value) = preg_split('/=/', $arg, 2);
869                 $options[$key] = $value;
870             }
871         }
872         
873         return $options;
874     }
875
876     /**
877      * compare shema of two tine databases
878      *
879      * @param Zend_Console_Getopt $_opts
880      * @throws Exception
881      */
882     protected function _compare(Zend_Console_Getopt $_opts)
883     {
884         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
885         print_r(Setup_Controller::getInstance()->compareSchema($options));
886     }
887 }