Once again i'm turning to the stack community to try and solve my problem.
I'm using Slim, Twig and RedBean together to create a backend app for my website (long story short, i'm using Slim to be able to connect an API and an application to it).
(Note: I'm relatively new to RedBean so i'm not yet at ease with it)
However, i'm getting a strange exception error from a try and catch when trying to update a user.
The following points however work:
- Add user
- Delete user
When i update my user, it gives me the message "This email is already in use" which is normal since i'm it's the account's email. However, i cannot get passed the error...
Here is exception file (Models/Validation/Users.php):
class Users extends SimpleModel {
public function update() {
$firstname = trim($this->bean->firstname);
$lastname = trim($this->bean->lastname);
$email = trim($this->bean->email);
if(isset($this->bean->firstname)){
$firstname = trim($this->bean->firstname);
if(empty($firstname)) {
throw new ValidationException( 'You have to provide a firstname.' );
}
}
if(isset($this->bean->lastname)){
$lastname = trim($this->bean->lastname);
if(empty($lastname)) {
throw new ValidationException( 'You have to provide a lastname.' );
}
}
if(isset($this->bean->email)){
$email = trim($this->bean->email);
if(empty($email)) {
throw new ValidationException( 'You have to provide an email.' );
}
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new ValidationException( 'Not a valid email.' );
}
$searchUser = R::findOne( 'Users', ' email = ? ', [ $email ] );
if(!empty($searchUser)){
$equal = $this->bean->equals($searchUser);
} else {
$equal = FALSE;
}
if(!empty($searchUser) && !$equal) {
throw new ValidationException( 'This email already exists.' );
}
}
}
And the update call:
public function update( $id, $entry ) {
try {
$user = R::load( $this->config->getTable('users'), 'id = ? ', [ $id ] );
if(array_key_exists('firstname',$entry)) $user->firstname = $entry['firstname'];
if(array_key_exists('lastname',$entry)) $user->lastname = $entry['lastname'];
if(array_key_exists('email',$entry)) $user->email = $entry['email'];
(!empty($entry['password'])) ? $user->password = password_hash($entry['password'], PASSWORD_BCRYPT) : null;
R::store($user);
} catch(ValidationException $e) {
$this->errors[] = $e->getMessage();
return FALSE;
}
}
The put controller:
Class PutController extends Controllers\Controller {
public function updateRecord() {
$user = new Users($this->configManager('Database'));
$this->data['user'] = $this->app->request->post();
$password = trim($this->app->request->post('password'));
$passwordConfirm = trim($this->app->request->post('password-confirm'));
if((!empty($password) || !empty($passwordConfirm)) && ($password != $passwordConfirm)){
$this->app->errors += ["Password and the confirmation are different"];
return;
}
$user->update($this->args['id'], $this->app->request->post());
$this->app->errors += $user->getErrors();
}
}
And finally the route:
$this->app->group('/update/:id', function () {
// Display the page to update a user
$this->app->map('/', function ($id) {
$data = new Users\GetController( 'updateView', ['id' => $id] );
$data->send("Users/update.template.html");
})->via('GET');
// Post request to update a user
$this->app->map('/', function ($id) {
$data = new Users\PutController( 'updateRecord', ['id' => $id] );
if(!empty($this->app->errors)) {
$this->app->flashNow("errors", $this->app->errors);
$data->send("Users/update.template.html");
} else {
$this->app->flash("success", "Successfully updated the user.");
$this->app->redirect('../');
}
})->via('POST', 'PUT');
});
And last but not least, the twig form:
<form action="" method="POST">
<div class="form-group">
<label for="firstname">Firstname</label>
<input value="{{user.firstname}}" type="text" class="form-control" id="firstname" name="firstname" placeholder="Firstname">
</div>
<div class="form-group">
<label for="lastname">Lastname</label>
<input value="{{user.lastname}}" type="text" class="form-control" id="lastname" name="lastname" placeholder="Lastname">
</div>
<div class="form-group">
<label for="email">Email address</label>
<input value="{{user.email}}" type="email" class="form-control" id="email" name="email" placeholder="Email">
</div>
<div class="form-group">
<label for="password">New password</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
</div>
<div class="form-group">
<label for="password-confirm">Confirm your password</label>
<input type="password" class="form-control" id="password-confirm" name="password-confirm" placeholder="Password">
</div>
<input type="submit" value="Submit" class="btn btn-default">
</form>
I have no idea how to get past this error. I've tried adding freeze(true) but it did not work.
Same thing for debug, i set it to true/false and nothing changed.
If anybody has tips on how to solve this, i would be extremely greatful !
Thank you!
I actually solved my problem on my own with Davide's comment that sparked an idea.
It was a silly mistake: The equals() function from RedBean actually checks for the bean's type and that's where the problem was.
One of my bean had the type 'Users' (with capital) and the other 'users' (no capital) which was causing the exception.
Thanks to Davide for the spark! :)
Related
I am trying to do a range from -> to search of postal codes. I have two input fields and a simple method. Is it possible to use a method with 2 arguments?
Here is my method:
searchPostalCode(from:number, to:number):void{
console.log('from:' + from);
console.log('to:' + to);
}
And my inputs:
<input type="text" class="form-control col-sm-1" placeholder="from" (input)=searchPostalCode($event.target.value)>
<input type="text" class="form-control col-sm-1" placeholder="to" (input)=searchPostalCode($event.target.value)>
I'd say the most straightforward way would be to have two properties on the component and two methods updating those:
postalCodeFrom: number;
postalCodeTo: number;
updateFrom(value: number): void {
this.postalCodeFrom = value;
this.search();
}
updateTo(value: number): void {
this.postalCodeTo = value;
this.search();
}
search(): void {
// Make better checks - this will fail on 0
if (!this.postalCodeFrom || !this.postalCodeTo) {
// run some logic?
return;
}
// run the actual search.
}
Then have your inputs bound to that method:
<input type="text" class="form-control col-sm-1" placeholder="from" (input)=updateFrom($event.target.value)>
<input type="text" class="form-control col-sm-1" placeholder="to" (input)=updateTo($event.target.value)>
Of course there are other ways (like using RxJS) but the above should be good enough for the start.
Maybe you should use form module and do something like this.
myForm: FormGroup;
from = '';
to = '';
inside ngOnInit:
this.myForm = this.formBuilder.group({
from: [this.from],
to: [this.to]
});
this.myForm.controls['from'].valueChanges.subscribe(value => {
console.log(value);
});
this.myForm.controls['to'].valueChanges.subscribe(value => {
console.log(value);
});
and HTML:
<form [formGroup]="myForm">
...
<input type="text" name="from" [(ngModel)]="from" formControlName="from" placeholder="from"/>
<input type="text" name="to" [(ngModel)]="to" formControlName="to" placeholder="to"/>
...
</form>
I am currently trying to set up a EasyPost API and I need to store some information contained in a response from a POST route. I would like to send the data from the response straight to the client for storage, but I am unable to find out where or how to send the information.
This is my form receiving the information:
<div ng-controller="easypostController as epc" class="col l6">
<!-- -->
<h2>Customer address</h2>
<form class="blue-grey darken-4">
<input ng-model="epc.address.name" placeholder="Name">
<input ng-model="epc.address.street1" placeholder="Street 1">
<input ng-model="epc.address.street2" placeholder="Street 2">
<input ng-model="epc.address.city" placeholder=" City">
<input ng-model="epc.address.state" placeholder="State">
<input ng-model="epc.address.zip" placeholder="Zip">
<input ng-model="epc.address.country" placeholder="Country">
<input ng-model="epc.address.phone" placeholder="Phone">
<a class="waves-effect waves-light btn" ng-click="epc.sendAddress()">Verify</a>
</form>
</div>
This is the controller passing the information from the form to the factory:
function easypostController(easypostFactory) {
var epc = this
epc.address = {}
epc.sendAddress = function() {
epc.resId = {}
easypostFactory.send(epc.address)
.then(function(res) {
console.log("Successfullly sent address epc")
// epc.resId = easypostFactory.resId
epc.address = {}
})
// console.log(epc.resId)
}
}
This is my factory that passes the information to the server:
address.send = function(address) {
return $http.post(addressUrl, address)
// epf.resId = address
console.log(address, "=====")
}
And this is where I am having issues, I am not able to get any res.send() function to send the response object back to the client side.
var address = easypost.Address.create(req.body, function(err, fromAddress) {
var verifiedAddress = {}
fromAddress.verify(function(err, response) {
console.log("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")
if (err) {
console.log('Address is invalid.')
} else if (response.message !== undefined && response.message != null) {
console.log('Address is valid but has an issue:', response.message)
var verifiedAddress = response.address
} else {
verifiedAddress = response.address
console.log(verifiedAddress)
res.send(verifiedAddress)
}
})
})
The verifiedAddress is the correct object as logged by my server I am just unable to send the response object to the client. Any help would be greatly appreciated.
Thanks
rather than use angular js for frontend, try to use a simple html form. here is the example :
<form name="simple" action="someurl" method="post"> <input type="text" name="username"> </form>
And you can get the value of the input text by these codes :
router.post("someurl", function(req,res){ var username = req.body.username }) console.log(username)
Hope this will help you :)
I searched, I know 'the directive way' to do custom validation, but it looks like a overkill to me, I hope there is a simpler way, so I tried somwthing like this.
it works, but really not sure it is the right way(or angular way).
.controller('vali', ['$scope', function vali($scope) {
var th = this
th.formData = {}
// watch password repeat
$scope.$watch(function() {
return th.password1
}, function(newPass) {
if(!customValidate(newPass)) th.form.pass2.$setValidity('custom', false)
else th.form.pass2.$setValidity('custom', true)
})
//custom validate: password repeat must equal to password
function customValidate(v) {
if(v === th.formData.password) return true
else return false
}
this.submit = function(form) {
if(!th.form.$invalid) th.postToServer(th.formData)
}
this.postToServer = function(data) {
//do post to server
console.log(data)
}
}])
html:
<div ng-controller='vali as v'>
<form name='v.form' ng-submit='v.submit'>
<input type='password' name='pass1' ng-model='v.formData.password' minlength='6' />
<input type='password' name='pass2' ng-model='v.password1' />
<div ng-messages='v.form.pass2.$error' ng-if='v.form.pass2.$dirty'>
<div ng-message='required'>required</div>
<div ng-message='custom'> not equal</div>
</div>
<button type='submit'>submit</button>
</form>
</div>
You don't need to create your own directive for this. There is already a built-in directive for the password validation.
You can use that like this :
<input name="password" required ng-model="password">
<input name="confirm_password"
ui-validate=" '$value==password' "
ui-validate-watch=" 'password' ">
The input will be valid when the expression in ui-validate is true, so you can have any validation you want by changing the expression.
I have created a login function. At the moment when correct login details are entered it logs in the employee and if inaccurate details are entered shows error message. Issue is if a employee enters a correct username but wrong case it still logs in the employee. For example, if there is a employee in the database with username "admin", if I enter username as "ADMIN" or "Admin" with correct password in login, it will still log in the employee. My code is as follows:
employeesController:
<?php
class EmployeesController extends AppController {
//some code here
public function login()
{
$username=$this->request->data['username'];
App::uses('SimplePasswordHasher', 'Controller/Component/Auth');
$passwordHasher = new SimplePasswordHasher();
$password = $passwordHasher->hash($this->request->data['password']);
$msg = $this->Employee->authenticateUser($username,$password);
if($msg)
{
foreach ($msg as $userdetails)
{
$usertype=$userdetails['Employee']['access_level'];//either admin or staff
}
//set session variables to limit authority
$this->Session->write(array('User' => array(
'usertype' => $usertype
)));
$this->render("../Pages/index1");
$this->layout = '../Pages/index1';
}
else{
$this->set('error',$username);
$this->render("../Pages/home"); //login page is the home page
$this->layout = '../Pages/home';
}
}
}
home.ctp:
<head>
<script>
function validateForm()
{
var x=document.forms["myForm"]["username"].value;
var y=document.forms["myForm"]["password"].value;
if (x==null || x=="")
{
alert("Please Enter Username")
return false;
}
if (y==null || y=="")
{
alert("Please Enter Password")
return false;
}
}
</script>
</head>
<div class="users form">
<br>
<br>
<br>
<form name="myForm" action="Employees/login" onsubmit="return validateForm()" method="post" >
<?php
if (isset($error)) {
echo "<p style='color:red;font-size: 20px''>Username or Password is invalid. Please try again.</p>";
}?>
<p>Enter Username:
<input type="text" name="username" placeholder="username" style="height: 25px;width: 160px;"/></p>
<br><br>
<p>Enter Password:
<input type="password" name="password" placeholder="password" style="height: 25px;width: 160px;"/></p>
<br>
<input type="submit" style="height:35px;width:100px;font-size: 18px; align:center;" value="Sign in">
</form>
</div>
Can someone please help? I want only the exact username to be able to log in.
regardless the framework you are using this problem depends on th charset of your DB.
Problably you are using an *_ci charset (case insensitive).
Also *_cs (case sensitive) charset exists if you really need it.
There is an Angular seed using Firebase and AngularFire on github form the Firebase team that I am trying to understand how works. The login page looks like this:
<form>
<label>
<span>email</span>
<input type="text" ng-model="email" />
</label>
<label>
<span>password</span>
<input type="password" ng-model="pass" />
</label>
<label ng-cloak ng-show="createMode">
<span>confirm pass</span>
<input type="password" ng-model="confirm" />
</label>
<button ng-click="login()" ng-hide="createMode">Log In</button>
<button ng-click="createMode = true" ng-hide="createMode">Register</button>
<button ng-cloak ng-show="createMode" ng-click="createAccount()">Create Account</button>
<button ng-cloak ng-show="createMode" ng-click="createMode = false">Cancel</button>
<p ng-show="err" class="error">{{err}}</p>
</form>
And the controller for the login-function looks like this:
$scope.login = function(cb) {
$scope.err = null;
if( !$scope.email ) {
$scope.err = 'Please enter an email address';
}
else if( !$scope.pass ) {
$scope.err = 'Please enter a password';
}
else {
loginService.login($scope.email, $scope.pass, function(err, user) {
$scope.err = err? err + '' : null;
if( !err ) {
cb && cb(user);
}
});
}
The view calls the login function like this: login(), but in the controller the function definition starts like this $scope.login = function(cb) and then cb is used in the function. But the function is never called with any variable/object, so what is happening with cb here?
The parameter is not used when calling login function from the template, but if you look at $scope.createAccount function definition in the controller, it calls the same $scope.login function, but with defined callback parameter