What i'm doing wrong?
<?php
public function login() {
$user_name = time();
User::create(array(
'name' => $user_name,
'email' => $user_name.'#test.com',
'password' => Hash::make('123123'),
));
$user = array(
'email' => $user_name.'#test.com',
'password' => '123123',
);
$m = User::where('email' , '=', $user_name.'#test.com')->first();
dd([
'Auth::attempt($user)',
Auth::attempt($user),
'Auth::check()',
Auth::check(),
'Hash::check($m->password, \'123123\')',
Hash::check($m->password, '123123')
]);
}
Result:
array(6) {
[0]=>
string(20) "Auth::attempt($user)"
[1]=>
bool(false)
[2]=>
string(13) "Auth::check()"
[3]=>
bool(false)
[4]=>
string(38) "Hash::check($user->password, '123123')"
[5]=>
bool(false)
}
Not sure what information should I add.
app/config/auth.php
'driver' => 'eloquent',
'model' => 'User',
'table' => 'users',
app/config/app.php
'key' => 'DMmiPAxSYz4O2jG44S92OcdPZN7ZsGGs',
'cipher' => MCRYPT_RIJNDAEL_256,
models/User.php
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* Validation rules
*/
public static $rules = array(
'name' => 'required',
'email' => 'email|required|unique',
'password' => 'min:6',
);
/**
* Validation rules
*/
public static $messages = array(
'name.required' => 'The name field is required',
'email.email' => 'The email field must contain properly formatted email.',
'email.required' => 'The email field is required',
'password.required' => 'The password field is required',
'password.min:6' => 'The password must be minimum 6 characters long',
);
protected $table = 'users';
protected $hidden = array('password', 'remember_token');
protected $guarded = array('id');
public function setPasswordAttribute($value) {
if ($value) {
$this->attributes['password'] = Hash::make($value);
}
}
}
Well here's some checks that you can do
Have you setup config/auth.php with driver, model and table?
Have you filled the fillable array of the User's model?
Have you change the key inside config/app.php ?
Also try to dd($m) in order to see what you got from that query.
I found what is wrong.
This part of code hash password for first time:
User::create(array(
'name' => $user_name,
'email' => $user_name.'#test.com',
'password' => Hash::make('123123'), // <---- first time
));
And this mutator in User model does hashing for second time before put password to database:
public function setPasswordAttribute($value) {
if ($value) {
$this->attributes['password'] = Hash::make($value); // <---- second time
}
}
So I just changed first block to this:
User::create(array(
'name' => $user_name,
'email' => $user_name.'#test.com',
'password' => '123123', // <---- no hashing here
));
Related
I am manually implementing user registration within my application and I have failed to understand this section of laravel 8 docs
If you are manually implementing registration within your application instead of using a starter kit, you should ensure that you are dispatching the Illuminate\Auth\Events\Registered event after a user's registration is successful:
use Illuminate\Auth\Events\Registered;
event(new Registered($user));
I tried different approaches but in the end i failed to understand this and email is not being sent
Here is my registration code
public function storeUser(Request $request){
$validated = $request->validate([
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email:rfc,dns',
'password' => ['required','confirmed', Password::min(8)],
'phone_number' => 'required'
]);
$registeredDetails = User::create([
'first_name' => $request->first_name,
'last_name' => $request->last_name,
'email' => $request->email,
'password' => Hash::make($request->password),
'phone_number' => $request->phone_number
]);
}
My question is where do I dispatch this event the documentation is saying?
Here is the top of my UserControler
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Auth\Events\Registered;
and here is the mail code in env
MAIL_MAILER=smtp
MAIL_HOST=kokayazanzibar.com
MAIL_PORT=465
MAIL_USERNAME=demo#kokayazanzibar.com
MAIL_PASSWORD=ienteredmypasswordhere
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=demo#kokayazanzibar.com
MAIL_FROM_NAME="${APP_NAME}"
Here is EventServiceProvider
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*
* #return void
*/
public function boot()
{
//
}
}
You would dispatch this after the user is created in your application.
In your case:
$validated = $request->validate([
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email:rfc,dns',
'password' => ['required','confirmed', Password::min(8)],
'phone_number' => 'required'
]);
$registeredDetails = User::create([
'first_name' => $request->first_name,
'last_name' => $request->last_name,
'email' => $request->email,
'password' => Hash::make($request->password),
'phone_number' => $request->phone_number
]);
event(new Registered($registeredDetails));
I did not implement the interface on my User Model.
It was
class User extends Authenticatable
{
I thought I put it well but I was missing this implementation and was supposed to be like this
class User extends Authenticatable implements MustVerifyEmail
{
and now its working.
I've changed the auth.php file in order to authenticate my users according to authors table. But I keep getting No account for you when I'm running test route.
auth.php
<?php
return array(
'driver' => 'eloquent',
'model' => 'Author',
'table' => 'authors',
'reminder' => array(
'email' => 'emails.auth.reminder', 'table' => 'password_reminders',
),
);
routes.php
Route::get('test', function() {
$credentials = array('username' => 'giannis',
'password' => Hash::make('giannis'));
if (Auth::attempt($credentials)) {
return "You are a user.";
}
return "No account for you";
});
AuthorsTableSeeder.php
<?php
class AuthorsTableSeeder extends Seeder {
public function run()
{
// Uncomment the below to wipe the table clean before populating
DB::table('authors')->delete();
$authors = array(
[
'username' => 'giannis',
'password' => Hash::make('giannis'),
'name' => 'giannis',
'lastname' => 'christofakis'],
[
'username' => 'antonis',
'password' => Hash::make('antonis'),
'name' => 'antonis',
'lastname' => 'antonopoulos']
);
// Uncomment the below to run the seeder
DB::table('authors')->insert($authors);
}
}
Addendum
I saw in another post that you have to implement the UserInterface RemindableInterface interfaces. But the result was the same.
Author.php
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Author extends Eloquent implements UserInterface, RemindableInterface {
protected $guarded = array();
public static $rules = array();
public function posts() {
return $this->hasMany('Post');
}
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return "giannis#hotmail.com";
}
}
You don't need to Hash your password when you are using Auth::attempt(); so remove Hash::make from routes
Route::get('test', function() {
$credentials = array('username' => 'giannis',
'password' => 'giannis');
if (Auth::attempt($credentials)) {
return "You are a user.";
}
return "No account for you";
});
and it will work like a charm!
I have a form with 2 fields (username, password) and a mysql table with those 2 same fields (username, password), and I authentication system working properly :)
But, I can not make it work if my table fields have different names, for example: (my_user, my_pass).
If you just change the username field on the other also works for me, that gives me problems is the password field.
My config auth.php
'driver' => 'eloquent'
Update
Already found the solution in my controller, the password name can not change.
Before (WRONG):
What I've done in first place was wrong
$userdata = array(
'my_user' => Input::get('my_user'),
'my_pass' => Input::get('my_pass')
);
it should be
$userdata = array(
'my_user' => Input::get('my_user'),
'password' => Input::get('my_pass')
);
You can define you own username and password field in the auth.php inside the config folder.
return array(
'driver' => 'eloquent',
'username' => 'my_user',
'password' => 'my_pass',
'model' => 'User',
'table' => 'users',
);
I hope this can be of some help.
I ran into this same problem. You need to extend your model:
// User.php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $fillable = array('name','passwd','email','status','timezone','language','notify');
protected $hidden = array('passwd');
protected $table = "users_t";
protected $primaryKey = "uid";
public static $rules = array(
'name' => 'required',
'passwd' => 'required',
'email' => 'required'
);
public function getAuthIdentifier() {
return $this->getKey();
}
public function getAuthPassword() {
return $this->passwd;
}
public function getReminderEmail() {
return $this->email;
}
public static function validate($data) {
return Validator::make($data,static::$rules);
}
}
You need to implements this methods too:
public function getRememberToken(){
}
public function setRememberToken($value){
}
public function getRememberTokenName(){
}
Hello I'm trying ZF2 form with an input file.
I have a form with a file input and I want to insert the randomize name into my db.
How I can return the randomized name?
thanks.
This is the simple form class:
class OrdineForm extends Formhttp://stackoverflow.com/questions/ask
public function __construct($name = null)
{
parent::__construct('ordine');
$this->setAttribute('method', 'post');
$this->addElements();
$this->addInputFilter();
}
public function addElements(){
$this->add(array(
'name' => 'pdf',
'attributes' => array(
'type' => 'text',
'disabled' =>'true',
),
'options' => array(
'label' => 'PDF',
),
));
// FILE INPUT
$file = new File('file');
$file
->setLabel('PDF attach')
->setAttributes(array(
'id' => 'file',
));
$this->add($file);
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Add',
'id' => 'submitbutton',
'class' => 'btn btn-success'
),
));
}
public function addInputFilter()
{
$inputFilter = new InputFilter\InputFilter();
$fileInput= new FileInput('file');
$fileInput->setRequired(false);
$fileInput->getFilterChain()->attachByName(
'filerenameupload',
array(
'target' => './public/tmpuploads/',
'randomize' => true,
"UseUploadname" => true,
)
);
$inputFilter->add($fileInput);
$this->setInputFilter($inputFilter);
}
}
After you have validated the form in your controller you can use $form->getData();
there should be a key 'file' as that is what you named your file element. Within that a key 'tmp_name'.
This will be the randomized name.
Eg:
public function uploadfileAction()
{
//get form and filter
$form = $this->getServiceLocator()->get('SomeModule\Form\UploadFileForm');
$filter = $this->getServiceLocator()->get('SomeModule\Form\UploadFileFilter');
$form->setInputFilter($filter->getInputFilter());
if ($this->getRequest()->isPost()) {
//merge files with post
$post = array_merge_recursive(
$this->getRequest()->getPost()->toArray(),
$this->getRequest()->getFiles()->toArray()
);
//set data in form
$form->setData($post);
//check is valid- form data will now contain new name
if ($form->isValid()) {
var_dump($form->getData());
}
}
}
The resulting array dump may look something like this:
array(13) {
["file"]=>
array(5) {
["name"]=>
string(14) "some-pdf.pdf"
["type"]=>
string(24) "application/pdf"
["tmp_name"]=>
string(46) "/public/tmpuploads/new-randomized-name.pdf"
["error"]=>
int(0)
["size"]=>
int(651264)
}
["submit"]=>
string(6) "Submit"
["csrf"]=>
string(32) "4df771bb2fb14e28992a408583745946"
}
You can then just do:
$formData = $form->getData();
$fileNewLocation = $formData['file']['tmp_name'];
//do what you want with $fileNewLocation
Back in May, I posted this question. I'm trying to do the same thing again on a different app, but I haven't found a solution to this problem. I do have more information and better code, so I'm hoping you guys can help me sort this out.
Use Case:
Doctor's office has a website with admin users. The users login successfully with CakePHP's Auth via User model and UsersController.
Doctors have referring physicians with completely different profiles and actions. Doctors need to login via example.com/physicians/login. However, this login is failing with this
authError => 'You are not authorized to access that location.'
Here is my code in AppController:
class AppController extends Controller {
public $helpers = array('Form', 'Html', 'Time', 'Session', 'Js' => array('Jquery'));
public $components = array(
'Session',
'Auth' => array(
'autoRedirect' => false,
'authorize' => 'Controller'
)
);
public function beforeFilter() {
$this->Auth->allow('index', 'view', 'edit', 'display', 'featured', 'events', 'contact', 'signup', 'search', 'view_category', 'view_archive', 'addComment', 'schedule', 'login');
}
}
And here is my UsersController that is working:
class UsersController extends AppController {
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'userModel' => 'User',
'fields' => array(
'username' => 'username',
'password' => 'password'
)
)
),
'loginRedirect' => array('controller' => 'users', 'action' => 'admin'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'index'),
'loginAction' => array('controller' => 'users', 'action' => 'login'),
'sessionKey' => 'Admin'
)
);
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('add', 'login', 'logout');
}
function isAuthorized() {
return true;
}
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
public function logout() {
$this->Session->destroy();
$this->redirect($this->Auth->logout());
}
Here is my PhysiciansController code that is NOT working:
class PhysiciansController extends AppController {
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'userModel' => 'Physician',
'fields' => array(
'username' => 'username',
'password' => 'password'
)
)
),
'loginRedirect' => array('controller' => 'physicians', 'action' => 'dashboard'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'index'),
'loginAction' => array('controller' => 'physicians', 'action' => 'login'),
'sessionKey' => 'Physician'
)
);
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->authorize = array(
'Actions' => array(
'userModel' => 'Physician',
'actionPath' => 'physicians'
)
);
$this->Auth->allow('login', 'logout');
// $this->Session->write('Auth.redirect','/physicians/index');
}
function isAuthorized() {
return true;
}
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->redirect(array('controller' => 'physicians', 'action' => 'dashboard'));
} else {
$this->Session->read();
debug($this->Auth);
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
public function logout() {
$this->Session->destroy();
$this->redirect($this->Auth->logout());
}
I really don't want to start over and switch to ACL -- I'm not sure that's necessary for just two logins. Help would be very much appreciated!
EDIT: Joshua's answer below is awesome and super helpful. I implemented it, but I'm still receiving an unauthorized error when I try to login as a Physician via /phys/physican/login (prefix/controller/action). The Admin setup works great. Here's the debug code when I try to login:
object(AuthComponent) {
components => array(
(int) 0 => 'Session',
(int) 1 => 'RequestHandler'
)
authenticate => array(
'Form' => array(
'userModel' => 'Physician'
)
)
authorize => false
ajaxLogin => null
flash => array(
'element' => 'default',
'key' => 'auth',
'params' => array()
)
loginAction => array(
'controller' => 'physicians',
'action' => 'phys_login'
)
loginRedirect => null
logoutRedirect => '/'
authError => 'You are not authorized to access that location.'
allowedActions => array()
request => object(CakeRequest) {
params => array(
'prefix' => '*****',
'plugin' => null,
'controller' => 'physicians',
'action' => 'phys_login',
'named' => array(),
'pass' => array(),
'phys' => true,
'_Token' => array(
'key' => 'ad1ea69c3b2c7b9e833bbda03ef18b04079b23c3',
'unlockedFields' => array()
),
'isAjax' => false
)
data => array(
'Physician' => array(
'password' => '*****',
'username' => 'deewilcox'
)
)
query => array()
url => 'phys/physicians/login'
base => ''
webroot => '/'
here => '/phys/physicians/login'
}
response => object(CakeResponse) {
}
settings => array()
}
OK I've got a way to do it. You know about prefix routing? If not, read my answer here: CakePHP/MVC Admin functions placement That answer describes how to set up a single routing prefix ('admin'). But you can have any number - just like this:
Configure::write('Routing.prefixes', array('admin','phys','member','user'));
// now we have admin, phys, member and user prefix routing enabled.
What you can do is have all the doctor's methods use 'admin' prefix routing, and all the physicians methods use 'phys' prefix routing.
So the below is code I've hacked together pretty quickly, so it might not be perfect but it should show the concept. Here it is in pseudo code for the before filter method of your app controller:
if (USER IS TRYING TO ACCESS AN ADMIN PREFIXED METHOD) {
Then use the users table for auth stuff
} else if (USER IS TRYING TO ACCESS A PHYS PREFIXED METHOD) {
Then use the physicians table for auth stuff
} else {
It's neither an admin method, not a physicians method. So just always allow access. Or always deny access - depending on your site
}
Here's my app controller code:
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $components = array('Security','Cookie','Session','Auth','RequestHandler');
public $helpers = array('Cache','Html','Session','Form');
function beforeFilter() {
if ($this->request->prefix == 'admin') {
$this->layout = 'admin';
// Specify which controller/action handles logging in:
AuthComponent::$sessionKey = 'Auth.Admin'; // solution from https://stackoverflow.com/questions/10538159/cakephp-auth-component-with-two-models-session
$this->Auth->loginAction = array('controller'=>'administrators','action'=>'login');
$this->Auth->loginRedirect = array('controller'=>'some_other_controller','action'=>'index');
$this->Auth->logoutRedirect = array('controller'=>'administrators','action'=>'login');
$this->Auth->authenticate = array(
'Form' => array(
'userModel' => 'User',
)
);
$this->Auth->allow('login');
} else if ($this->request->prefix == 'phys') {
// Specify which controller/action handles logging in:
AuthComponent::$sessionKey = 'Auth.Phys'; // solution from https://stackoverflow.com/questions/10538159/cakephp-auth-component-with-two-models-session
$this->Auth->loginAction = array('controller'=>'users','action'=>'login');
$this->Auth->logoutRedirect = '/';
$this->Auth->authenticate = array(
'Form' => array(
'userModel' => 'Physician',
)
);
} else {
// If we get here, it is neither a 'phys' prefixed method, not an 'admin' prefixed method.
// So, just allow access to everyone - or, alternatively, you could deny access - $this->Auth->deny();
$this->Auth->allow();
}
}
public function isAuthorized($user){
// You can have various extra checks in here, if needed.
// We'll just return true though. I'm pretty certain this method has to exist, even if it just returns true.
return true;
}
}
Note the lines:
AuthComponent::$sessionKey = 'Auth.Admin'; // solution from https://stackoverflow.com/questions/10538159/cakephp-auth-component-with-two-models-session
and
AuthComponent::$sessionKey = 'Auth.Phys'; // solution from https://stackoverflow.com/questions/10538159/cakephp-auth-component-with-two-models-session
What that does is allows a person to be logged in as both a physician, and an admin, in the one browser, without interfering with each other's session. You may not need it in the live site, but it's certainly handy while testing.
Now, in you're respective controllers, you'll need straight-forward login/logout methods, with the appropriate prefix.
So, for admin prefixing, in your users controller:
public function admin_login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Username or password is incorrect'), 'default', array(), 'auth');
}
}
}
public function admin_logout() {
$this->Session->setFlash('Successfully Logged Out');
$this->redirect($this->Auth->logout());
}
And in your physicians controller:
public function phys_login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Username or password is incorrect'), 'default', array(), 'auth');
}
}
}
public function phys_logout() {
$this->Session->setFlash('Successfully Logged Out');
$this->redirect($this->Auth->logout());
}
Like I said, that all code I hacked together pretty quickly, so it might not work verbatim, but it should show the concept. Let me know if you have any questions.
Instead of
$this->Session->write('Auth.redirect','/physicians/index');
you should use
setcookie("keys", value);