Password validation in symfony forms - php

I'm new to this and I have a problem lares from making a long time, I have the following code.
<?php
class RegistroUsuariosForm extends sfForm {
public function configure() {
$this->setWidgets(array(
'password1' => new sfWidgetFormInputPassword(),
'password2' => new sfWidgetFormInputPassword(),
'avatar' => new sfWidgetFormInputFile(),
));
$this->widgetSchema->setLabels(array(
'password1' => 'Password',
'password2' => 'Repetir Contraseña',
'avatar' => 'Imagen a mostrar'
));
$this->widgetSchema->setNameFormat('RegUsuario[%s]');
$this->validatorSchema->setPostValidator(new sfValidatorSchemaCompare('password1', '==', 'password2',
array(),
array('invalid' => 'Las contraseñas no son iguales')));
$this->setValidators(array(
'password1' => new sfValidatorString(array('min_length' => 4),
array('required' => 'Campo obligatorio',
'min_length' => 'Minimo %min_length% caracteres.',)),
'password2' => new sfValidatorString(array('min_length' => 4),
array('required' => 'Campo obligatorio',
'min_length' => 'Minimo %min_length% caracteres.',)),
'avatar' => new sfValidatorFile(
array(
'required' => false,
'max_size' => (1048576 * 2),
'mime_types' => 'web_images',
),
array(
'required' => 'Campo obligatorio',
'max_size' => 'El archivo es muy grande (máximo de 2Mb).',
'mime_types' => 'El tipo de archivo es invalido (%mime_type%).',
'partial' => 'El archivo subido fue sólo parcialmente cargado.',
'no_tmp_dir' => 'Falta la carpeta temporal.',
'cant_write' => 'No se pudo guardar el archivo en el servidor.',
'extension' => 'De carga del archivo se detuvo, por extensión.'
)),
));
}
}
public function executeActivarinvitacion(sfWebRequest $request) {
$key = $request->getParameter('key');
$this->formulario = new RegistroUsuariosForm();
if (($dato = Invitaciones::TraerDatosDeInvitacion($key))) {
$this->key = $key;
if ($request->isMethod('post')) {
$RegUsuario = $request->getParameter('RegUsuario');
$Avatar = $request->getFiles('RegUsuario');
$this->formulario = new RegistroUsuariosForm();
$this->formulario->bind($RegUsuario, $Avatar);
if ($this->formulario->isValid()) {
echo $RegUsuario['password1'];
echo ' - '.$RegUsuario['password2'];
exit();
}
}
} else {
$this->forward404();
}
$this->usuario = $dato['usuario'];
$this->correo = $dato['correo'];
}
The validation of the password just does not work, does anyone know what?

sfForm->setValidators() internally re-creates a new validatorSchema, so your previously set form validator is just cleared. Just put the call to $this->validatorSchema->setPostValidator() below the rest and it should work.

Related

Correct syntax for CodeIgniter 4 Validation matches option

I am implementing a registration section for a site, using CodeIgniter 4.0.4.
I implemented the following rules in my Validation configuration file.
public $registro = [
'registro.nombre' => [
'rules' => 'required',
'errors' => [
'required' => 'El nombre es un campo obligatorio.'
]
],
'registro.apellido' => [
'rules' => 'required',
'errors' => [
'required' => 'El apellido es un campo obligatorio.'
]
],
'registro.email' => [
'rules' => 'required|valid_email',
'errors' => [
'required' => 'El correo electrónico es un campo obligatorio.',
'valid_email' => 'Por favor, revisa el formato de tu correo electrónico, no parece ser válido.'
]
],
'registro.password' => [
'rules' => 'required|min_length[6]',
'errors' => [
'required' => 'La contraseña es un campo obligatorio.',
'min_length' => 'La contraseña debe ser de al menos 6 caracteres.'
]
],
'registro.verificar_password' => [
'rules' => 'required|matches[registro.password]|min_length[6]',
'errors' => [
'required' => 'Verificar contraseña es un campo obligatorio.',
'matches[registro.password]' => 'Las contraseñas no coinciden, por favor revisa.',
'min_length' => 'Verificar contraseña es un campo que debe ser de al menos 6 caracteres.'
]
]
];
Everything works fine, except the matches[registro.password] option. The problem is that I am not sure how to add it in the errors message. Inside the documentation there isn't a specific example for this.
My inputs (reduced code) for the passwords are these:
<input type="password" name="registro[password]" minlength="6" id="registro_password" placeholder="Contraseña (mínimo 6 caracteres)" required />
<input type="password" name="registro[verificar_password]" minlength="6" data-equalto="registro_password" id="registro_verificar_password" placeholder="Verificar contraseña" required />
So, basically when I send the info to my controller I get an array with those two indexes. I make sure that the passwords are the same, but I keep getting that error. I tried to change the errors index for matches to these two versions:
// Version 1
'matches[registro.password]' => 'Las contraseñas no coinciden, por favor revisa.'
// Output
// The registro.verificar_password field does not match the registro.password field.
// This is not a message I have defined as you can see above
// Version 2
'matches' => 'Las contraseñas no coinciden, por favor revisa.'
// Output
// Las contraseñas no coinciden, por favor revisa.
// This is the message I have defined above.
For this example I am literally using 123456 as a password.
I tried doing this and here are the results:
var_dump($post['registro']['password'] == $post['registro']['verificar_password']);
// Output
// bool(true)
if(!$validation->run($post, 'registro')) {
echo $validation->listErrors();
}
// Output
// Las contraseñas no coinciden, por favor revisa.
Am I doing something incorrectly, or is this a validation library bug?
Ok, I checked this with the CodeIgniter 4 team, creating an issue report.
This was indeed a bug, which by when people read this would be fixed. Just to clear up my own question, the correct way of using the errors message for the matches index would be:
'registro.verificar_password' => [
'rules' => 'required|matches[registro.password]|min_length[6]',
'errors' => [
'required' => 'Verificar contraseña es un campo obligatorio.',
'matches' => 'Las contraseñas no coinciden, por favor revisa.',
'min_length' => 'Verificar contraseña es un campo que debe ser de al menos 6 caracteres.'
]
]
Basically the index should be only matches in the errors array.

