Laravel 5 SQLSTATE[23000] users_email_unique - php

I am implementing a social authentication on my website with laravel 5.
I successfully logged in a couple of users but now for some very strange reasons it doesn't work anymore..
When I try to log in a new user I have this error coming up:
QueryException in Connection.php line 624:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'users_email_unique' (SQL: insert into `users` (`name`, `profile_picture`, `facebook_id`) values (Hwan, https://graph.facebook.com/v2.4/1701160536770162/picture1701160536770162type=normal, ?))
But this user has never been registered in the DB before !!
I tried with other users, all the same...
But if I remove an existing FB user from the DB and try again, it works !!
Here is my controller:
class AccountController extends Controller {
/**
* Redirect the app to the social provider
*
* #return SNS token and user data
*/
public function redirectToProvider($provider) {
return Socialize::with($provider)->redirect();
}
/**
* Callback handler
*
* #return redirect to index
*/
public function handleProviderCallback($provider) {
$user = Socialize::with($provider)->user();
// get the sns user data
$id = $user->getId();
$name = $user->getName();
$avatar = $user->getAvatar();
// get the user provider id form the DB
$users = DB::table('users')->where($provider.'_id', $id)->get();
// check if the record exists
if(empty($users)){
DB::table('users')->insert(
['name' => $name,'profile_picture' => $avatar,$provider.'_id' => $id]
);
$users = DB::table('users')->where($provider.'_id', $id)->get();
}
foreach ($users as $user)
{
$userID = $user->id;
}
Auth::loginUsingId($userID);
{
return redirect()->to('home');
}
}
}
And my routes:
Route::get('connect/{provider}', 'AccountController#redirectToProvider');
Route::get('account/{provider}', 'AccountController#handleProviderCallback');
And my user schema:
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password', 60);
$table->string('profile_picture');
$table->text('facebook_id');
$table->rememberToken();
$table->timestamps();
});
Any help is greatly appreciated
Thank you

You have a unique constraint on your email field but you do not appear to be inserting an email address. After one user is inserted without an email address, no other users can be signed up without an email address.
You will not be able to have two empty strings in the email column of your database.

Related

How to redirect users conditionally?

I am on Laravel with Jetstream, I am using responses to redirect a user, once after a user registers himself. I am successfully able to redirect users whenever a user registers. Only admins can create users or invite them. So whenever I create a user from the admin panel, it redirects me to the route('frontend.dashboard') which can only be viewed by the user with a client role. So as I am logged in as an administrator, it throws me a status error 404.
How can I omit the redirection part when an administrator is registering an account. So a user is only redirected whenever he himself registers.
RegisterResponse.php
class RegisterResponse implements RegisterResponseContract
{
public function toResponse($request)
{
if(Auth::user()->hasAnyRoles(['Administrator', 'Employee'])) {
return redirect()->route('backend.dashboard');
}
return redirect()->route('frontend.dashboard');
}
You can use middleware to restrict user to redirect different routes.
Otherwise you can create two tables named "permissions" and "features" in your database.
Table columns should be like this:
- Table(Permissions):
Schema::create('permissions', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('user_id');
$table->unsignedInteger('feature_id');
$table->timestamps();
});
- Table(Features):
Schema::create('features', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Now make a helper function like this which will check if the particular user has access to redirect to the particular route.
**
Helper function:
**
function has_permission($feature_name)
{
$user = Auth::user();
if($user->role->name == 'admin' ){
$status = True;
}else{
$feature = Feature::where('name', $feature_name)->first();
$status = Permission::where([['user_id', $user->id],['feature_id', $feature->id]])->exists();
}
return $status;
}
So, now you can add condition in your Controllers every functions which redirect to a page like this:
if (!has_permission('shipments')) {
$notification=array(
'message' => 'Sorry ! You do not have permission',
'alert-type' => 'warning'
);
Thank you.Happy coding

Save to user database from a Json response in Laravel

I successfully implement a payment gateway on my Laravel Application
But I get this response from the payment
public function handleGatewayCallback()
{
$paymentDetails = Payant::getPaymentData();
dd($paymentDetails);
}
What I am trying to is to save some of the response to the user database, but I am unable to achieve this. I tried doing it this way
public function handleGatewayCallback(Request $request)
{
$paymentDetails = Payant::getPaymentData();
// dd($paymentDetails);
$user = User::find(Auth::id());
$user->sub_paid_at = $request->paid_at;
$user->role = $request->planObject['name'];
$user->save();
}
It returned this error
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'sub_paid_at' cannot be null (SQL: update users set sub_paid_at = ?, users.updated_at = 2019-12-14 07:27:45 where id = 3)
UPDATE
This is my user database Schema
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->enum('role', ['subscriber', 'admin', 'basic', 'couple', 'family'])->default('subscriber');
$table->timestamp('email_verified_at')->nullable();
$table->string('avatar')->nullable();
$table->integer('no_of_logins')->default(0);
$table->date('sub_paid_at')->nullable();
$table->string('session_id')->nullable();
$table->string('password')->nullable();
$table->rememberToken();
$table->timestamps();
});
}
I want to be able to update user role from the response, so I tried this
$user->role = $request->plan_object['name'];
But it returned error
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'role' cannot be null (SQL: update users set role = ?, sub_paid_at = 1970-01-01 00:00:00, users.updated_at = 2019-12-14 08:40:46 where id = 3)
Change your variable name from paid_at to paidAt
$user->sub_paid_at = $request->paidAt;
But better you change format
$user->sub_paid_at = date("Y-m-d H:i:s",strtotime($request->paidAt));
This fix my question
$user = User::find(Auth::id());
$user->sub_paid_at = date("Y-m-d H:i:s",strtotime($paymentDetails['data']['paidAt']));
$user->role = $paymentDetails['data']['plan_object']['name'];
$user->save();

