Yii2 ActiveForm issue - forms

I have a update user form with fields such as username, email, password, etc. I need the password field to be empty and to update the users.password field in the MySQL database only when the user has filled in the password field. Is it possible? I use the ActiveForm widget of Yii2.

First of all, it's not an Yii2 ActiveForm issue. It can be possible by following some simple steps.
Create two variables in your model, one for storing password, and another is for repeat password field.
public $REPEAT_PASSWORD;
public $INIT_PASSWORD;
then add afterFind function to set null value to your password field, so it wont be shown to user
public function afterFind()
{
//reset the password to null because we don't want password to be shown.
$this->INIT_PASSWORD = $this->PASSWORD;
$this->PASSWORD = null;
parent::afterFind();
}
and now, write beforeSave function to save user password if user has entered on
public function beforeSave()
{
// in this case, we will use the old hashed password.
if(empty($this->PASSWORD) && empty($this->REPEAT_PASSWORD) && !empty($this->INIT_PASSWORD)) {
$this->PASSWORD=$this->REPEAT_PASSWORD=$this->INIT_PASSWORD;
} elseif(!empty($this->PASSWORD) && !empty($this->REPEAT_PASSWORD) && ($this->PASSWORD == $this->REPEAT_PASSWORD)) {
$this->PASSWORD = md5($this->PASSWORD);
$this->REPEAT_PASSWORD = md5($this->REPEAT_PASSWORD);
}
return parent::beforeSave();
}

Related

How to do decrypt AES256 in backpack laravel

In one application where i am using backpack for admin dashboard. I am sending data(such as 'name', 'email') as encrypting AES256 to stored in the database. Now, I want to retrieve those data and show in the admin dashboard. But the problem is how will I decrypt those data values before showing in the dashboard ?
If you wanna decrypt your data from the database, you can use accessors in your models to modify the shown data.
So, in your users model add this function:
public function getNameAttribute($value) {
// Add decrypt methond in this function
// $name = decrypt($value, 'password');
return $name;
}
public function getEmailAttribute($value) {
// Add decrypt methond in this function
// $email = decrypt($value, 'password');
return $email;
}
I found the decrypt example here https://stackoverflow.com/a/46872528/8653054

How to compare two passwords in codeigniter using encryption

