I'm working on a project and one part of it is that users can create projects.
It is required for a project to be coupled to a user. If the user is logged in when creating a project, then there is no problem, i can just attach the project to the authenticated user, but when the user is not logged in, i have the following section in my form
In short, there are 2 radiobuttons, the 1st means "i have an account, log me in" with the login fields below it. The 2nd means "i'm a new user, create an account", which will show the correct fields to create a user.
Since this form is added to the project creation form, everything has to be validated at once.
Now i have a formRequest that handles all the validation, but i'm struggling with the login part.
When validating, i have to check the following things:
1) if the user was logged in when starting to fill in the form, but is no longer logged in when storing the data, then we have to add this to the errors array
2) if the user was not logged in when starting to fill in the form, and he choses to log in through the form a have explained above, then we need to try and log in the user when creating the project, and add a message to the errors array when the login fails "wrongs credentials has been supplied....".
I have tried with the following FormRequest:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateJobsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
if (! auth()->check()) {
if($this->get('is_logged_in')) {
// If we reach this, then we were logged in when starting to fill in the form
// but are no longer when finishing the form (idle for to long, ....).
$this->getValidatorInstance()->errors()->add('authentication', 'You were no longer authenticated when creating the project.');
}
if($this->get('auth_type') == 'login') {
if(! auth()->attempt($this->getLoginParams())) {
// if we reach this, we have chosen to log in through the form, bu the provided details did not match our records.
$this->getValidatorInstance()->errors()->add('authentication', 'Failed to authenticate');
}
}
}
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'login.email' => 'required_if:auth_type,login',
'login.password' => 'required_if:auth_type,login',
'register.email' => 'nullable|required_if:auth_type,register|email|max:255',
'register.password' => 'required_if:auth_type,register,confirmed|max:255',
'register.firstname' => 'required_if:auth_type,register|max:255',
'register.name' => 'required_if:auth_type,register|max:255',
'jobs.*.title' => 'required',
'jobs.*.description' => 'required',
'jobs.*.category_id' => 'required|exists:job_categories,id',
'jobs.*.location_id' => 'required|exists:job_locations,id',
'jobs.*.profiles' => 'required|numeric'
];
}
private function getLoginParams()
{
return ['email' => $this->get('login.email'), 'password' => $this->get('login.password')];
}
}
The most important part is in the authorize method. I'm trying to add items to the errors array, but its not working.
1) If all the other validations from the rules function pass, then i am not redirected to the creation page but the code enters the controller and a project is created.
2) if not all other validations pass, then i'm redirected to the creation page, but the errors i added in the authorize method are not added to the errors, and thus not shown on the creation page.
I don't think the authorize method is the right place to put this logic.
I would add additional rules to the rules array based on the login status.
try something like this:
public function rules()
{
$rules = [
'login.email' => 'required_if:auth_type,login',
'login.password' => 'required_if:auth_type,login',
'register.email' => 'nullable|required_if:auth_type,register|email|max:255',
'register.password' => 'required_if:auth_type,register,confirmed|max:255',
'register.firstname' => 'required_if:auth_type,register|max:255',
'register.name' => 'required_if:auth_type,register|max:255',
'jobs.*.title' => 'required',
'jobs.*.description' => 'required',
'jobs.*.category_id' => 'required|exists:job_categories,id',
'jobs.*.location_id' => 'required|exists:job_locations,id',
'jobs.*.profiles' => 'required|numeric'
];
if (! auth()->check()) {
if($this->get('is_logged_in')) {
// If we reach this, then we were logged in when starting to fill in the form
// but are no longer when finishing the form (idle for to long, ....).
$rules = array_merge($rules, ['no_authentication' => 'required']);
}
if($this->get('auth_type') == 'login') {
if(! auth()->attempt($this->getLoginParams())) {
// if we reach this, we have chosen to log in through the form, bu the provided details did not match our records.
$rules = array_merge($rules, ['failed_authentication' => 'required', 'Failed to authenticate']);
}
}
}
return $rules;
}
public function messages()
{
return [
'no_authentication.required' => 'You were no longer authenticated when creating the project.',
'failed_authentication.required' => 'Failed to authenticate'
];
}
Related
I followed laravel documentation about Form Request Validation.
and im not sure if get it correctly. i created a make:request EmployeeRequest to validate an employee form. but for some reasons it only redirects me to a blank page with "forbidden" as message
// this is my request code
public function rules()
{
return [
'email' => 'bail|required|email|unique:employees|max:255',
'first_name' => 'bail|required|max:50|min:2',
'last_name' => 'bail|required|max:50|min:2',
'date_of_birth' => 'bail|required',
'contact_number' => 'bail|required|max:11',
'image' => 'bail|required|image',
];
}
//then i called it in my controller like this
public function store(EmployeeRequest $request)
{
//my code if everything is valid
}
(when entering invalid data)
it only redirects me to a blank page with an echo of forbidden.
im not sure if i understand it correctly. but im expecting that it will automatically redirects to the previous page with errors
Maybe you have to authorize the user, or change the authorize() function to return true . From the docs:
If the authorize method returns false, a HTTP response with a 403 status code will automatically be returned and your controller method
will not execute.
If you plan to have authorization logic in another part of your
application, return true from the authorize method:
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
Working in Laravel Spark and have a custom API endpoint that checks a user credentials but doesn't log them in, just returns the user data.
I have a form request that checks the email and password for being required and then I use
withValidator()
to run some more validation on the password.
public function rules()
{
return [
'email' => 'required|email|exists:users',
'password' => 'required'
];
}
public function withValidator($validator)
{
$validator->after(function ($validator) {
$user = User::where('email', $this->email)->first();
if ( $user && !Hash::check($this->password, $user->password) ) {
$validator->errors()->add('password', 'Incorrect password');
} else {
// Pass the user to the controller
}
});
}
In my controller I want to be able to return the user, but I dont want to run through the process of checking the hash etc.
I would simply like to be able to do:
return $request->user
Or similar.
Is there a way to do this?
Why not just do this in the controller?
$user = User::where('email', $request->email)->first();
If you put this after the validator, you already know the user is valid, otherwise the validator would fail before it got to that point.
I am in the middle of working with my create a user form inside of my restful user controller. While the user is on the form I have it currently posting to the store method. When the form is submitted to the method I want it to validate the user input and then redirect back to the create method for either displaying a success message or an array of error messages if there was a failure in the data validation. Can someone point out what is needed to help me redirect to the create method with either a success message or error message based off the validation test.
/**
* Store a newly created user in storage.
*
* #return Response
*/
public function store()
{
$input = Input::all();
$validation = Validator::make($input, $rules);
if ($validation->fails())
{
$messages = $validator->all();
}
else
{
User::create([
'username' => $input['username'],
'email_address' => $input['email_address'],
'password' => $input['password'],
'role_id' => $input['role']
]);
}
return Redirect::to('users/create');
}
you could use either
$messages = $validator->messages();
or
$failed = $validator->failed();
to retrieve error messages. If you want show 'flash' message, you can use 'with' method in redirection.
Redirect::to('user/currentroute')->with('message', 'Something wrong');
for more details, you should read in documentation
I have created login form and using Auth method for authorizing user with email and password. Login is done be doLogin function in HomeControler
public function doLogin()
{
$rules = array(
'email' => 'required|email', // make sure the email is an actual email
'password' => 'required|alphaNum|min:3' // password can only be alphanumeric and has to be greater than 3 characters
);
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect::to('login')
->withErrors($validator) // send back all errors to the login form
->withInput(Input::except('password')); // send back the input (not the password) so that we can repopulate the form
} else {
$userdata = array(
'email' => Input::get('email'),
'password' => Input::get('password')
);
if (Auth::attempt($userdata)) {
$id = Auth::id();
return Redirect::to('panel');
} else {
return Redirect::to('login');
}
}
}
In my routes.php file I have created route to get user by id and before that check if user is logged in.
Route::get('panel/{id}', array('before' => 'auth', function($id)
{
$user=User::find($id);
dd($user);
}));
I have faced 2 problems so far:
– How I can create route with get parameters in doLogin function, so that it redirects user in panel/id/ address?
return Redirect::to('panel')->with('id', $id); is not working!
And second problem is that panel/{id} route is checking if user is logged in with 'before' => 'auth', but if I logged in with User id 1 and then opened address panel/2/ it opens the current route. How I can make laravel to check that user id that is logged in mit opens the current route. How I can make laravel to check that user id that is logged in matches the user ID that is requested in route?atches the user ID that is requested in route?
Just extends all of controllers you want to authorize from BaseController.
BaseController could be
class BaseController extends Controller {
public function __construct() {
$this->beforeFilter('auth');
}
}
then forget about it, it works fine.
Is there any way to use Validator on login form from Simple Authentication in Lithium tutorial. I know that it is better to use validation in model, but with login form there's no model, so, as I understand, I need to use Validator in the SessionsController, but I don't know how to do it (
What I am trying to do is in SessionsController:
<?php
namespace app\controllers;
use lithium\security\Auth;
use lithium\storage\Session;
use lithium\util\Validator;
class SessionsController extends \lithium\action\Controller {
private $rules = array(
'password' => array(
array('notEmpty', 'message' => 'password is empty'),
),
'email' => array(
array('notEmpty', 'message' => 'email is empty'),
array('email', 'message' => 'email is not valid')
)
);
public function add() {
if ($this->request->data && Auth::check('default', $this->request)) {
return $this->redirect('/');
}
// Handle failed authentication attempts
$errors = Validator::check($this->request->data, $this->rules);
return compact('errors');
}
public function delete() {
Auth::clear('default');
return $this->redirect('/');
}
/* ... */
}
and I'm expect that after empty form was sent, it will be rendered with errors, like in user creation from tutorial. But there are no errors showed, just login form again. Can I ever validate forms without models and how to do it in Lithium?
Thanks beforehand.
The errors rendered in the form are bound to an entity, which is bound to the form when you create it with $this->form->create($user). In this case only, the errors are displayed thanks to the form helper automatically.
If your need is to check, in the controller, the incoming data, you can check $this->request->data['password'] and return errors that you need to handle by yourself in the form view (with if (!empty($errors)) for example)