SQLSTATE[23000]: Integrity constraint violation: on Laravel 5

Trying to Update user Profile after Login and am having this ERROR:
QueryException in Connection.php line 662:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`wallet`.`profiles`, CONSTRAINT `profiles_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) (SQL: insert into `profiles` (`gender`, `city`, `state`, `profession`, `aboutmyself`, `fb`, `twitter`, `gp`, `instagram`, `personal_site`, `aboutme`, `linkedin`, `pinterest`, `updated_at`, `created_at`) values (male, Upper Darby, Washington DC, Architects, Am a Benefactor of Grace and a Heir to the Throne a Royal Priesthood. I Love Jesus! s, url, url, url, url, url, url, hurl, url, 2016-11-05 09:35:51, 2016-11-05 09:35:51))
AND THIS
PDOException in Connection.php line 390:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`wallet`.`profiles`, CONSTRAINT `profiles_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
Meaning that part of the CODE is executing now but something on Integrity Violation is hindering the data from being saved.
CONTROLLER (UserController.php)
public function update(Request $request)
{
$rules = [
'name' => 'required',
'email' => 'required',
'phone' => 'required|numeric',
'country' => 'required',
'gender' => 'required',
'birthday' => 'required',
'fb' => 'url',
'twitter' => 'url',
'gp' => 'url',
'instagram' => 'url',
'personal_site' => 'url',
'aboutme' => 'url',
'linkedin' => 'url',
'pinterest' => 'url'
];
$data= $request->all();
$validator = Validator::make($data, $rules);
if($validator->fails()){
return Redirect::back()->withInput()->withErrors($validator);
}
$user = Auth::user();
$user->name = $data['name'];
$user->email = $data['email'];
$user->phone = $data['phone'];
$user->country = $data['country'];
$user->birthday = $data['birthday'];
$user->address = $data['address'];
if($user->save()) {
$profile_id = $user->id;
$profile = Profile::findOrFail($user->id);
if(count($profile) > 0) {
$profile = new Profile();
$profile->gender = $data['gender'];
$profile->city = $data['city'];
$profile->state = $data['state'];
$profile->profession = $data['profession'];
$profile->aboutmyself = $data['aboutmyself'];
$profile->fb = $data['fb'];
$profile->twitter = $data['twitter'];
$profile->gp = $data['gp'];
$profile->instagram = $data['instagram'];
$profile->personal_site = $data['personal_site'];
$profile->aboutme = $data['aboutme'];
$profile->linkedin = $data['linkedin'];
$profile->pinterest = $data['pinterest'];
//$profile = $user->profile()->save($profile);
$profile->save();
}
} else {
return redirect()->back()->withInput()->withInfo("Something went wrong. Please, try again");
}
return redirect()->route('profile')->withSuccess("Your Profile Succesfully Updated.");
}
USER Migration
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('login');
$table->string('email')->nullable();
$table->string('phone')->nullable();
$table->string('password', 60);
$table->string('birthday');
$table->string('country')->default('AF');
$table->string('address');
$table->integer('active')->default(0);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('users');
}
}
PROFILE Migration
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProfilesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
// $table->string('birthday');
$table->string('aboutmyself');
$table->string('gender');
$table->string('age');
$table->string('propic')->default('uploads/demo.png');
$table->string('address');
$table->string('state');
$table->string('city');
$table->string('fb');
$table->string('twitter');
$table->string('gp');
$table->string('personal_site');
$table->string('instagram');
$table->string('aboutme');
$table->string('linkedin');
$table->string('pinterest');
$table->foreign('user_id')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('profiles');
}
}
It's a lot of code to look through, however, I think your issue may lie with the $fillable array on your User model. It appears that you have added extra columns to you users table without allowing them to be mass assigned, so you need to make sure you add them to the $fillable array as so:
protected $fillable = ['name', 'login','email', 'password', 'country', 'birthday'...];
See: https://laravel.com/docs/5.3/eloquent#mass-assignment
You should also really be using a FormRequest for a validator that size to prevent it from clogging up your controller:
https://laravel.com/docs/5.3/validation#form-request-validation
And you should look at how to save relationships:
https://laravel.com/docs/5.3/eloquent-relationships#inserting-and-updating-related-models
You should note that eloquent automatically maps your input fields to database columns with the same name so you should really be able to break that controller method down to just a few lines of code.
You violate foreign key contraint. You don't add anything to $profile->user_id and it stays null and your database disallows that. Simply add $profile->user_id = $user->id; after $profile = new Profile(); and it should work.