Laravel rules with condition and custom error messages

I want to optimize the code to make it more efficient and scalable.
So I want to merge this part into one:
if($request->input('logintype') == 'register'){
$validator = Validator::make($request->all(), [
'option.*' => 'required|integer',
'quantity.*' => 'required|integer',
'conditions' => 'required',
'comission' => 'required',
],[
'option.integer' => 'Debe introducir una opción válida',
'quantity.required' => 'Introduzca una cantidad a comprar',
'quantity.integer' => 'Debe introducir una cantidad válida',
'quantity.*.max' => 'Se ha superado el límite máximo de tickets por persona',
'conditions.required' => 'Debe aceptar los Términos y Condiciones',
'comission.required' => 'Debe seleccionar el método de pago',
]);
}
else{
$validator = Validator::make($request->all(), [
'option.*' => 'integer',
'quantity.*' => 'required|integer',
'comission' => 'required',
],[
'option.integer' => 'Debe introducir una opción válida',
'quantity.required' => 'Introduzca una cantidad a comprar',
'quantity.integer' => 'Debe introducir una cantidad válida',
'quantity.*.max' => 'Se ha superado el límite máximo de tickets por persona',
'comission.required' => 'Debe seleccionar el método de pago',
]);
}
I've check that this is possible with this code:
$validator->sometimes('conditions', 'required', function($request){
return $request->input('logintype') == 'register';
});
But I'm unsure how to deal with the custom error messages.
You can achieve this by adding the extra comment to the validator.
Just do like this
$validator = Validator::make($request->all(), [
'option.*' => 'required|integer',
'quantity.*' => 'required|integer',
'comission' => 'required',
],[
'option.integer' => 'Debe introducir una opción válida',
'quantity.required' => 'Introduzca una cantidad a comprar',
'quantity.integer' => 'Debe introducir una cantidad válida',
'quantity.*.max' => 'Se ha superado el límite máximo de tickets por persona',
'conditions.required' => 'Debe aceptar los Términos y Condiciones',
'comission.required' => 'Debe seleccionar el método de pago',
]);
$validator->sometimes('conditions', 'required', function($request){
return $request->input('logintype') == 'register';
});
It will validated your input fields and give your define error message check this
And you can also add multiple field by array
$validator->sometimes(['conditions','option'], 'required', function($request){
return $request->input('logintype') == 'register';
});
Check this https://laravel.com/docs/5.5/validation#conditionally-adding-rules
You may use required_if to conditionally add the required rule.
In this scenario required_if rule is added to the fields option and conditions.
FormRequest is used for separating validation logic from controller.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class YourRequestClassName extends FormRequest
{
public function authorize()
{
return true;
}
public function messages()
{
return [
'option.integer' => 'Debe introducir una opción válida',
'quantity.required' => 'Introduzca una cantidad a comprar',
'quantity.integer' => 'Debe introducir una cantidad válida',
'quantity.*.max' => 'Se ha superado el límite máximo de tickets por persona',
'conditions.required_if' => 'Debe aceptar los Términos y Condiciones',
'comission.required' => 'Debe seleccionar el método de pago',
];
}
public function rules()
{
return [
'option.*' => [
'required_if:logintype,register',
'nullable',
'integer',
],
'quantity.*' => [
'required',
'nullable',
'integer',
],
'conditions' => [
'required_if:logintype,register',
'nullable',
],
'comission' => [
'required',
],
];
}
}
In your controller, you can inject the App\Http\Requests\YourRequestClassName to the method.
use App\Http\Requests\YourRequestClassName;
public function registerAction(YourRequestClassName $request)
{
//rest of the controller code
As Kyslik said, adding this logic to a Request would make things a little neater in your controller.
I tend to go with the following style of a Request containing the validation rules and custom validation messages. In your case it could look something like this:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Validator;
class LoginRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
if ($this->input('logintype') == 'register') {
return [
'option.*' => 'required|integer',
'quantity.*' => 'required|integer',
'conditions' => 'required',
'comission' => 'required',
];
}
return [
'option.*' => 'integer',
'quantity.*' => 'required|integer',
'comission' => 'required',
];
}
public function messages()
{
if ($this->input('logintype') == 'register') {
return [
'option.integer' => 'Debe introducir una opción válida',
'quantity.required' => 'Introduzca una cantidad a comprar',
'quantity.integer' => 'Debe introducir una cantidad válida',
'quantity.*.max' => 'Se ha superado el límite máximo de tickets por persona',
'conditions.required' => 'Debe aceptar los Términos y Condiciones',
'comission.required' => 'Debe seleccionar el método de pago',
];
}
return [
'option.integer' => 'Debe introducir una opción válida',
'quantity.required' => 'Introduzca una cantidad a comprar',
'quantity.integer' => 'Debe introducir una cantidad válida',
'quantity.*.max' => 'Se ha superado el límite máximo de tickets por persona',
'comission.required' => 'Debe seleccionar el método de pago',
];
}
public function validate()
{
return Validator::make(parent::all(), $this->rules(), $this->messages());
}
}
And in the controller use like this:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Requests\LoginRequest;
class LoginController extends Controller
{
public function search(LoginRequest $request)
{
$status_code = 200;
$response = [];
try {
$validator = $request->validate();
if ($validator->fails()) {
// throw new ValidationException or something similar
}
} catch (Exception $e) {
// Deal with it
} finally {
return response()->json($response, $status_code);
}
}
}
As you can see it makes the controller tidier.
In your LoginRequest you can customise it heavily, change rules depending on some of the inputs or the HTTP method used, e.g. different between POST and GET, etc.
Hope this helps.

