partkeepr

fork of partkeepr
git clone https://git.e1e0.net/partkeepr.git
Log | Files | Refs | Submodules | README | LICENSE

commit 22af0258cde07295cf76bfa77723ed1a904c8858
parent 71a93a016c2885bb304157712d6e56b0e94b7052
Author: Felicitus <felicitus@felicitus.org>
Date:   Mon, 12 Oct 2015 16:14:13 +0200

Implemented password changing

Diffstat:
Mapp/config/config_partkeepr.yml | 13++++++++++++-
Asrc/PartKeepr/AuthBundle/Action/ChangePasswordAction.php | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/PartKeepr/AuthBundle/Resources/config/actions.xml | 6++++++
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/User/Preferences/UserPasswordChangePanel.js | 149+++++++++++++++++++++++++++++++++++++++++--------------------------------------
4 files changed, 175 insertions(+), 72 deletions(-)

diff --git a/app/config/config_partkeepr.yml b/app/config/config_partkeepr.yml @@ -959,6 +959,17 @@ services: - "partkeepr.auth.login" # Controller - "PartKeeprAuthLogin" + resource.user.item_operation.change_password: + class: "Dunglas\ApiBundle\Api\Operation\Operation" + public: false + factory: [ "@api.operation_factory", "createItemOperation" ] + arguments: + - "@resource.user" # Resource + - [ "PUT" ] # Methods + - "/users/{id}/changePassword" # Path + - "partkeepr.auth.change_password" # Controller + - "PartKeeprAuthChangePassword" + resource.user.collection_operation.get_providers: class: "Dunglas\ApiBundle\Api\Operation\Operation" public: false @@ -1029,7 +1040,7 @@ services: - method: "initCollectionOperations" arguments: [ [ "@resource.user.collection_operation.get", "@resource.user.collection_operation.post_custom", "@resource.user.collection_operation.get_providers" ] ] - method: "initItemOperations" - arguments: [ [ "@resource.user.item_operation.get", "@resource.user.item_operation.get", "@resource.user.item_operation.put_custom", "@resource.user.item_operation.delete", "@resource.user.item_operation.get_preferences", "@resource.user.item_operation.set_preference", "@resource.user.item_operation.delete_preference", "@resource.user.item_operation.login" ] ] + arguments: [ [ "@resource.user.item_operation.get", "@resource.user.item_operation.get", "@resource.user.item_operation.put_custom", "@resource.user.item_operation.delete", "@resource.user.item_operation.get_preferences", "@resource.user.item_operation.set_preference", "@resource.user.item_operation.delete_preference", "@resource.user.item_operation.login", "@resource.user.item_operation.change_password" ] ] - method: "initDenormalizationContext" arguments: - { groups: [ "default" ] } diff --git a/src/PartKeepr/AuthBundle/Action/ChangePasswordAction.php b/src/PartKeepr/AuthBundle/Action/ChangePasswordAction.php @@ -0,0 +1,79 @@ +<?php +namespace PartKeepr\AuthBundle\Action; + + +use Dunglas\ApiBundle\Action\ActionUtilTrait; +use Dunglas\ApiBundle\Api\ResourceInterface; +use Dunglas\ApiBundle\Exception\RuntimeException; +use Dunglas\ApiBundle\Model\DataProviderInterface; +use FOS\UserBundle\Model\UserManagerInterface; +use FOS\UserBundle\Util\UserManipulator; +use PartKeepr\AuthBundle\Entity\User; +use PartKeepr\AuthBundle\Services\UserService; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Core\Encoder\EncoderFactory; +use Symfony\Component\Serializer\SerializerInterface; + +class ChangePasswordAction +{ + use ActionUtilTrait; + + /** + * @var UserService + */ + private $userService; + + /** + * @var UserManipulator + */ + private $userManipulator; + + /** + * @var EncoderFactory + */ + private $encoderFactory; + + /** + * @var UserManagerInterface + */ + private $userManager; + + public function __construct( + UserService $userService, + UserManipulator $userManipulator, + EncoderFactory $encoderFactory, + UserManagerInterface $userManager + ) { + $this->userService = $userService; + $this->userManipulator = $userManipulator; + $this->encoderFactory = $encoderFactory; + $this->userManager = $userManager; + } + + public function __invoke (Request $request) { + $user = $this->userService->getUser(); + + if (!$request->request->has("oldpassword") && !$request->request->has("newpassword")) { + throw new \Exception("old password and new password need to be specified"); + } + + $FOSUser = $this->userManager->findUserByUsername($user->getUsername()); + + if ($FOSUser === null) { + throw new \Exception("Cannot change password for legacy or LDAP users"); + } + + $encoder = $this->encoderFactory->getEncoder($FOSUser); + $encoded_pass = $encoder->encodePassword($request->request->get("oldpassword"), $FOSUser->getSalt()); + + if ($FOSUser->getPassword() != $encoded_pass) { + throw new \Exception("Passwords don't match"); + } + + $this->userManipulator->changePassword($user->getUsername(), $request->request->get("newpassword")); + + + return $user; + } +} diff --git a/src/PartKeepr/AuthBundle/Resources/config/actions.xml b/src/PartKeepr/AuthBundle/Resources/config/actions.xml @@ -35,5 +35,11 @@ <argument type="service" id="partkeepr.userservice"/> <argument type="service" id="api.serializer"/> </service> + <service id="partkeepr.auth.change_password" class="PartKeepr\AuthBundle\Action\ChangePasswordAction"> + <argument type="service" id="partkeepr.userservice"/> + <argument type="service" id="fos_user.util.user_manipulator"/> + <argument type="service" id="security.encoder_factory"/> + <argument type="service" id="fos_user.user_manager"/> + </service> </services> </container> diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/User/Preferences/UserPasswordChangePanel.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/User/Preferences/UserPasswordChangePanel.js @@ -1,75 +1,82 @@ Ext.define('PartKeepr.UserPasswordChangePanel', { - extend: 'Ext.form.FormPanel', - title: i18n("Change Password"), - bodyStyle: 'background:#DBDBDB;padding: 10px;', - initComponent: function () { + extend: 'Ext.form.FormPanel', + title: i18n("Change Password"), + bodyStyle: 'background:#DBDBDB;padding: 10px;', + initComponent: function () + { - this.oldPassword = Ext.create("Ext.form.field.Text", { - inputType: "password", - name: 'password', - labelWidth: 150, - style: 'border-bottom: 1px solid grey; padding-bottom: 10px;', - width: 300, - fieldLabel: i18n("Current Password") - }); - - this.newPassword = Ext.create("Ext.form.field.Text", { - style: 'margin-top: 10px', - inputType: "password", - name: 'password', - labelWidth: 150, - width: 300, - fieldLabel: i18n("New Password") - }); - - this.newPasswordConfirm = Ext.create("Ext.form.field.Text", { - inputType: "password", - name: 'password', - labelWidth: 150, - width: 300, - validator: Ext.bind(this.validatePassword, this), - fieldLabel: i18n("New Password (Confirm)") - }); - - this.items = [ - this.oldPassword, - this.newPassword, - this.newPasswordConfirm, - { - xtype: 'fieldcontainer', - hideEmptyLabel: false, - width: 300, - labelWidth: 150, - items: { - xtype: 'button', - handler: this.onChangePassword, - scope: this, - width: 145, - iconCls: 'web-icon accept', - text: i18n("Change Password") - } - }]; - - this.callParent(); - }, - onChangePassword: function () { - if (this.getForm().isValid()) { + this.oldPassword = Ext.create("Ext.form.field.Text", { + inputType: "password", + name: 'password', + labelWidth: 150, + style: 'border-bottom: 1px solid grey; padding-bottom: 10px;', + width: 300, + fieldLabel: i18n("Current Password") + }); - var call = new PartKeepr.ServiceCall("UserPreference", "changePassword"); - call.setParameter("oldpassword", md5(this.oldPassword.getValue())); - call.setParameter("newpassword", md5(this.newPassword.getValue())); - call.setHandler(Ext.bind(this.onAfterPasswordChange, this)); - call.doCall(); - } - }, - onAfterPasswordChange: function (data) { - Ext.Msg.alert(data.data, data.data); - }, - validatePassword: function () { - if (this.newPassword.getValue() != this.newPasswordConfirm.getValue()) { - return i18n("Passwords don't match"); - } - - return true; - } + this.newPassword = Ext.create("Ext.form.field.Text", { + style: 'margin-top: 10px', + inputType: "password", + name: 'password', + labelWidth: 150, + width: 300, + fieldLabel: i18n("New Password") + }); + + this.newPasswordConfirm = Ext.create("Ext.form.field.Text", { + inputType: "password", + name: 'password', + labelWidth: 150, + width: 300, + validator: Ext.bind(this.validatePassword, this), + fieldLabel: i18n("New Password (Confirm)") + }); + + this.items = [ + this.oldPassword, + this.newPassword, + this.newPasswordConfirm, + { + xtype: 'fieldcontainer', + hideEmptyLabel: false, + width: 300, + labelWidth: 150, + items: { + xtype: 'button', + handler: this.onChangePassword, + scope: this, + width: 145, + iconCls: 'web-icon accept', + text: i18n("Change Password") + } + } + ]; + + this.callParent(); + }, + onChangePassword: function () + { + if (this.getForm().isValid()) { + + var user = PartKeepr.getApplication().getLoginManager().getUser(); + + user.callPutAction("changePassword", { + "oldpassword": this.oldPassword.getValue(), + "newpassword": this.newPassword.getValue() + }, Ext.bind(this.onAfterPasswordChange, this)); + // @TODO Logout the user after succesful password change + } + }, + onAfterPasswordChange: function (data) + { + Ext.Msg.alert(data); + }, + validatePassword: function () + { + if (this.newPassword.getValue() != this.newPasswordConfirm.getValue()) { + return i18n("Passwords don't match"); + } + + return true; + } });