diff --git a/CHANGELOG-1.0.md b/CHANGELOG-1.0.md index 861f62eb8..1c0be30a8 100644 --- a/CHANGELOG-1.0.md +++ b/CHANGELOG-1.0.md @@ -3,6 +3,16 @@ CHANGELOG for 1.0.x This changelog references any relevant changes introduced in 1.0 minor versions. +* 1.0.3 (2019-10-23) + * **Issue #230:** Custom field privilege issue + * **Issue #29:** File attachment limit exceed + * **Issue #234:** Agent profile issue while thread added at customer panel + * **Issue #240:** Super admin name is not showing when set via terminal + * **Misc. Updates:** + * Added patch to support previously configured workflows with deprecated events + * Both agents and customers now share a common password reset page (events agent.forgot_password & customer.forgot_password deprecated) + * Updated README.md with link to the official gitter chat for uvdesk/core-framework + * 1.0.1 (2019-10-15) * **Issue #223:** Custom field privilege issue * **Issue #224:** Email template privilege issue diff --git a/Controller/Authentication.php b/Controller/Authentication.php index 40fbd91ae..ca70eccd5 100644 --- a/Controller/Authentication.php +++ b/Controller/Authentication.php @@ -3,12 +3,14 @@ namespace Webkul\UVDesk\CoreFrameworkBundle\Controller; use Symfony\Component\Form\FormError; -use Webkul\UVDesk\CoreFrameworkBundle\Entity\User; use Symfony\Component\HttpFoundation\Request; -use Webkul\UVDesk\CoreFrameworkBundle\Utils\TokenGenerator; +use Symfony\Component\HttpFoundation\Response; +use Webkul\UVDesk\CoreFrameworkBundle\Entity\User; use Symfony\Component\EventDispatcher\GenericEvent; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Form\Extension\Core\Type\EmailType; +use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Webkul\UVDesk\CoreFrameworkBundle\Utils\TokenGenerator; +use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events as CoreWorkflowEvents; class Authentication extends Controller @@ -32,82 +34,71 @@ public function logout(Request $request) public function forgotPassword(Request $request) { - if (null == $this->get('user.service')->getSessionUser()) { - $entityManager = $this->getDoctrine()->getManager(); + if (null != $this->get('user.service')->getSessionUser()) { + return new Response('How did you land here? :/', 404); + } + + $entityManager = $this->getDoctrine()->getManager(); - if ($request->getMethod() == 'POST') { - $user = new User(); - $form = $this->createFormBuilder($user,['csrf_protection' => false]) - ->add('email',EmailType::class) - ->getForm(); + if ($request->getMethod() == 'POST') { + $user = new User(); + $form = $this->createFormBuilder($user,['csrf_protection' => false]) + ->add('email',EmailType::class) + ->getForm(); - $form->submit(['email' => $request->request->get('forgot_password_form')['email']]); - $form->handleRequest($request); - - if ($form->isValid()) { - $repository = $this->getDoctrine()->getRepository('UVDeskCoreFrameworkBundle:User'); - $user = $entityManager->getRepository('UVDeskCoreFrameworkBundle:User')->findOneBy(array('email' => $form->getData()->getEmail())); - - if ($user && $user->getAgentInstance()) { - // Trigger agent forgot password event - $event = new GenericEvent(CoreWorkflowEvents\Agent\ForgotPassword::getId(), [ - 'entity' => $user, - ]); - - $this->get('event_dispatcher')->dispatch('uvdesk.automation.workflow.execute', $event); - $request->getSession()->getFlashBag()->set('success','Please check your mail for password update.'); + $form->submit(['email' => $request->request->get('forgot_password_form')['email']]); + $form->handleRequest($request); + + if ($form->isValid()) { + $repository = $this->getDoctrine()->getRepository('UVDeskCoreFrameworkBundle:User'); + $user = $entityManager->getRepository('UVDeskCoreFrameworkBundle:User')->findOneByEmail($form->getData()->getEmail()); + + if (!empty($user)) { + // Trigger agent forgot password event + $event = new GenericEvent(CoreWorkflowEvents\UserForgotPassword::getId(), [ + 'entity' => $user, + ]); - return $this->redirect($this->generateUrl('helpdesk_member_update_account_credentials')."/".$form->getData()->getEmail()); - } else { - $request->getSession()->getFlashBag()->set('warning', 'This Email address is not registered with us.'); - } + $this->get('event_dispatcher')->dispatch('uvdesk.automation.workflow.execute', $event); + $request->getSession()->getFlashBag()->set('success', 'Please check your mail for password update.'); + } else { + $request->getSession()->getFlashBag()->set('warning', 'This email address is not registered with us.'); } } - - return $this->render("@UVDeskCoreFramework//forgotPassword.html.twig"); } - - return $this->redirect($this->generateUrl('helpdesk_member_dashboard')); + + return $this->render("@UVDeskCoreFramework//forgotPassword.html.twig"); } - public function updateCredentials($email, $verificationCode) + public function updateCredentials($email, $verificationCode, Request $request, UserPasswordEncoderInterface $encoder) { if (empty($email) || empty($verificationCode)) { - return $this->redirect($this->generateUrl('helpdesk_member_handle_login')); + return new Response('How did you land here? :/', 404); + } else { + $entityManager = $this->getDoctrine()->getManager(); + $user = $entityManager->getRepository('UVDeskCoreFrameworkBundle:User')->findOneByEmail($email); + + if (empty($user) || $user->getVerificationCode() != $verificationCode) { + return new Response('How did you land here? :/', 404); + } } - $entityManager = $this->getDoctrine()->getManager(); - $request = $this->container->get('request_stack')->getCurrentRequest(); - - // Validate request - $user = $entityManager->getRepository('UVDeskCoreFrameworkBundle:User')->findOneByEmail($email); - - if (empty($user) || null == $user->getAgentInstance() || $user->getVerificationCode() != $verificationCode) { - return $this->redirect($this->generateUrl('helpdesk_member_handle_login')); - } - if ($request->getMethod() == 'POST') { $updatedCredentials = $request->request->all(); if ($updatedCredentials['password'] === $updatedCredentials['confirmPassword']) { - $user->setPassword($this->encodePassword($user, $updatedCredentials['password'])); + $user->setPassword($encoder->encodePassword($user, $updatedCredentials['password'])); $user->setVerificationCode(TokenGenerator::generateToken()); $entityManager->persist($user); $entityManager->flush(); $request->getSession()->getFlashBag()->set('success', 'Your password has been updated successfully.'); - return $this->redirect($this->generateUrl('helpdesk_member_handle_login')); } else { - $request->getSession()->getFlashBag()->set('warning', "Password don't match."); + $request->getSession()->getFlashBag()->set('warning', "Please try again. The passwords do not match."); } } - - return $this->render("@UVDeskCoreFramework//resetPassword.html.twig"); - } - protected function encodePassword(User $user, $plainPassword) - { - return $encodedPassword = $this->container->get('security.password_encoder')->encodePassword($user, $plainPassword); + return $this->render("@UVDeskCoreFramework//resetPassword.html.twig"); } } diff --git a/Fixtures/EmailTemplates.php b/Fixtures/EmailTemplates.php index d299f3d44..3d88c675f 100644 --- a/Fixtures/EmailTemplates.php +++ b/Fixtures/EmailTemplates.php @@ -10,15 +10,14 @@ class EmailTemplates extends DoctrineFixture { private static $seeds = [ + CoreEmailTemplates\UserForgotPassword::class, CoreEmailTemplates\Agent\TicketReply::class, CoreEmailTemplates\Agent\TicketCreated::class, CoreEmailTemplates\Agent\AccountCreated::class, - CoreEmailTemplates\Agent\ForgotPassword::class, CoreEmailTemplates\Agent\TicketAssigned::class, CoreEmailTemplates\Customer\TicketReply::class, CoreEmailTemplates\Customer\TicketCreated::class, CoreEmailTemplates\Customer\AccountCreated::class, - CoreEmailTemplates\Customer\ForgotPassword::class, ]; public function load(ObjectManager $entityManager) diff --git a/README.md b/README.md index 56d8570e1..25e78d129 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,12 @@
-[UVDesk Community Edition][1] is an easy-to-use, highly customizable open-source **helpdesk solution** built on top of the reliable [Symfony][2] **PHP framework**, enabling organizations to provide their customers with the best level of support solution possible. - -CoreFrameworkBundle --------------- + The standalone **CoreFrameworkBundle** lies at the heart of the [UVDesk Community][1] helpdesk, providing the core essential functionalities and integration tools to easily integrate any other community helpdesk packages, furhter extending the capabilities of the helpdesk system. diff --git a/Repository/ThreadRepository.php b/Repository/ThreadRepository.php index db95849a9..5a97c29c9 100644 --- a/Repository/ThreadRepository.php +++ b/Repository/ThreadRepository.php @@ -137,7 +137,7 @@ public function getAllCustomerThreads($ticketId,\Symfony\Component\HttpFoundatio 'reply' => html_entity_decode($thread['message']), 'source' => $thread['source'], 'threadType' => $thread['threadType'], - 'userType' => 'customer', + 'userType' => $thread['createdBy'], 'formatedCreatedAt' => $userService->getLocalizedFormattedTime($userService->getSessionUser(), $thread['createdAt']), 'timestamp' => $userService->convertToDatetimeTimezoneTimestamp($thread['createdAt']), 'cc' => $thread['cc'], diff --git a/Resources/config/routes/private.yaml b/Resources/config/routes/private.yaml index f77a27ebc..386b9e416 100644 --- a/Resources/config/routes/private.yaml +++ b/Resources/config/routes/private.yaml @@ -7,15 +7,6 @@ helpdesk_member_handle_logout: path: /logout controller: Webkul\UVDesk\CoreFrameworkBundle\Controller\Authentication::logout -helpdesk_member_forgot_account_password: - path: /forgot-password - controller: Webkul\UVDesk\CoreFrameworkBundle\Controller\Authentication::forgotPassword - -helpdesk_member_update_account_credentials: - path: /update-credentials/{email}/{verificationCode} - controller: Webkul\UVDesk\CoreFrameworkBundle\Controller\Authentication::updateCredentials - defaults: { email: '', verificationCode: '' } - # Agent Panel Resources helpdesk_member_dashboard: path: /dashboard diff --git a/Resources/config/routes/public.yaml b/Resources/config/routes/public.yaml index 3c0d16f66..ba7cdb9d0 100644 --- a/Resources/config/routes/public.yaml +++ b/Resources/config/routes/public.yaml @@ -1 +1,12 @@ -# Add public routing resources here ... \ No newline at end of file +# Add public routing resources here ... +helpdesk_forgot_account_password: + path: /{_locale}/forgot-password + controller: Webkul\UVDesk\CoreFrameworkBundle\Controller\Authentication::forgotPassword + requirements: { _locale: '%app_locales%' } + defaults: { _locale: '%locale%' } + +helpdesk_update_account_credentials: + path: /{_locale}/update-credentials/{email}/{verificationCode} + controller: Webkul\UVDesk\CoreFrameworkBundle\Controller\Authentication::updateCredentials + requirements: { _locale: '%app_locales%' } + defaults: { _locale: '%locale%', email: '', verificationCode: '' } diff --git a/Resources/views/Templates/attachment.html.twig b/Resources/views/Templates/attachment.html.twig index ab3893ada..a8a0dce6d 100644 --- a/Resources/views/Templates/attachment.html.twig +++ b/Resources/views/Templates/attachment.html.twig @@ -7,37 +7,85 @@ $(function () { var FileView = Backbone.View.extend({ fileCounter: 0, + max_post_size: {{ max_post_size }}, + max_file_uploads: {{ max_file_uploads }}, + upload_max_filesize: {{ upload_max_filesize }}, el: '.attachment-block', events : { 'click .uv-file-label': 'createFileType', 'change .attachment': 'selectFile', - 'click .uv-added-attachment span': 'removeFile' + 'click .uv-added-attachment span': 'removeFile', + 'click .uv-field-message': 'removeError', }, createFileType: function(e) { - currentElement = Backbone.$(e.currentTarget) + this.removeError(e) + var currentElement = Backbone.$(e.currentTarget), + attachmentBlock = currentElement.parents('.attachment-block') + if (attachmentBlock.children('.uv-added-attachment').length + 1 > this.max_file_uploads) { + attachmentBlock.append(this.getDefaultErrorMessage()) + return; + } this.fileCounter += 1; - currentElement.parents('.attachment-block').append(' ') + attachmentBlock.append(' ') $('#file-' + this.fileCounter).find('.attachment').trigger('click') }, labelTemplate: _.template('{%global.companyLogo%}
-
-
-
- - Forgot password, this is it!! - -
-
-
-
Hi {%user.userName%},
-
-
-
-
You recently requested to reset your password for your {%global.companyName%} account. Click the link to reset it {%user.forgotPasswordLink%}
-
-
-
If you did not request a password reset, please ignore this mail or revert back to let us know.
-Thanks and Regards
-{%global.companyName%}
- - -MESSAGE; - - public static function getName() - { - return self::$name; - } - - public static function getTemplateType() - { - return self::$type; - } - - public static function getSubject() - { - return self::$subject; - } - - public static function getMessage() - { - return self::$message; - } -} \ No newline at end of file diff --git a/Templates/Email/Resources/Customer/ForgotPassword.php b/Templates/Email/Resources/UserForgotPassword.php similarity index 90% rename from Templates/Email/Resources/Customer/ForgotPassword.php rename to Templates/Email/Resources/UserForgotPassword.php index 789746b36..37b6c2ea9 100644 --- a/Templates/Email/Resources/Customer/ForgotPassword.php +++ b/Templates/Email/Resources/UserForgotPassword.php @@ -1,13 +1,13 @@ diff --git a/Templates/config.yaml b/Templates/config.yaml index d64417502..a3e1f6948 100644 --- a/Templates/config.yaml +++ b/Templates/config.yaml @@ -9,6 +9,12 @@ parameters: uvdesk_site_path.member_prefix: member uvdesk_site_path.knowledgebase_customer_prefix: customer + # File uploads constraints + # @TODO: Set these parameters via compilers + max_post_size: 8388608 + max_file_uploads: 20 + upload_max_filesize: 2097152 + uvdesk: site_url: 'localhost:8000' upload_manager: diff --git a/Templates/twig.yaml b/Templates/twig.yaml index 1fb0aa3c0..d423bf860 100644 --- a/Templates/twig.yaml +++ b/Templates/twig.yaml @@ -3,6 +3,9 @@ twig: default_agent_image_path: '%assets_default_agent_profile_image_path%' default_customer_image_path: '%assets_default_customer_profile_image_path%' default_helpdesk_image_path: '%assets_default_helpdesk_profile_image_path%' + max_post_size: '%max_post_size%' + max_file_uploads: '%max_file_uploads%' + upload_max_filesize: '%upload_max_filesize%' user_service: "@user.service" uvdesk_service: "@uvdesk.service" ticket_service: "@ticket.service" diff --git a/Templates/uvdesk.php b/Templates/uvdesk.php index 6951e4a9b..6a50b5600 100644 --- a/Templates/uvdesk.php +++ b/Templates/uvdesk.php @@ -12,6 +12,12 @@ uvdesk_site_path.member_prefix: member uvdesk_site_path.knowledgebase_customer_prefix: customer + + # File uploads constraints + # @TODO: Set these parameters via compilers + max_post_size: 8388608 + max_file_uploads: 20 + upload_max_filesize: 2097152 uvdesk: site_url: '{{ SITE_URL }}' diff --git a/Workflow/Actions/MailUser.php b/Workflow/Actions/MailUser.php new file mode 100644 index 000000000..b925e7be8 --- /dev/null +++ b/Workflow/Actions/MailUser.php @@ -0,0 +1,63 @@ +get('doctrine.orm.entity_manager'); + + return array_map(function ($emailTemplate) { + return [ + 'id' => $emailTemplate->getId(), + 'name' => $emailTemplate->getName(), + ]; + }, $entityManager->getRepository('UVDeskCoreFrameworkBundle:EmailTemplates')->findAll()); + } + + public static function applyAction(ContainerInterface $container, $entity, $value = null) + { + $entityManager = $container->get('doctrine.orm.entity_manager'); + + switch (true) { + case $entity instanceof CoreEntities\User: + $emailTemplate = $entityManager->getRepository('UVDeskCoreFrameworkBundle:EmailTemplates')->findOneById($value); + + if (empty($emailTemplate)) { + // @TODO: Send default email template + return; + } + + $emailPlaceholders = $container->get('email.service')->getEmailPlaceholderValues($entity); + $subject = $container->get('email.service')->processEmailSubject($emailTemplate->getSubject(), $emailPlaceholders); + $message = $container->get('email.service')->processEmailContent($emailTemplate->getMessage(), $emailPlaceholders); + + $messageId = $container->get('email.service')->sendMail($subject, $message, $entity->getEmail()); + break; + default: + break; + } + } +} diff --git a/Workflow/Events/Agent/ForgotPassword.php b/Workflow/Events/Agent/ForgotPassword.php index f4fbcd707..99785a54c 100644 --- a/Workflow/Events/Agent/ForgotPassword.php +++ b/Workflow/Events/Agent/ForgotPassword.php @@ -3,16 +3,10 @@ namespace Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events\Agent; use Webkul\UVDesk\AutomationBundle\Workflow\FunctionalGroup; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Webkul\UVDesk\AutomationBundle\Workflow\Event as WorkflowEvent; +use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events\UserForgotPassword as UserForgotPasswordEvent; -class ForgotPassword extends WorkflowEvent +class ForgotPassword extends UserForgotPasswordEvent { - public static function getId() - { - return 'uvdesk.agent.forgot_password'; - } - public static function getDescription() { return 'Agent Forgot Password'; diff --git a/Workflow/Events/Customer/ForgotPassword.php b/Workflow/Events/Customer/ForgotPassword.php index 15359dbd6..dcd70e59e 100644 --- a/Workflow/Events/Customer/ForgotPassword.php +++ b/Workflow/Events/Customer/ForgotPassword.php @@ -3,16 +3,10 @@ namespace Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events\Customer; use Webkul\UVDesk\AutomationBundle\Workflow\FunctionalGroup; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Webkul\UVDesk\AutomationBundle\Workflow\Event as WorkflowEvent; +use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events\UserForgotPassword as UserForgotPasswordEvent; -class ForgotPassword extends WorkflowEvent +class ForgotPassword extends UserForgotPasswordEvent { - public static function getId() - { - return 'uvdesk.customer.forgot_password'; - } - public static function getDescription() { return 'Customer Forgot Password'; diff --git a/Workflow/Events/UserForgotPassword.php b/Workflow/Events/UserForgotPassword.php new file mode 100644 index 000000000..6fd4e5070 --- /dev/null +++ b/Workflow/Events/UserForgotPassword.php @@ -0,0 +1,25 @@ +