Note: I ended up finding out that the problem was caused by a syntax error on the controller itself.
Ok so, I'm using Laravel to develop a platform.
I have a form that allows the user to register a domain. This form is submited through ajax to "[my domain]/thedomains/create". Here is the code that does so:
$("#btn_doms_create_submit").click(function (){
$.ajax({
type: 'GET',
url: "/thedomains/create",
data: { _token : $("input[name=\"_token\"]").val(),
domain : $("input[name=\"create_dom\"]").val(),
field_ip : $("input[name=\"create_ip\"]").val(),
obs : $("textarea[name=\"create_obs\"]").val(),
active : $("input[name=\"create_active\"]").is(":checked")+"",
itld : $("input[name=\"create_itld\"]").is(":checked")+"" },
dataType: 'json',//returned data
success: function(data){
if (data["errors"] == "")
{
toastr.success(data.message);
$("#doms_create").modal("hide");
updateTable();
}
else
{
var txtError = "";
for (error in data.errors) {
txtError += "<li>" + data.errors[error] + "</li>";
}
toastr.warning(data.message + "<ul>" + txtError + "</ul>");
if (data.errors.domain != null) {
$("#div_create_dom").attr("class","form-group has-error");
}
if (data.errors.field_ip != null) {
$("#div_create_ip").attr("class","form-group has-error");
}
}
}
});
});
The code behind "/thedomains/create" is
public function create(Request $request) {
$return_val = [ "message" => trans("system.dom_succ", ["name" => $request->dom]),
"errors" => "" ];
$validator = Validator::make($request->all(), [
"domain" => "required|max:255|url",
"field_ip" => "max:255"
],[
"domain.required" => trans("system.val_dom_required"),
"domain.max" => trans("system.val_dom_max"),
"domain.url" => trans("system.val_dom_url")
]);
if (!$validator->fails()) {
$dom = new Doms;
$dom->name = $request->domain;
$dom->ip = $request->ip;
$dom->obs = $request->obs;
if ($request->active == "true")
$dom->status = true;
else
$dom->status = false;
if ($request->itld == "true")
$dom->is_top_level_domain = true;
else
$dom->is_top_level_domain = false;
} else {
$return_val["message"] = trans("system.note_errors");
$return_val["errors"] = $validator->errors();
}
return json_encode($return_val);
}
As you can see, I have a validation to verify that all the required data is present and valid, according to the needed standards.
The problem is: When I submit this form with some invalid domain or with no domain at all, the verification occurs naturally, the return is given, etc. But when I have a valid domain, the validation throughs the following error on my browser's (chrome) console:
GET [my domain]/thedomains/create?_token=2vsOrtkcWGid5Ex2HegtY3Fw2E…aE&domain=http%3A%2F%2Ftecnosece.com&field_ip=&obs=&active=true&itld=false 403 (Forbidden)
Idk why this happens. I've already changed the route from "domains" to "thedomains", thinking there could be some kind of blocking from my host, but that didn't solve the problem.
Any idea of what's happening?
Edit:
As requested, here is my routes portion for "/thedomains":
Route::group(['prefix' => 'thedomains'], function () {
Route::get("/",function () {
return view("doms");
});
Route::get("/all", "DomsController#getAll");
Route::post("/get", "DomsController#get");
Route::get("/create", "DomsController#create");
Route::post("/edit", "DomsController#edit");
Route::post("/del", "DomsController#del");
Route::get("/search", "DomsController#search");
Route::post("/migrate", "DomsController#migrate");
});
Related
I'm looking for a way to display validation errors in jQuery after sending a form in ajax that returns validation errors in JSON.
My code works for simple form, but the difficulties appear for more complex forms, especially for forms containing inputs for associated data.
For example :
Here is a form containing input files and associated data for writing captions :
// Articles/edit.php
$this->Form->create($article);
echo $this->Form->control('title');
echo $this->Form->control('photos.0.legend');
echo $this->Form->control('photos.1.legend');
$this->Form->end();
I post the form in ajax to my ArticlesController's edit method that looks like that :
// ArticlesController.php
public function edit($id)
{
$article = $this->Articles->findById($id)->firstOrFail();
if ($this->request->is(['post', 'put'])) {
$article = $this->Articles->patchEntity($article, $this->request->getData());
if ($this->Articles->save($article)) {
$redirection = ['action' => 'index'];
if ($this->request->is('ajax')) {
die(json_encode(['error' => false, 'redirection' => Router::url($redirection)]));
}
return $this->redirect($redirection);
}
else {
if ($this->request->is('ajax')) {
die(json_encode(['error' => true, 'validationErrors' => $article->getErrors()]));
}
}
}
$this->set(compact('article'));
}
Here is the return of validation errors in JSON :
{
"error": true,
"validationErrors": {
"title": {
"_empty": "The title please."
},
"photos": { // validation errors are nested
"1": {
"legend": {
"_empty": "The legend please."
}
}
}
}
}
Here is how I'm tring to display validation errors :
// Articles/edit.php
$('form')
.fileupload({ // It sends the form in ajax
dataType: 'json',
// [...]
done: function (e, data) {
var responseJSON = data.jqXHR.responseJSON;
if (!responseJSON.error) { // There's no error => redirect
window.location = responseJSON.redirection;
}
else { // The form contains validation errors
$.each(responseJSON.validationErrors, function (field, errors) {
displayFieldErrors(field, errors);
});
}
},
// [...]
});
// Display validation errors in a field
function displayFieldErrors(field, errors)
{
var fieldId = field.replace(/_/, '-');
var input = $("#" + fieldId);
var errorMessage = '';
$.each(errors, function (key, message) {
errorMessage = errorMessage + message + '<br>';
});
input.parents('.input').addClass('error');
input.after('<div class="error-message">' + errorMessage + '</div>');
}
The problem is that validation errors for associated data fields are nested (e.g photos), so how to get the input's id involved ?
Could anyone help me to find a correct implementation for my jQuery function displayFieldErrors() ?
I've solved the problem by returning formated validation errors from a JSON View (server side) :
// in Articles/json/edit.php
$errors = [];
// Recursive function to build `$errors[]` associating each field in error to one or many error message(s)
$fieldsInError = function ($err, $buildingField = '') use (&$errors, &$fieldsInError) {
foreach ($err as $key => $value) {
if (is_array($value)) {
$fieldsInError($value, empty($buildingField) ? $key : $buildingField . '.' . $key); // recursive
}
else { // string
if (isset($errors[$buildingField])) {
if (is_array($errors[$buildingField])) {
$errors[$buildingField][] = $value;
}
else {
$errors[$buildingField] = [$errors[$buildingField], $value];
}
}
else {
$errors += [$buildingField => $value];
}
}
}
};
$fieldsInError($article->getErrors());
echo json_encode(['error' => true, 'validationErrors' => $errors]));
JSON is now looking like that :
{
"error": true,
"validationErrors": {
"title": "The title please.",
"photos.1.legend": "The legend please."
}
}
I need to check the field phone_mobile for duplicate into the database. If a field value is not a duplicate then continue saving.
And if such a phone already exists in the database, then show the alert message and stop the process(form submission).
My actions:
In the file ./modules/Contacts/metadata/editviewdefs.php connected custom js file:
$viewdefs['Contacts']['EditView'] = array(
'templateMeta' => array(
'includes' => array (
array (
'file' => 'custom/include/javascript/custom_contact.js'
),
),
'form'=>array(
...
Works great.
In custom_contact.js file overload check_form(formname) function:
function check_form(formname)
{
if(formname === 'correct')
{
// This part does not work right for me
var _form = document.getElementById('EditView');
_form.action.value='Save';
SUGAR.ajaxUI.submitForm(_form);
return false;
}
if(formname === 'EditView')
{
// Ajax query works perfectly
$.ajax({
url : '/',
method : 'POST',
data : {},// some data
success : function(data) {
data = JSON.parse(data);
if(!data.success)
{
var text = 'The phone already exists';
return false;
}
check_form('correct');
}
});
}
return false;
}
But the if(formname === 'correct') ... block does not work correctly.
I need to stop the work of the form_save and include when necessary.
Please help to solve the problem correctly.I'm new to SugarCRM.
This is something related to javsacrip/jquery error handling and you can find many logics on google as well.
Try following code:
// DOM Ready
$('input#PHONE_FIELD_ID').on('change', function () {
handlePhoneValidation();
return false;
});
var clickAttr = $("#SAVE_BUTTON_ID").attr("onclick");
$("#SAVE_BUTTON_ID").attr("onclick","return handlePhoneValidation(); "+clickAttr);
function handlePhoneValidation(){
clear_all_errors();
var node = $('input#PHONE_FIELD_ID');
current_val = node.val();
/*
* Your validation will go here
* if condition fail then return false otherwise true
*/
return false;
}
I resolved this another way
./custom/modules/Module_name/metadata/editviewdefs.php
$viewdefs ['Accounts'] = [
'EditView' => [
'templateMeta' => [
'form' => [
'includes' => [
[
// include custom js file
'file' => 'modules/Module_name/file_name.js'
],
'buttons' => [
// Override save button and return after click custom function
0 => array (
'customCode' => '<input type="submit" name="save" id="save" onClick="this.form.return_action.value=\'DetailView\'; this.form.action.value=\'Save\'; return check_custom_data(\'EditView\'); " value="'.$GLOBALS['app_strings']['LBL_SAVE_BUTTON_LABEL'].'">',
),
'CANCEL',
After
modules/Module_name/file_name.js:
// Function check_custom_data() :
function check_custom_data(formname)
{
if(formname === 'correct')
{
var _form = document.getElementById('EditView');
_form.action.value='Save';
SUGAR.ajaxUI.submitForm(_form);
return check_form('EditView');
}
if(formname === 'EditView')
{
$.ajax({
url : '/',
method : 'POST',
data : { }, // Some data
success: function(data) {
data = JSON.parse(data);
if(!data.success)
{
// Some code
return false;
}
}
// If everything is ok
check_custom_data('correct');
}
});
return false;
}
This is working for me.
There is my form:
$form = ActiveForm::begin([
'id' => 'user-create-form',
'enableAjaxValidation' => true,
'enableClientValidation' => false,
'validationUrl' => Url::toRoute(Yii::$app->controller->id . '/validation'),
'validateOnType' => true,
]);
JS-script is registered on this form and performed Russian to English transliteration according to some rules on .keyup() event. Transliteration result is added to samname field.
There is validation rule in UserCreateForm model:
public function rules()
{
return [
[['samname'], 'validateUserExist'],
];
}
public function validateUserExist()
{
$check = Yii::$app->CustomComponents->checkUserExist($this->samname);
if ($check) {
$errorMessage = 'User exists: ' . $check;
$this->addError('samname', $errorMessage);
}
}
Function checkUserExist() checks existing of created name and returns an error in matching case.
There is action on controller:
public function actionValidation()
{
$model = new UserCreateForm();
if (\Yii::$app->request->isAjax && $model->load(\Yii::$app->request->post())) {
\Yii::$app->response->format = Response::FORMAT_JSON;
echo json_encode(ActiveForm::validate($model));
\Yii::$app->end();
}
}
It works great, validation is performed, matching case returns an error...
But!
It's required that JS-script is run again and added next letter to the name on error (JS-script provides this functionality). How to run JS-script again after validator was return an error?
#yafater Thanks for help! I find solution.
$('form').on('afterValidateAttribute', function (event, attribute, message) {
if (attribute.name === 'samname')
{
$.ajax({
url: "url-to-action",
type: "POST",
dataType: "json",
data: $(this).serialize(),
success: function(response) {
if ( typeof(response["form-samname"]) != "undefined" && response["form-samname"] !== null ) {
// code here
}
},
});
return false;
}
});
I am working on an application using Cakephp on the server side and PhoneGap at the client Side, with JSON as a intermediate to access the server side.
Now, I am working specifically on a login form where the user needs to enter his/her username and password. I put in my controller the following:
public function api_login() {
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Authorization");
if ($this->request->data && isset($this->request->data['username']) && isset($this->request->data['password'])) {
$arrUser = $this->User->find('all',array(
'conditions'=>array(
'username'=> $this->request->data['username'],
'password' => $this->request->data['password']
)
));
if (count($arrUser) > 0 ) {
$this->Session->write('Auth.User',$arrUser[0]['User']);
$arrReturn['status'] = 'SUCCESS';
$arrReturn['data'] = array('loginSuccess' => 1,'user_id' => $arrUser[0]['User']['id'] );
}
else {
$arrReturn['status'] = 'NOTLOGGEDIN';
$arrReturn['data'] = array( 'loginSuccess' => 0 );
}
} else {
$arrReturn['status'] = 'NOTLOGGEDIN';
$arrReturn['data'] = array( 'loginSuccess' => 0 );
}
echo json_encode($arrReturn);
}
and in the client side, I am retrieving what JSON encoded as follows:
<script>
$(document).ready(function(){
$('form').on('submit',function(e){
e.preventDefault();
$username = $("#form-username").val();
$password = $("#form-password").val();
$.ajax({
url : "http://localhost/teslaphonegap_cakephp/" + 'login.json',
cache : false,
data : {
'username' : $username,
'password' : $password },
dataType : 'json',
type : 'POST',
success : function(result) {
if(result.status=="SUCCESS"){
alert("success");
console.log(result);
}else{
alert("username or pass are wrong");
console.log(result);
} },
error : function(xhr, status, err) {
alert("ERROR");
}
});
});
});
</script>
and in my Model I used the beforeSave() in order to hash the passwords before they get added at the very beginning in the Database:
public function beforeSave($options = array()) {
$value=$this->data['User']['password'];
$encrypted = Security::encrypt($value, Configure::read('Security.cipherCriptKey'));
$this->data['User']['password'] = $encrypted;
return true;
}
Now, when I try to login it always returns the error message because it compares a value that is unhashed with other values that are already hashed in my Database. How can I solve this issue? I used the afterFind() but it didn't work:
public function afterFind($results, $primary = false) {
foreach ($results as $key => $val) {
if(isset($val['User']['password'])){
$results['User']['password'] = Security::decrypt($val['User']['password'], Configure::read('Security.cipherCriptKey'));
}
return $results;
}
}
-- EDIT
and in my core.php I used the following:
Configure::write('Security.cipherCriptKey','su0HKssPmdbwgK6LdQLqzp0Y7zOmyaTI');
First of all, your afterFind() callback won't work as expected.
The line
$results['User']['password'] = Security::decrypt($val['User']['password'], Configure::read('Security.cipherCriptKey'));
should be written as
$results[$key]['User']['password'] = Security::decrypt($val['User']['password'], Configure::read('Security.cipherCriptKey'));
However, changing this won't fix your problem. If you search the database for a record with a password matching $this->request->data['password'], it will return no results. Note that the password in the database is hashed.
You have to fetch the record from table users that matches $this->request->data['username'], decrypt the value of field password and compare it against $this->request->data['password'].
Decryption is already taken care by afterFind(), so your code could be written as follows:
if ($this->request->data && isset($this->request->data['username']) && isset($this->request->data['password'])) {
$arrUser = $this->User->find('first',array(
'conditions'=>array(
'username'=> $this->request->data['username'],
)
));
if ($this->request->data['password'] == $arrUser['User']['password']) {
$this->Session->write('Auth.User',$arrUser['User']);
$arrReturn['status'] = 'SUCCESS';
$arrReturn['data'] = array('loginSuccess' => 1,'user_id' => $arrUser['User']['id'] );
//rest of your code
I'm creating a login system in laravel. On my local server, the code works but when I put it on a live server, the Auth::check() keeps return false and thus when I login with the right credentials it redirects me back to login page again. FYI My liver server is using php 5.4 while my local server is using php 5.5
Here is my code.
routes.php
Route::get('/', function() {
//Auth::check() KEEPS RETURNING FALSE EVEN WHEN USER LOGS IN
if (Auth::check() == true) {
$role = Auth::user()->role;
if ($role == 1) {
return View::make('administrator');
} elseif ($role == 9) {
return View::make('agent');
}
} else {
return View::make('login');
}
});
LoginController.php
public function login() {
if (Auth::attempt(array('username' => Input::json('username'), 'password' => Input::json('password')))) {
return Response::json(Auth::user());
} else {
return Response::json(array('flash' => 'Invalid email or password'), 500);
}
}
}
angularcontroller.js
$scope.login = function() {
//assign variables
var post = {};
post.username = $scope.info.username;
post.password = $scope.info.password;
//Validation
var errors = 0;
if (errors == 0) {
loginServ.login(post).then(function(data) {
if (data.status == 500) {
alert('wrong username or password');
} else {
window.location.replace("");
}
});
}
};
angular_service.js
login_module.factory('loginServ', function($http, $q) {
return {
login: function(post) {
var url = "login/login";
return $q.all([
$http.post(url, {
username: post.username,
password: post.password
})
])
.then(function(results) {
var data = [];
angular.forEach(results, function(result) {
data = data.concat(result.data);
// console.log("data: "+result);
// console.log("result.data: "+result.data);
});
return data[0];
},
function(error) {
console.log(error.status);
return error;
// Handle error here
});
}
}
});
I have login form using angularjs. It sends a POST request and if it gets a 200 response then it sends a GET request to "/". However even with right login credentials it keeps going back to the same login page.
Thanks
Try to change the value in app\config\session.php => 'cookie'.
This should fix the issue