How to require all Controller and Action to login to guests using already a code with multiple roles' actions?

I have this behaviors in SiteController
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout'],
'rules' => [
[
//El administrador tiene permisos sobre las siguientes acciones
'actions' => ['logout'],
//Esta propiedad establece que tiene permisos
'allow' => true,
//Usuarios autenticados, el signo ? es para invitados
'roles' => ['#'],
//Este método nos permite crear un filtro sobre la identidad del usuario
//y así establecer si tiene permisos o no
'matchCallback' => function ($rule, $action) {
//Llamada al método que comprueba si es un administrador
return User::isUserAdmin(Yii::$app->user->identity->rutProfesor);
},
],
[
//Los usuarios simples tienen permisos sobre las siguientes acciones
'actions' => ['logout'],
//Esta propiedad establece que tiene permisos
'allow' => true,
//Usuarios autenticados, el signo ? es para invitados
'roles' => ['#'],
//Este método nos permite crear un filtro sobre la identidad del usuario
//y así establecer si tiene permisos o no
'matchCallback' => function ($rule, $action) {
//Llamada al método que comprueba si es un usuario simple
return User::isUserSimple(Yii::$app->user->identity->rutProfesor);
},
],
],
],
//Controla el modo en que se accede a las acciones, en este ejemplo a la acción logout
//sólo se puede acceder a través del método post
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
But I don't know how to implement that the guests must need to login to access any action, even when they enter the main page. I know I have to put BeforeRequest before the rules, but I think it will affect the actions for the multiple logged users' roles. I need help, please.
Try This code i will work
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
//'only' => ['logout', 'signup','index'],
'rules' => [
[
'actions' => ['signup', 'login'],
'allow' => true,
'roles' => ['?'],///guest user//
],
[
'actions' => ['logout', 'index','test'],
'allow' => true,
'roles' => ['#'],///login user///
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
// 'logout' => ['post'],
],
],
];
}

Trouble with laravel (NotFoundHttpException)