Laravel 5.1 login with mfa token

I'm trying to get the a login with mfa to work. I'm using the https://github.com/antonioribeiro/google2fa package.
Basically the user-migration looks like this
class CreateUsersTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up() {
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->string('google2fa_secret');
$table->boolean('useMfa')->default(false);;
$table->timestamps();
});
}
...
If the user has not yet activated mfa I create a new secret every time the user opens the profile page.
if(!$user->useMfaToken()){
$google2fa = new Google2FA();
$user->google2fa_secret = $google2fa->generateSecretKey();
$user->save();
$google2fa_url = $google2fa->getQRCodeGoogleUrl(
'DatenPro.de',
$user->email,
$user->google2fa_secret
);
}
If the user enters the secret for finalizing the activation of mfa this will be executed:
public function saveMfa(){
$user = \Auth::user();
$secret = \Input::get('secret');
$google2fa = new Google2FA();
$valid = $google2fa->verifyKey($user->google2fa_secret, $secret);
if($valid){
$user->useMfa = true;
$user->save();
return redirect()->back()->withMessage('mfa sucessfully activated');
}
...
Now I'm working on the login with a mfa-token. I want that the user has the option to enter the token at the login page, if he has already activated it, otherwise if the mfa-Checkbox is deselected the "secret" text-input is hidden.
Email: __________
Password: __________
Use Mfa: [x]
Secret: __________
Where do I have to put the checks of the mfa token? I have read about it to check it through a middleware and a session-variable, but this seems kind of wrong.
Just figured it out before posting.
You can implement a "authenticated"-method in the AuthController.
This could look like this:
public function authenticated($request, $user){
if($user->useMfaToken()){
$secret = \Input::get('secret');
$google2fa = new Google2FA();
$validMfaToken = $google2fa->verifyKey($user->google2fa_secret, $secret);
}else{
$validMfaToken = true;
}
if($validMfaToken){
return redirect()->intended('dashboard');
}
Auth::logout();
return redirect($this->loginPath)
->withInput($request->only('email', 'remember'))
->withErrors([
'secret' => 'mfa token was not corret',
]);
}

laravel check if user is active?

using laravel 4 I am trying to add 'active' column to my database to check if the user is active and is not suspended , here is my migration users table.
public function up()
{
//
Schema::create(
'users',
function (Blueprint $table) {
$table->increments('id');
$table->string('email', 300);
$table->string('password', 60);
$table->boolean('active'); // check this one
$table->string('first_name', 100);
$table->string('last_name', 100);
$table->string('address', 250)->nullable();
$table->string('city', 100)->nullable();
$table->string('state', 2)->nullable();
$table->string('zip', 5)->nullable();
$table->string('phone', 10)->nullable();
$table->timestamps();
}
);
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
//
Schema::drop('users');
}
could you help me if I use $table->boolean('active'); // check this one
*is this the right way to do it? so I can use the Auth class like this to check if the user is active or not? *
$is_active = Auth::user()->active;
if (!$is_active == 1)
{
echo "Account not activated";
}
You can do it the way you have mentioned but the Laravel way to do this exists
if (Auth::attempt(array('email' => $email, 'password' => $password, 'active' => 1)))
{
// The user is active, not suspended, and exists.
}
Read : Laravel\Docs\Authentication
Just my 2 bit : The way are building you database is not advised. You should keep your user login information (email, password & active) in users table and others in a separate user_profile table. Later you can use eloquent to map relations.

Categories