I stored a password in database using an encryption key, but now, when the user wants to login in the system, how can I compare both passwords? Each time it gives a different encrypted password..
$first_password = $this->input->post('password');
$password=$this->encrypt->encode($first_password);
Here is my model code
public function validate_login($username,$password){
$q = $this->db->where(['username'=>$username,'password'=>$password])
->get('oss_user');
if($q->num_rows()){
return $q->row()->user_id;
}
else{
return FALSE;
}
My question is: how can I compare the user entered password with the password stored in database?
You can not compare encrypted password this way. First you have get record from database using email id, once you find row of same email id then you have to pass encrypted password which is store in database on this function "$this->encrypt->decode($encrypted_password);", so you get back original password from encryption form and then compare it with password given during login session, please see follow code.
public function validate_login($username,$password){
$q = $this->db->where(['username'=>$username])
->get('oss_user');
if($q->num_rows()){
$desc_password = $this->encrypt->decode($q->row()->password);
if($desc_password == $password){
return $q->row()->user_id;
}
else
return FALSE;
}
else{
return FALSE;
}

Getting user type in mvc using mongodb

I am trying to verify if a user belongs to the Admin group. If he/she does, the admin page can be visible from the browser. So far I have this:
#if (HttpContext.Current.Session["userName"] != null && !Session["userName"].Equals(""))
{
Admin page
}
It works as it is supposed to, displays this route only for people that are logged in, but what about checking the type and allowing only admin users to see it? I also have this method in my userDB.
public string getType(string username) {
var mongoClient = new MongoClient("mongodb://localhost");
var database = mongoClient.GetDatabase("SearchForKnowledge");
var coll = database.GetCollection<BsonDocument>("Users");
var filter = Builders<BsonDocument>.Filter.Eq("userName",username);
var results = coll.Find(filter).ToList().First();
return results["type"].ToString();
}
It just returns the type of the user.
You need to call the getType method by passing the user name as parameter. If return value of getType is Admin then redirect the users to admin page.
string userName= (string)(Session["userName"]);
string result = getType(userName);
if (result == "Admin")
//... redirect the user

Grails form field always null

I want to add password confirmation to my project's registration page. But I'm having a problem with value of one of my fields. All the fields are ok but the password2 field, it's the confirmation password and is a transient field of User domain class. Here are my Domain, Controller and View codes
Domain class:
class User {
String fullName
String username
String email
String password
String password2
static transients = ['password2']
static constraints = {
username size: 5..15, blank: false, unique: true
email email: true, blank: false
password blank:false, size:5..15, matches:/[\S]+/, validator:{ val, obj ->
if (obj.password != obj.password2)
return 'user.password.dontmatch'
}
}
}
Part of the Controller:
if (request.method == 'POST') {
// create domain object and assign parameters using data binding
def u = new User(params)
if (! u.save()) {
// validation failed, render registration page again
flash.error = "error(s) creating user: Value of the confirmation password is: "+u.password2
//render(view:"/signup",model:[user:user])
return [user:u]
} else {
// validate/save ok, store user in session, redirect to homepage
session.user = u
redirect(controller:'home')
return
}
} else if (session.user) {
// don't allow registration while user is logged in
redirect(controller:'home')
return
}
And a part from the View:
<div><input class="pretty-input ${hasErrors(bean:user,field:'email','input-error')}" type="email" name="email" value="${user?.email}" ></input><span>— Enter email</span></div>
<div><input class="pretty-input ${hasErrors(bean:user,field:'password','input-error')}" type="password" name="password"></input><span>— Choose a password</span></div>
<div><input class="pretty-input ${hasErrors(bean:user,field:'password2','input-error')}" type="password" name="password2"></input><span>— Repeat the password</span></div>
My code works if I remove password's custom validation because password2's value is always null. I why this happens when all other fields works but password2 not.
Trasients fields are not bindables by default, thus you cannot pass params to fill it.
You can do this:
static constraints = {
... your code here
password2 bindable: true
}
But I recommend you to use a command object to validate that condition, it is clever.

Specflow with MVC Model Validation Issue

I am using Specflow, nunit and moq to test the default MVC2 application registration as I learn SpecFlow.
I have the following steps for checking if the username and password have not been entered.
Steps
[Given(#"The user has not entered the username")]
public void GivenTheUserHasNotEnteredTheUsername()
{
_registerModel = new RegisterModel
{
UserName = null,
Email = "test#dummy.com",
Password = "test123",
ConfirmPassword = "test123"
};
}
[Given(#"The user has not entered the password")]
public void GivenTheUserHasNotEnteredThePassword()
{
_registerModel = new RegisterModel
{
UserName = "user" + new Random(1000).NextDouble().ToString(),
Email = "test#dummy.com",
Password = string.Empty,
ConfirmPassword = "test123"
};
}
[When(#"He Clicks on Register button")]
public void WhenHeClicksOnRegisterButton ()
{
_controller.ValidateModel(_registerModel);
_result = _controller.Register(_registerModel);
}
[Then(#"He should be shown the error message ""(.*)"" ""(.*)""")]
public void ThenHeShouldBeShownTheErrorMessage(string errorMessage, string field)
{
Assert.IsInstanceOf<ViewResult>(_result);
var view = _result as ViewResult;
Assert.IsNotNull(view);
Assert.IsFalse(_controller.ModelState.IsValid);
Assert.IsFalse(view.ViewData.ModelState.IsValidField(field));
Assert.IsTrue(_controller.ViewData.ModelState.ContainsKey(field));
Assert.AreEqual(errorMessage,
_controller.ModelState[field].Errors[0].ErrorMessage);
}
Extension method to force validation
public static class Extensions
{
public static void ValidateModel<T> ( this Controller controller, T modelObject )
{
if (controller.ControllerContext == null)
controller.ControllerContext = new ControllerContext();
Type type = controller.GetType();
MethodInfo tryValidateModelMethod =
type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Where(
mi => mi.Name == "TryValidateModel" && mi.GetParameters().Count() == 1).First();
tryValidateModelMethod.Invoke(controller, new object[] { modelObject });
}
}`
I do not understand why the password missing test fails on the following lines.
Assert.IsFalse(view.ViewData.ModelState.IsValidField(field));
Assert.IsTrue(_controller.ViewData.ModelState.ContainsKey(field));
I have noticed that the error message being returned is for the Password and ConfirmPassword not matching but I dont understand why for all the other tests, including the Missing Confirm Password test (Identical to the missing Password test) they work fine.
Any ideas?
Features
Scenario: Register should return error if username is missing
Given The user has not entered the username
When He Clicks on Register button
Then He should be shown the error
message "The Username field is required." "username"
Scenario: Register should return error if password is missing
Given The user has not entered the
password
When He Clicks on Register button
Then He should be shown the error message "'Password' must be at least
6 characters long." "Password"
UPDATE
Ok seems the ValidatePasswordLengthAttribute in the Account Model couldn't initilise Membership.Provider as I did not have the connectionstring in my app.config. Is the Pembership.Provider connecting to the membership DB now?
I have added the connection string but now the test passes 50% of the time as it returns two errors:
Password required
Password must be 6 chars long.
The problem is that they are not returned in the same order every time so the test is flaky.
How can I rewrite my scenario and test to account for this? Can I still keep the one "Then" method or do I need to create a new method?
Thanks.
I had to add the connection string the the AccountService to the App.config which nunit uses. This was causing an error on the ValidatePasswordLengthAttribure.
I have updated the Assert which checks for the correct error message to:
Assert.AreEqual(errorMessage,
_controller.ModelState[field].Errors.First(e => e.ErrorMessage == errorMessage).ErrorMessage);
Still unsure about whether the Membership.Provider is hitting the DB