diff options
Diffstat (limited to 'app/Console')
| -rw-r--r-- | app/Console/BaseCommand.php (renamed from app/Console/Base.php) | 5 | ||||
| -rw-r--r-- | app/Console/CronjobCommand.php (renamed from app/Console/Cronjob.php) | 2 | ||||
| -rw-r--r-- | app/Console/LocaleComparatorCommand.php (renamed from app/Console/LocaleComparator.php) | 2 | ||||
| -rw-r--r-- | app/Console/LocaleSyncCommand.php (renamed from app/Console/LocaleSync.php) | 2 | ||||
| -rw-r--r-- | app/Console/ProjectDailyColumnStatsExportCommand.php (renamed from app/Console/ProjectDailyColumnStatsExport.php) | 2 | ||||
| -rw-r--r-- | app/Console/ProjectDailyStatsCalculationCommand.php (renamed from app/Console/ProjectDailyStatsCalculation.php) | 2 | ||||
| -rw-r--r-- | app/Console/ResetPasswordCommand.php | 79 | ||||
| -rw-r--r-- | app/Console/ResetTwoFactorCommand.php | 38 | ||||
| -rw-r--r-- | app/Console/SubtaskExportCommand.php (renamed from app/Console/SubtaskExport.php) | 2 | ||||
| -rw-r--r-- | app/Console/TaskExportCommand.php (renamed from app/Console/TaskExport.php) | 2 | ||||
| -rw-r--r-- | app/Console/TaskOverdueNotificationCommand.php (renamed from app/Console/TaskOverdueNotification.php) | 83 | ||||
| -rw-r--r-- | app/Console/TaskTriggerCommand.php (renamed from app/Console/TaskTrigger.php) | 2 | ||||
| -rw-r--r-- | app/Console/TransitionExportCommand.php (renamed from app/Console/TransitionExport.php) | 2 |
13 files changed, 209 insertions, 14 deletions
diff --git a/app/Console/Base.php b/app/Console/BaseCommand.php index 25d48e44..4444ceba 100644 --- a/app/Console/Base.php +++ b/app/Console/BaseCommand.php @@ -11,6 +11,7 @@ use Symfony\Component\Console\Command\Command; * @package console * @author Frederic Guillot * + * @property \Kanboard\Validator\PasswordResetValidator $passwordResetValidator * @property \Kanboard\Export\SubtaskExport $subtaskExport * @property \Kanboard\Export\TaskExport $taskExport * @property \Kanboard\Export\TransitionExport $transitionExport @@ -21,11 +22,13 @@ use Symfony\Component\Console\Command\Command; * @property \Kanboard\Model\ProjectDailyStats $projectDailyStats * @property \Kanboard\Model\Task $task * @property \Kanboard\Model\TaskFinder $taskFinder + * @property \Kanboard\Model\User $user * @property \Kanboard\Model\UserNotification $userNotification * @property \Kanboard\Model\UserNotificationFilter $userNotificationFilter + * @property \Kanboard\Model\ProjectUserRole $projectUserRole * @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher */ -abstract class Base extends Command +abstract class BaseCommand extends Command { /** * Container instance diff --git a/app/Console/Cronjob.php b/app/Console/CronjobCommand.php index 3a5c5596..dae13af9 100644 --- a/app/Console/Cronjob.php +++ b/app/Console/CronjobCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\NullOutput; -class Cronjob extends Base +class CronjobCommand extends BaseCommand { private $commands = array( 'projects:daily-stats', diff --git a/app/Console/LocaleComparator.php b/app/Console/LocaleComparatorCommand.php index 8e5e0904..de83714f 100644 --- a/app/Console/LocaleComparator.php +++ b/app/Console/LocaleComparatorCommand.php @@ -7,7 +7,7 @@ use RecursiveDirectoryIterator; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class LocaleComparator extends Base +class LocaleComparatorCommand extends BaseCommand { const REF_LOCALE = 'fr_FR'; diff --git a/app/Console/LocaleSync.php b/app/Console/LocaleSyncCommand.php index d62b40b5..11cfbde0 100644 --- a/app/Console/LocaleSync.php +++ b/app/Console/LocaleSyncCommand.php @@ -6,7 +6,7 @@ use DirectoryIterator; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class LocaleSync extends Base +class LocaleSyncCommand extends BaseCommand { const REF_LOCALE = 'fr_FR'; diff --git a/app/Console/ProjectDailyColumnStatsExport.php b/app/Console/ProjectDailyColumnStatsExportCommand.php index 2513fbf1..ced1a374 100644 --- a/app/Console/ProjectDailyColumnStatsExport.php +++ b/app/Console/ProjectDailyColumnStatsExportCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ProjectDailyColumnStatsExport extends Base +class ProjectDailyColumnStatsExportCommand extends BaseCommand { protected function configure() { diff --git a/app/Console/ProjectDailyStatsCalculation.php b/app/Console/ProjectDailyStatsCalculationCommand.php index 9884cc1c..5b898f02 100644 --- a/app/Console/ProjectDailyStatsCalculation.php +++ b/app/Console/ProjectDailyStatsCalculationCommand.php @@ -6,7 +6,7 @@ use Kanboard\Model\Project; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ProjectDailyStatsCalculation extends Base +class ProjectDailyStatsCalculationCommand extends BaseCommand { protected function configure() { diff --git a/app/Console/ResetPasswordCommand.php b/app/Console/ResetPasswordCommand.php new file mode 100644 index 00000000..93dc3761 --- /dev/null +++ b/app/Console/ResetPasswordCommand.php @@ -0,0 +1,79 @@ +<?php + +namespace Kanboard\Console; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\Question; + +class ResetPasswordCommand extends BaseCommand +{ + protected function configure() + { + $this + ->setName('user:reset-password') + ->setDescription('Change user password') + ->addArgument('username', InputArgument::REQUIRED, 'Username') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $helper = $this->getHelper('question'); + $username = $input->getArgument('username'); + + $passwordQuestion = new Question('What is the new password for '.$username.'? (characters are not printed)'.PHP_EOL); + $passwordQuestion->setHidden(true); + $passwordQuestion->setHiddenFallback(false); + + $password = $helper->ask($input, $output, $passwordQuestion); + + $confirmationQuestion = new Question('Confirmation:'.PHP_EOL); + $confirmationQuestion->setHidden(true); + $confirmationQuestion->setHiddenFallback(false); + + $confirmation = $helper->ask($input, $output, $confirmationQuestion); + + if ($this->validatePassword($output, $password, $confirmation)) { + $this->resetPassword($output, $username, $password); + } + } + + private function validatePassword(OutputInterface $output, $password, $confirmation) + { + list($valid, $errors) = $this->passwordResetValidator->validateModification(array( + 'password' => $password, + 'confirmation' => $confirmation, + )); + + if (!$valid) { + foreach ($errors as $error_list) { + foreach ($error_list as $error) { + $output->writeln('<error>'.$error.'</error>'); + } + } + } + + return $valid; + } + + private function resetPassword(OutputInterface $output, $username, $password) + { + $userId = $this->user->getIdByUsername($username); + + if (empty($userId)) { + $output->writeln('<error>User not found</error>'); + return false; + } + + if (!$this->user->update(array('id' => $userId, 'password' => $password))) { + $output->writeln('<error>Unable to update password</error>'); + return false; + } + + $output->writeln('<info>Password updated successfully</info>'); + + return true; + } +} diff --git a/app/Console/ResetTwoFactorCommand.php b/app/Console/ResetTwoFactorCommand.php new file mode 100644 index 00000000..3bf01e81 --- /dev/null +++ b/app/Console/ResetTwoFactorCommand.php @@ -0,0 +1,38 @@ +<?php + +namespace Kanboard\Console; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ResetTwoFactorCommand extends BaseCommand +{ + protected function configure() + { + $this + ->setName('user:reset-2fa') + ->setDescription('Remove two-factor authentication for a user') + ->addArgument('username', InputArgument::REQUIRED, 'Username'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $username = $input->getArgument('username'); + $userId = $this->user->getIdByUsername($username); + + if (empty($userId)) { + $output->writeln('<error>User not found</error>'); + return false; + } + + if (!$this->user->update(array('id' => $userId, 'twofactor_activated' => 0, 'twofactor_secret' => ''))) { + $output->writeln('<error>Unable to update user profile</error>'); + return false; + } + + $output->writeln('<info>Two-factor authentication disabled</info>'); + + return true; + } +} diff --git a/app/Console/SubtaskExport.php b/app/Console/SubtaskExportCommand.php index aaa95276..986af1a4 100644 --- a/app/Console/SubtaskExport.php +++ b/app/Console/SubtaskExportCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class SubtaskExport extends Base +class SubtaskExportCommand extends BaseCommand { protected function configure() { diff --git a/app/Console/TaskExport.php b/app/Console/TaskExportCommand.php index 4515bf95..789245bc 100644 --- a/app/Console/TaskExport.php +++ b/app/Console/TaskExportCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class TaskExport extends Base +class TaskExportCommand extends BaseCommand { protected function configure() { diff --git a/app/Console/TaskOverdueNotification.php b/app/Console/TaskOverdueNotificationCommand.php index 43be4df8..7e8484c8 100644 --- a/app/Console/TaskOverdueNotification.php +++ b/app/Console/TaskOverdueNotificationCommand.php @@ -3,24 +3,33 @@ namespace Kanboard\Console; use Kanboard\Model\Task; +use Kanboard\Core\Security\Role; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class TaskOverdueNotification extends Base +class TaskOverdueNotificationCommand extends BaseCommand { protected function configure() { $this ->setName('notification:overdue-tasks') ->setDescription('Send notifications for overdue tasks') - ->addOption('show', null, InputOption::VALUE_NONE, 'Show sent overdue tasks'); + ->addOption('show', null, InputOption::VALUE_NONE, 'Show sent overdue tasks') + ->addOption('group', null, InputOption::VALUE_NONE, 'Group all overdue tasks for one user (from all projects) in one email') + ->addOption('manager', null, InputOption::VALUE_NONE, 'Send all overdue tasks to project manager(s) in one email'); } protected function execute(InputInterface $input, OutputInterface $output) { - $tasks = $this->sendOverdueTaskNotifications(); + if ($input->getOption('group')) { + $tasks = $this->sendGroupOverdueTaskNotifications(); + } elseif ($input->getOption('manager')) { + $tasks = $this->sendOverdueTaskNotificationsToManagers(); + } else { + $tasks = $this->sendOverdueTaskNotifications(); + } if ($input->getOption('show')) { $this->showTable($output, $tasks); @@ -50,6 +59,54 @@ class TaskOverdueNotification extends Base } /** + * Send all overdue tasks for one user in one email + * + * @access public + */ + public function sendGroupOverdueTaskNotifications() + { + $tasks = $this->taskFinder->getOverdueTasks(); + + foreach ($this->groupByColumn($tasks, 'owner_id') as $user_tasks) { + $users = $this->userNotification->getUsersWithNotificationEnabled($user_tasks[0]['project_id']); + + foreach ($users as $user) { + $this->sendUserOverdueTaskNotifications($user, $user_tasks); + } + } + + return $tasks; + } + + /** + * Send all overdue tasks in one email to project manager(s) + * + * @access public + */ + public function sendOverdueTaskNotificationsToManagers() + { + $tasks = $this->taskFinder->getOverdueTasks(); + + foreach ($this->groupByColumn($tasks, 'project_id') as $project_id => $project_tasks) { + $users = $this->userNotification->getUsersWithNotificationEnabled($project_id); + $managers = array(); + + foreach ($users as $user) { + $role = $this->projectUserRole->getUserRole($project_id, $user['id']); + if($role == Role::PROJECT_MANAGER) { + $managers[] = $user; + } + } + + foreach ($managers as $manager) { + $this->sendUserOverdueTaskNotificationsToManagers($manager, $project_tasks); + } + } + + return $tasks; + } + + /** * Send overdue tasks * * @access public @@ -79,10 +136,12 @@ class TaskOverdueNotification extends Base public function sendUserOverdueTaskNotifications(array $user, array $tasks) { $user_tasks = array(); + $project_names = array(); foreach ($tasks as $task) { if ($this->userNotificationFilter->shouldReceiveNotification($user, array('task' => $task))) { $user_tasks[] = $task; + $project_names[$task['project_id']] = $task['project_name']; } } @@ -90,12 +149,28 @@ class TaskOverdueNotification extends Base $this->userNotification->sendUserNotification( $user, Task::EVENT_OVERDUE, - array('tasks' => $user_tasks, 'project_name' => $tasks[0]['project_name']) + array('tasks' => $user_tasks, 'project_name' => implode(", ", $project_names)) ); } } /** + * Send overdue tasks for a project manager(s) + * + * @access public + * @param array $manager + * @param array $tasks + */ + public function sendUserOverdueTaskNotificationsToManagers(array $manager, array $tasks) + { + $this->userNotification->sendUserNotification( + $manager, + Task::EVENT_OVERDUE, + array('tasks' => $tasks, 'project_name' => $tasks[0]['project_name']) + ); + } + + /** * Group a collection of records by a column * * @access public diff --git a/app/Console/TaskTrigger.php b/app/Console/TaskTriggerCommand.php index 8d707211..9e9554f9 100644 --- a/app/Console/TaskTrigger.php +++ b/app/Console/TaskTriggerCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Kanboard\Model\Task; use Kanboard\Event\TaskListEvent; -class TaskTrigger extends Base +class TaskTriggerCommand extends BaseCommand { protected function configure() { diff --git a/app/Console/TransitionExport.php b/app/Console/TransitionExportCommand.php index d9f805a4..265757b3 100644 --- a/app/Console/TransitionExport.php +++ b/app/Console/TransitionExportCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class TransitionExport extends Base +class TransitionExportCommand extends BaseCommand { protected function configure() { |