I'm getting this error.
Symfony \ Component \ HttpKernel \ Exception \ NotFoundHttpException
I have a login view with a form, I validate the form with ajax, without a problem. When I try to return a view once I've successfuly logged in.
if ($validation->fails()){
return Response::json(array( 'success' => false, 'errors' => $validation->getMessageBag()->toArray() ));
}else if(Auth::attempt($loginData)){
$usuario=Usuario::find(Input::get('rut'));
return View::make('logged')->with(array('nombre' => $usuario->primer_nombre.' '.$usuario->apellido_paterno.' '.$usuario->apellido_materno,
'rut' => $usuario->id_usuario,
'tipo' => $usuario->id_tipo));
}else{ return Response::json(array( 'exists' => false, 'message' => 'El usuario no existe o la contraseña es inválida.' )); }
I guess the problem is in the last else statement,I get an 404 error.
This is the route:
Route::post('ingresar','LoginController#login');
The action on the form is ingresar then I use the login method in LoginController
public function login(){
if(Request::ajax()){
//validamos el formulario.
$loginData = array(
'id_usuario' => Input::get('rut'),
'password' => Input::get('password')
);
$rules = array(
'rut' => 'required',
'password' => 'required',
);
$messages = array(
'required' => 'El campo :attribute es obligatorio.',
);
$validation = Validator::make(Input::all(), $rules, $messages);
if ($validation->fails()){
return Response::json(array(
'success' => false,
'errors' => $validation->getMessageBag()->toArray()
));
}else if(Auth::attempt($loginData)){
$usuario=Usuario::find(Input::get('rut'));
return View::make('logged')->with(array('nombre' => $usuario->primer_nombre.' '.$usuario->apellido_paterno.' '.$usuario->apellido_materno,
'rut' => $usuario->id_usuario,
'tipo' => $usuario->id_tipo));
}else{
return Response::json(array(
'exists' => false,
'message' => 'El usuario no existe o la contraseña es inválida.'
));
}
}
}

Yii: Call to undefined function CDbExpression()

I'm having this error:
Fatal error: Call to undefined function CDbExpression() in C:\wamp\www\yii-related\agroplasticos\protected\models\Cliente.php on line 73
Being that file as follows (this is the exploding part in the code):
public function rules()
{
return array(
#la identificación solo podrá elegirse durante la creación y la actualización privilegiada.
array('identificacion', 'required', 'on' => 'insert, updateAdmin'),
array('identificacion', 'numerical', 'integerOnly' => true, 'on' => 'insert, updateAdmin'),
array('identificacion', 'length', 'max'=>15, 'on' => 'insert, updateAdmin'),
#el asesor solo podrá elegirse durante la actualización privilegiada.
#(durante la inserción se tomará el administrador actual como asesor)
array('id_asesor', 'filter', 'filter' => array($this, 'defaultAdministrator'), 'on' => 'insert'),
array('id_asesor', 'required', 'on' => 'updateAdmin'),
array('id_asesor', 'length', 'max'=>10, 'on' => 'updateAdmin'),
#la contraseña será requerida solamente en la inserción.
#no estará presente en la actualización (se usará otro form).
array('clave', 'filter', 'filter' => array($this, 'passwordUpdate'), 'on' => 'insert, passwordUpdate'),
array('clave', 'required', 'on' => 'insert, passwordUpdate'),
#el email será siempre requerido (y en formato de email).
array('email', 'filter', 'filter' => 'strtolower'),
array('email', 'required'),
array('email', 'email'),
array('email', 'length', 'max'=>255),
#el nombre será siempre requerido (restringiendo longitudes).
array('nombre', 'filter', 'filter' => 'strtoupper'),
array('nombre', 'required'),
array('nombre', 'match', 'pattern' => '/^([\p{L}\'\d.-]+\s*)*[\p{L}\'\d.-]+$/u'),
array('nombre', 'length', 'max'=>60, 'min'=>5),
#la ciudad será siempre requerida (solo permitimos null a las entradas ya existentes).
array('id_ciudad', 'required'),
array('id_ciudad', 'numerical', 'integerOnly' => true),
array('id_ciudad', 'length', 'max'=>10),
#la habilitacion será booleana. solamente va poder cambiarse durante actualización privilegiada.
#(durante la inserción se debe poner en 1)
array('habilitado', 'required', 'on' => 'updateAdmin'),
array('habilitado', 'boolean', 'on' => 'updateAdmin'),
array('habilitado', 'default', 'value' => 1, 'on' => 'insert'),
#la fecha va a tener un valor predeterminado durante la inserción
array('registrado_en', 'default', 'value' => CDbExpression('NOW()'), 'on' => 'insert'),
// The following rule is used by search().
array('identificacion, email, nombre, habilitado, registrado_en, id_ciudad, id_asesor', 'safe', 'on'=>'search'),
);
}
Are not those expressions (i.e. native, like CDbExpression) '__autoload'ed?
What must I do to fix it? (yii version: 1.1.14)
They are autoloaded, but only if called correctly.
This is a function call (inside an array definition):
'value' => CDbExpression('NOW()')
This creates an object:
'value' => new CDbExpression('NOW()')

Categories