ZF2 optionally change user password in form - zend-framework2

i want to have a form, where a logged in user can change his user data. Optionally he can insert a new password. I tried to remove the inputfilter of the 'password' and 'passwordVerification' fields, if the posted password is empty, but i don't know how to handle the save in my service, that the password gets not overwritten...
Controller action
public function indexAction() {
$identity = $this->authentication()->getIdentity();
$userService = $this->userService;
$form = $this->userForm;
$form->bind($identity);
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->get('password')->getValue() == '') {
$validationGroup = $form->getValidationGroup();
$passwordKey = array_search('password', $validationGroup);
$passwordVerificationKey = array_search('passwordVerification', $validationGroup);
unset($validationGroup[$passwordKey]);
unset($validationGroup[$passwordVerificationKey]);
$form->setValidationGroup($validationGroup);
$form->getInputFilter()->remove('password');
$form->getInputFilter()->remove('passwordVerification');
}
if ($form->isValid()) {
$userService->saveUser($form->getData());
$this->flashMessenger()->addSuccessMessage('Data has been saved successfully');
return $this->redirect()->toRoute('admin/account');
}
}
return array(
'userForm' => $form
);
}
User service
public function saveUser(User $user) {
if ($password = $user->getPassword()) {
$user->setPassword($this->authenticationService->getAdapter()->getBcrypt()->create($password));
}
$this->userRepository->save($user);
}

when i'm doing this i use a use an unmapped password property (e.g. passwordForm) in my user entity which is used in the form so the original password is not overridden. if the passwordForm field is filled you can override the original password with that value

Related

ZF2 on post update record (not working)

I am trying to update records in my database. I am following a book but something isnt working.
This is the edit action. On post form action leads to process action.
public function editAction()
{
$userTable = $this->getServiceLocator()->get('UserTable');
$user = $userTable->getUser($this->params()->fromRoute('id'));
$form = $this->getServiceLocator()->get('UserEditForm');
$form->bind($user);
$viewModel = new ViewModel(array(
'form' => $form,
'user_id' => $this->params()->fromRoute('id')
));
return $viewModel;
}
Process action
public function processAction()
{
// Get User ID from POST
$post = $this->request->getPost();
$userTable = $this->getServiceLocator()->get('UserTable');
// Load User entity
$user = $userTable->getUser($post->id);
// Bind User entity to Form
$form = $this->getServiceLocator()->get('UserEditForm');
$form->bind($user);
$form->setData($post);
// Save user
$this->getServiceLocator()->get('UserTable')->saveUser($user);
}
And this is the class UserTable with function save user:
public function saveUser(User $user)
{
$data = array(
'email' => $user->email,
'name' => $user->name,
'password' => $user->password,
);
$id = (int)$user->id;
if ($id == 0) {
$this->tableGateway->insert($data);
} else {
if ($this->getUser($id)) {
$this->tableGateway->update($data, array('id' => $id));
} else {
throw new \Exception('User ID does not exist');
}
}
}
There is no error showing. It passes $this->tableGateway->update and just nothing !
EDIT: I can delete users, add users.
u miss this
if ($form->isValid()) {
$this->getServiceLocator()->get('UserTable')->saveUser($form->getData());
}
After validation you can now retrieve validate form data with $form->getData().
Also note that because of binding entity to form via $form->bind($user) $form->getData() is an instance of User
Hope it helps ;)
I dont know why but i must check if form is valid.
if($form->isValid()){
// do the save
}

How to update unique email address or other properties in asp.net mvc5?

In my asp.net mvc5 application user can update there email address or other data. When user create an account it works fine, but when I update date if the email field unchanged then validation message show "Email Address already exists". So how can I fix it?
I also need to check if email address change then it must check this email is unique or not. If not unique then user can't update the data and validation message show "Email Address already exists".
Script
$('#UserEmail').blur(function () {
var url = "/Account/CheckUserEmail";
var Email = $('#UserEmail').val();
$.get(url, { input: email }, function (data) {
if (data == "Available") {
$("#result").html("<span style='color:green;'>User email available</span>");
$("#UserEmail").css('background-color', '');
} else if (data == "Empty") {
$("#result").html("<span> </span>");
} else {
$("#result").html("<span style='color:red'>User email not available</span>");
//$("#UserEmail").css('background-color', '#e97878');
}
});
})
Controller
public string CheckUserEmail(string email)
{
if (input == string.Empty)
{
return "Empty";
}
var finduser = UserManager.FindByEmail(email);
if (finduser == null)
{
return "Available";
}
else
{
return "Not Available";
}
return "";
}
Currently you handling the .blur() event which would unnecessarily trigger your ajax call when a user tabs through the controls unchanged. Instead you should be handling the .change() event. This would be triggered only when the text is changed and the control loses focus. A user could still make a change, then go back and undo it so you could prevent the server being called by comparing the value and defaultValue. Finally there seems no point calling the server if the user has not entered an email.
Script (note the isValid variable declared outside the function so this could be checked to prevent a submit)
var isValid = true;
$('#UserEmail').change(function () {
var span = $('<span></span>');
var url = '#Url.Action("CheckUserEmail", "Account")'; // don't hard code your url's
var email = $(this).val();
if(!email) { // assume an email address is required
isValid = false;
span.text('Please enter an email address');
} else if (email == $(this)[0].defaultValue) { // nothing has changed so OK
isValid = true;
} else { // call server to validate
$.get(url, { input: email }, function (data) {
isValid = data;
if (!isValid) {
span.text('User email not available');
}
});
}
if(isValid) {
span.css('color', 'green'); // better to use class names
} else {
span.css('color', 'red');
}
$("#result").html(span);
});
Controller
public JsonResult CheckUserEmail(string email)
{
return Json(UserManager.FindByEmail(email) == null, JsonRequestBehavior.AllowGet);
}
However all this is rather fragile and doesn't prevent the form from being submitted. I would recommend using jquery unobtrusive validation along with the RemoteAttribute for checking if an existing email exists, and the Required and EmailAttribute for ensuring its a valid email address, then using #Html.ValidationMessageFor() in the view.

