Boolean validation check cakephp not working - validation

Hey trying to get a validation check working on a boolean field called 'activated'. Basically if the boolean is 1 then the account is active, meaning they can login. If it is anything else then users cannot login.
Here is my check from the User Model:
public $checkActive = array(
'activated'=>array(
'rule'=>array('equalTo', '1'),
'message'=>'The account must be activated, please check your email.'
));
Unfortunately users are able to login when they are not suppose to.

I believe that validation in models are only tested when data is being saved.
If you are using the Authentication component, you can define a 'scope' which is a condition which must equal true for the user to be authenticated.
'scope' => array('User.activated' => 1)
More info and an example: http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html)
If you have written your own authentication then you could add the condition to your current find statement.
$this->User->find('all', array('conditions' => array('username' => $username, 'password' => $password, 'activated' =>1);
Hope this answers your question.

Related

exists validation is not working in laravel

LoginController
public function login(Request $request)
{
$request->validate([
'email'=>'required|exists:users',
'password'=>'required|exists:users',
]);
$email=$request->email;
$password=$request->password;
if (Auth::attempt(['email' => $email, 'password' => $password,'role'=>'admin'])) {
$token = $request->user()->createToken($request->email)->plainTextToken;
return response([
'token'=>$token,
'message'=>'Admin logged in successfully',
],200);
}
if (Auth::attempt(['email' => $email, 'password' => $password,'role'=>'user'])) {
$token = $request->user()->createToken($request->email)->plainTextToken;
return response([
'token'=>$token,
'message'=>'User logged in successfully',
],200);
}
return response([
'message'=>'Email or password is wrong',
],401);
}
I am creating a login API. So, I want to show email is wrong and password is wrong if the user or admin enters wrong email and wrong password. Here, when I enter the correct email and wrong password it displays only password is wrong error which is ok but when I enter the wrong email and correct password it shows two error messages that the email is wrong and the password is wrong. It should have shown only email is wrong error but why it is showing two errors can anyone explain it to me?
There are two type of validation rules in the laravel docs for this type of case.
exists - The field under validation must exist in a given database table.
'email' => 'exists:users,email'
unique - The field under validation must not exist within the given database table.
'email' => 'unique:users,email'
In both case specify the column name with a comma.
You cannot use exists in this way for checking the password. All you can do is check that it has been provided.
'password'=>'required|exists:users',
This will check that the supplied value is present in the password field of ANY user. Since the passwords are hashed, it would never match any user, never mind the user being checked.
As a security point, you should not indicate which of the items is wrong because this is a weakness and tells the person accessing the API that they have correctly guessed a username or a password.
Change both validations to required only and leave the Auth::attempt() to do the rest, returning the 401 if the credentials are not matched.

Laravel 5 - Validation

I am confuse how can I validate a user's username if I am updating it. Here's the scenario, if I click a specific user in list of users page it will redirect into a page which has a form with user's data in the form. Now, I have:
public function updateUser(Request $request){
$this->validate($request, [
'username' => 'required|unique:users',
'name' => 'required|max:255'
]);
}
UPDATE
$this->validate($request, [
'name' => 'unique:roles,name,'.$request->id
]);
I know the part where 'username' => 'required|unique:users' is checking if the username exists in the users table, but what if I dont want to change/update the username, and I just want to update the other field, then it says that the username is already exists. How can I validate it in a right way.
Need help guys. This can also help others for this kind of problem.
Laravel will accept a new parameter for the key of the table. This should be the id of the element you would like to ignore in your query.
something like 'username' => 'required|unique:users,username,'.$request->get('id'),
You will have to pass the id variable in your request when updating.
Laravel documentation: https://laravel.com/docs/5.4/validation#rule-unique
You can also try using the Rule class (search for "Forcing A Unique Rule To Ignore A Given ID"), which was added in Laravel version 5.3.
You can see an example of usage of my answer in the documentation at:
https://laravel.com/docs/5.2/validation#rule-unique (search for "Forcing A Unique Rule To Ignore A Given ID")
Update as per question update:
$this->validate($request, [
'name' => 'required|unique:roles, name,'.$request->id
]);
you want to update profile and at that time you stuck with this error "username is already exists". so my suggestion is just remove the required validation from username if username is not updated then don't send it to server, so you no need to check whether it's exists or not in table and also if want to check particular column you can write like this
public function updateUser(Request $request){
$this->validate($request, [
'username' => 'unique:users,column-name',
'name' => 'required|max:255'
]);
}
in above case if we receive a username then we check it's uniqueness else not
You just need to check if the user exists or not
'username' => 'exists:users'
If the user exists in the database you will update it.
What wrong you are doing is: You are trying to update a user and validating that the username should be unique (this validation should be applied during user creation), that is not correct.
Thanks.
EDIT 1
Generally, username or email is a key column which you should not allow the user to update. Otherwise, this problem will always exist.
EDIT 2
I agree with the actual scenario that we can not assume that the username field will always remain same and the user can not update it. If the user is updating the username then you can try this code.
'username' => 'required|unique:users,username,'.$user->id
If your table uses a primary key column name other than id, you may specify it as the fourth parameter:
'username' => 'required|unique:users,username,'.$user->id.',user_id'

Cartalyst Sentinel Laravel - How do you create roles?

Im new to Cartalyst Sentinel and this concept of ACL. I've managed to create a user, perform activation and login and logout.
I'd like to take my learning to the next level. I would like 2 types of Users on this laravel app. 1 is Administrator another is Subscriber. I'm assuming my account creation method should by default create the user a subscriber.
public function postCreate() {
/* Validation */
$validation = Validator::make(Input::all(), [
'email' => 'required|email|max:50|unique:users',
'username' => 'required|min:3|max:20|unique:users',
'password' => 'required|min:6',
'password_repeat' => 'required|same:password',
]);
if ($validation->fails()) {
return Redirect('login')->withErrors($validation)->withInput();
} else {
$credentials = Input::all();
$user = Sentinel::register($credentials);
$activation = Activation::create($user);
$activation_code = $activation->code;
if ($user) {
Mail::send('emails.auth.activate', ['link' => URL::route('account-activate', [$user->id, $activation_code]), 'username' => $user->username], function($message) use ($user) {
$message->to($user->email, $user->username)->subject('Activate your account');
});
return Redirect::route('home')->with('global', 'Thank you for registering! We have sent you an email to activate your account');
}
}
}
Do i alter the code like so
$user = Sentinel::register($credentials);
$user = Sentinel::findById(1);
$role = Sentinel::findRoleByName('Subscribers');
$role->users()->attach($user);
The thing is i have not even created any roles to begin with. Where do we write that functionality? Right now i have the following Controllers
AccountController - handles activation
AuthController - handles login/logout
RegistrationController - handles registration of user
RolesController - i've not written anything inside here yet. Im a bit lost.
Please guide me. Any help is greatly appreciated.
You do not need to do a search for your user if you already registered them, the register method returns the user.
You can do the following to attach a role to a user:
$user = Sentinel::register($credentials);
$role = Sentinel::findRoleByName('Subscribers');
$role->users()->attach($user);
// OR
$user->roles()->attach($role);
you have both a user and a role object and they have a many to many relation so it doesn't matter which one you use.
You will need to create a db seeder or a method to create your permissions. But to create your Subscribers Role you will need to do the following:
Sentinel::getRoleRepository()->createModel()->create([
'name' => 'Subscribers',
'slug' => 'subscribers',
'permissions' => [
'user.view' => true,
'user.delete' => false,
// any other permissions you want your Subscribers to have
]
]);
A similar call can build your Administrator roles as well.
Your Roles Model and Controller are already built for you, you just need to access them through Sentinel, which you already have Sentinel::findRoleByName('Subscribers'); call.
Cartalyst has some pretty decent documentation about setting up roles and permissions for your users:
https://cartalyst.com/manual/sentinel#roles
https://cartalyst.com/manual/sentinel#permissions
It's just a matter of figuring out what you want each role to do or not do.
Also, you can set specific permissions per user to override the role permissions.

cakephp 2.x include userExists in validating login

I'm new to CakePhp, I'm using CakePhp 2.x.
I am probably going about solving the problem below the wrong way. And I just know I'm overlooked something real simple but,.....
I'm validating login details based on 'Between 5 to 15 characters' they are retuning errors as expected.
[The MODEL]
public $validate = array(
'username' => array(
'between' => array(
'rule' => array('between', 5, 15),
'message' => 'Between 5 to 15 characters'
)
),
'password' => array(
'rule' => array('minLength', '8'),
'message' => 'Minimum 8 characters long'
)
);
[The CONTROLLER]
public function login() {
if ($this->request->data) {
$this->User->set($this->request->data);
if ($this->User->validates() && $this->Auth->login()) {
if ($user = $this->Auth->user()) {
$this->render($this->Auth->redirect());
}else{
//??
}
}else{
$this->User->create();
pr($this->User->invalidFields());
$errors = $this->User->validationErrors;
$data = compact('errors');
$this->set('errors', $data);
$this->set('_serialize', array('errors'));
$this->Session->setFlash('Your username/password combination was incorrect');
}
}
}
So, the problem is, if the fields follow the rules in the model above even if the login details (the user) doesn't exist, no errors will be returned (no good). Would it be correct to add an other validation for this, adding another rule to check if that user actually exists? If so how!?
Or, do I work this into the controllers login function checking if the user exists? I'm a little confused now. Maybe I've been looking at the screen for too long.
Thanks.
Would it be correct to add an other validation for this, adding
another rule to check if that user actually exists? If so how!?
You can add as many rules as you want. In this case you want the rule "unique". Read this section of the book about data validation.
Or, do I work this into the controllers login function checking if the
user exists?
All data manipulation and validation should happen in the model layer of the MVC stack. So put everything into a model method and pass the post data to it and validate it there. You can put all logic into the controller to but that's stupid in terms of not following the MVC pattern. Models can be shared between shells and controllers for example, a controller not. Again you could instantiate a controller in a shell but doing all of this negates any benefit and idea the MVC pattern has. Also a model is competitively easy to test. And yes, you should unit test your code. Check how our users plugin is doing it for example.
You can specify multiple rules per field...
Follow this link to learn more about it...
http://book.cakephp.org/2.0/en/models/data-validation.html#multiple-rules-per-field
a sample code is given below
<?php
[IN The MODEL]
//the following code checks if the username is notempty, is a valid email and is it already taken or not...
public $validate = array(
'username' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'Please enter a valid email.',
),
'email' => array(
'rule' => array('email'),
'message' => 'Please enter a valid email.',
),
'isUnique' => array(
'rule' => 'isUnique',
'message' => 'This username has already been taken.'
)
)
);
?>

CakePHP - Validation rule 'last' not working

I have two custom validation rules (I have tested they work correctly):
class PasswordResetKey extends AppModel {
public $validate = array(
'timestamp' => array(
'rule' => '_notExpired',
'message' => 'Your password reset link has expired. Please request another one.',
'last' => true
),
'key' => array(
'rule' => '_validFormat',
'message' => 'You do not appear to have used a valid password reset link. Please request another one.'
)
);
But no matter what I do, the errors returned are always:
Array
(
[key] => You do not appear to have used a valid password reset link. Please request another one.
[timestamp] => Your password reset link has expired. Please request another one.
)
Even when I check that the timestamp rule fails, it still goes on and checks the other rule for 'key' as well. I only want the timestamp error if it is there.
last is for multi rules per field. due to the fact that you only have one rule per field its always last and thus pointless.
My intuition says _notExpired should not fire if the reset link is wrong. I would have that rule raise a flag only if the link is correct but expired.

Resources