Can I use the Configuration.Seed method to an an initial ApplicationUser to an MVC database?

I know that we can initialise the database when doing a Entity Framework migration using the Seed method, as below.
protected override void Seed(CraigSheppardSoftware.Models.ApplicationDbContext context)
{
context.Users.AddOrUpdate(p => p.UserName,
new ApplicationUser { FullName = "System Admin", UserName="CssOp", UserRole = UserType.SystemAdmin,
LandlinePhone=new ComplexDataTypes.PhoneNumber(), MobilePhone= new ComplexDataTypes.PhoneNumber()
} );
context.SaveChanges();
}
The problem is that the when I try to use that user to login with, I can't as I dont know what the password is.
There is no password field on the database. I notice that there is a PasswordHash field and suspect that this is an encrypted password. How do I create a password hash ?
Use UserManager to create / update the user.
var manager = new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(context));
var user = manager.Find("CssOp", "ThePassword");
if (user == null)
{
user = new ApplicationUser { UserName = "CssOp", Email = "email#mail.com" };
manager.Create(user, "ThePassword");
}
else
{
user.Email = "newemail#mail.com";
manager.Update(user);
}

Routing After Login zf2

Hi everyone I'm new with Zend Framework 2 , for ruthentification on my project i used this module (( http://samsonasik.wordpress.com/2013/05/29/zend-framework-2-working-with-authenticationservice-and-db-session-save-handler/#comment-5393 )) and i add the field "Role" on data base.
I want to ask how can i make a specific route for any member of user, for example if the user’s Admin when he connect he will be redirected automatically to route “Admin” and if the user’s “visitor” he will be redirected to route “visitor” ???
Thx
/** this function called by indexAction to reduce complexity of function */
protected function authenticate($form, $viewModel)
{
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$dataform = $form->getData();
$this->authService->getAdapter()
->setIdentity($dataform['username'])
->setCredential($dataform['password']);
$result = $this->authService->authenticate();
if ($result->isValid()) {
//authentication success
$resultRow = $this->authService->getAdapter()->getResultRowObject();
$this->authService->getStorage()->write(
array('id' => $resultRow->id,
'username' => $dataform['username'],
'ip_address' => $this->getRequest()->getServer('REMOTE_ADDR'),
'user_agent' => $request->getServer('HTTP_USER_AGENT'))
);
// your userid -> select the role
$role = $this->getRoleUser($resultRow->id);
return $this->redirect()->toRoute('success', array('action' => 'index', 'role'=>$role));
} else {
$viewModel->setVariable('error', 'Login Error');
}
}
}
}
Then into your success page, just perform some actions using the param role
Don't forget to create a function $role = $this->getRoleUser($resultRow->id); to get the role of the user.
To implement roles function
check before this documentation to how to configure and create models/database: http://framework.zend.com/manual/2.1/en/user-guide/database-and-models.html
protected function getRoleUser($userid){
$table = $this->getServiceLocator()->get('User\Model\UserTable');
return $table->find($userid)->current()->role;
}

ZF2 : paramaters coming from route are cleared after submitting a form

I'm using AbstractTableGateway and HydratingResultset to do db operations. (with BjyProfiler)
when i post my form data with add action it works, but edit action doesn't work. when i make a bind it works, but i m redirected to the add page because submitting the form resets paramaters coming from route.
here is my code for editAction() (same with Album editAction())
$id = (int)$this->params()->fromRoute('id');
if (!$id) {
return $this->redirect()->toRoute('voyage', array('action'=>'add'));
}
$voyage = $this->getVoyageTable()->getVoyage($id);
$form = new VoyageForm($this->getTypeVoyageTable());
$form->bind($voyage);
$form->get('submit')->setAttribute('value', 'Edit');
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$this->getVoyageTable()->saveVoyage($voyage);
// Redirect to list of voyages
return $this->redirect()->toRoute('voyage');
}
}
return array(
'id' => $id,
'form' => $form,
);
}
and my table :
class VoyageTable extends AbstractTableGateway
{
protected $table ='voyages';
public function __construct(Adapter $adapter)
{
$this->adapter = $adapter;
$this->resultSetPrototype = new HydratingResultSet();
$this->resultSetPrototype->setObjectPrototype(new Voyage());
$this->initialize();
}
[...]
Can sombody help me? How can i fix this problem ? Thanks.
You need to inform the form about the hydrator since ClassMethods is not the default
$form->setHydrator(new ClassMethods());

Resources