I want to get the errors from the server in the client, show them on the page when there's some troubles during login or registration, I think it's ok in the backend, but I don't know why they're not returning.
How to get that error messages from the validator in Vue?
I'm using: vuex, vue-router
My vuex file for login and register
actions: {
async login({ dispatch }, credentials) {
await axios.post('http://127.0.0.1:8000/api/login', credentials)
.then( res => {
if (res.data.success) {
// controllo se il token è buono
return dispatch('attempt', res.data.token)
}
})
.catch( err => {
console.log( err )
})
},
async attempt({ commit, state }, token) {
// blocco in caso ci fosse o meno il token
// se c'è il token
if (token) {
commit('SET_TOKEN', token)
}
// se non c'è
if(!state.token) {
return
}
// /blocco in caso ci fosse o meno il token
// provo a gettare l'user
try {
await axios.get('http://127.0.0.1:8000/api/user')
.then(res => {
commit('SET_USER', res.data)
})
} catch (e) {
commit('SET_TOKEN', null)
commit('SET_USER', null)
}
},
async register({ }, credentials) {
await axios.post('http://127.0.0.1:8000/api/register', credentials)
.then( () => {
})
.catch(err => {
console.log(err)
})
},
logoutAction({ commit }) {
return axios.post('http://127.0.0.1:8000/api/logout')
.then( () => {
commit('SET_TOKEN', null)
commit('SET_USER', null)
})
},
}
My controller
public function register(Request $request) {
$fields = $request->validate(
[
'name' => 'required|string',
'email' => 'required|string|unique:users,email',
'password' => 'required|string|confirmed'
]
);
$user = User::create([
'name' => ucwords($fields['name']),
'email' => $fields['email'],
'password' => bcrypt($fields['password']),
]);
$token = $user->createToken('token')->plainTextToken;
return response()->json(
[
'success' => true,
'user' => $user,
'token' => $token,
'message' => 'Registered successfully'
], 201);
}
public function login(Request $request) {
$fields = $request->all();
$validator = Validator::make($fields, [
'email' => 'required',
'password' => 'required'
]);
$user = User::where('email', $fields['email'])->first();
if($validator->fails()) {
return response()->json([
'message' => 'You must fill in all the fields!',
'errors' => $validator->errors()
], 401);
}
if(!$user || !Hash::check($fields['password'], $user->password)) {
return response()->json([
'message' => 'Invalid credentials.',
], 401);
}
$token = $user->createToken('token')->plainTextToken;
return response()->json(
[
'success' => true,
'user' => $user,
'token' => $token,
'message' => 'Logged in'
], 201);
}
public function logout(Request $request) {
auth()->user()->tokens()->delete();
return response()->json(
[
'message' => 'Logged out.'
]
);
}
Also I want to stop the user if the registration has empty fields, forcing him to stay in the register route, but with these settings down here the user will be redirected to the login page even if no registration fields are been typed in, as soon as I press enter or click 'register'.
p.s.: the 'home' route in which I'm pushing in the user is the page with the login form. So I want that the user will be redirect there only if the register form has been fulfilled.
submitRegistration() {
this.register(this.form)
.then(() => {
this.$router.push({name:'home'})
})
.catch((err) => {
// Ignore the vuex err regarding navigating to the page they are already on.
if (
err.name !== "NavigationDuplicated" &&
!err.message.includes(
"Avoided redundant navigation to current location"
)
) {
// But print any other errors to the console
console.log(err);
}
});
},
Related
I made a google login through socialite in laravel
public function redirectToProvider($provider)
{
$url = Socialite::driver($provider)->stateless()->redirect()->getTargetUrl();
return $url;
//return response()->json(['url' => $url], 200);
}
public function handleProviderCallback($provider)
{
$user = null;
if (Helper::validateProvider($provider) === false) {
return response()->json(['message' => 'The provider is not accepted temporally'], 422);
}
try {
$userProvider = Socialite::driver($provider)->stateless()->user();
} catch(\Exception $e) {
\Log::error($e->getMessage());
return response()->json(["message" => "An error occured while trying to login with {$provider}"], 422);
}
if (empty($userProvider)) {
return response()->json(["message" => "Invalid user provider"], 422);
}
if (empty($userProvider->id)) {
return response()->json(["message" => "Invalid provider id"], 422);
}
if (empty($userProvider->name)) {
return response()->json(["message" => "Invalid provider name"], 422);
}
if (empty($userProvider->email)) {
return response()->json(["message" => "Invalid provider email"], 422);
}
DB::transaction(function () use ($userProvider, $provider, &$user) {
$user = User::firstOrCreate([
'provider_id' => $userProvider->id,
'provider_name' => $provider,
], [
'email' => $userProvider->email,
'email_verified_at' => now(),
]);
});
if (! $user) {
return response()->json(["message" => "Cannot create an account"]);
}
$token = $user->createToken('token')->plainTextToken;
$response = [
'user' => $user,
'token' => $token,
'isAdmin' => $isAdmin
];
return response($response);
}
But now I do not know how I could proceed with these two api and take the data properly in my application de vue
I use vue3 and there I don't have much advantage of books already written
Is there a way I can get data from google?
For example, if I open the 2 apies in the browser, I can log in and my token will be returned
But in view, if I made a call to callback it would be a matter of course because I would send something to google
How can I proceed /
I am creating a new app using Cashier 10.1. In the past I would send a token from Stripe to the subscription function when registering a user with a subscription. Now it says it takes a Payment Method (id). I am registering a payment method with Stripe and passing that to my controller but it returns the error "This customer has no attached payment source". I read the docs but it only gives an example of how to add a subscription to a current user by passing to the view $user->createSetupIntent(). Below is the code for when a user registers:
Component
pay() {
this.isLoading = true;
if (this.form.payment_method == "cc") {
let that = this;
this.stripe
.createPaymentMethod({
type: "card",
card: that.card
})
.then(result => {
this.form.stripePayment = result.paymentMethod.id;
this.register();
})
.catch(e => {
console.log(e);
});
} else {
this.register();
}
},
register() {
this.form
.post("/register")
.then(data => {
this.isLoading = false;
if (data.type == "success") {
this.$swal({
type: "success",
title: "Great...",
text: data.message,
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 2000
});
setTimeout(() => {
// window.location.replace(data.url);
}, 2000);
}
})
.catch(error => {
this.isLoading = false;
});
}
RegisterController
protected function create(request $request)
{
$request->validate([
'name' => 'required',
'email' => 'required|unique:users',
'username' => 'required|alpha_dash|unique:users',
'phone' => 'required',
'city' => 'required',
'state' => 'required',
'password' => 'required|confirmed',
'agree' => 'required',
]);
$user = User::create([
'username' => $request['username'],
'name' => $request['name'],
'email' => $request['email'],
'phone' => $request['phone'],
'city' => $request['city'],
'state' => $request['state'],
'password' => Hash::make($request['password']),
]);
if ($request['subscription_type'] == 'premier' && $request['payment_method'] == 'cc') {
$user->newSubscription('default', env('STRIPE_PLAN_ID'))->create($request->input('stripePayment'), [
'email' => $request['email'],
]);
}
if ($user) {
$user->assignRole('subscriber');
Auth::login($user);
return response()->json([
'type' => 'success',
'message' => 'you are all set.',
'url' => '/dashboard'
]);
}
I found a good article explaining the new setup finally. Basically when I show my registration view I now create a new User and pass the intent there. I kept thinking the user had to be saved already, not just created. So if anyone else wants to do it:
Show the view
Registration Controller
public function show()
{
$user = new User;
return view('auth.register', [
'intent' => $user->createSetupIntent()
]);
}
Pass the intent to my Vue component
<register-form stripe-key="{{ env('STRIPE_KEY') }}" stripe-intent="{{ $intent->client_secret }}">
</register-form>
Add stripe elements to a div:
mounted() {
// Create a Stripe client.
this.stripe = Stripe(this.stripeKey);
// Create an instance of Elements.
var elements = this.stripe.elements();
var style = {
base: {
color: "#32325d",
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder": {
color: "#aab7c4"
}
},
invalid: {
color: "#fa755a",
iconColor: "#fa755a"
}
};
// Create an instance of the card Element.
this.card = elements.create("card", { style: style });
// Add an instance of the card Element into the `card-element` <div>.
this.card.mount("#card-element");
},
process the data
pay() {
this.isLoading = true;
if (this.form.payment_method == "cc") {
this.setupCard();
} else {
this.register();
}
},
setupCard() {
this.stripe
.handleCardSetup(this.stripeIntent, this.card, {
payment_method_data: {
billing_details: { name: this.form.name }
}
})
.then(data => {
this.form.stripePayment = data.setupIntent.payment_method;
if (this.form.stripePayment) this.register();
})
.catch(error => {
this.isLoading = false;
console.log(error);
});
},
register(setupIntent) {
this.form
.post("/register")
.then(data => {
this.isLoading = false;
if (data.type == "success") {
this.$swal({
type: "success",
title: "Great...",
text: data.message,
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 2000
});
setTimeout(() => {
window.location.replace(data.url);
}, 2000);
}
})
.catch(error => {
this.isLoading = false;
});
}
Save the user
Registration Controller
protected function create(request $request)
{
$request->validate([
'name' => 'required',
'email' => 'required|unique:users',
'username' => 'required|alpha_dash|unique:users',
'phone' => 'required',
'city' => 'required',
'state' => 'required',
'password' => 'required|confirmed',
'agree' => 'required',
]);
$user = User::create([
'username' => $request['username'],
'name' => $request['name'],
'email' => $request['email'],
'phone' => $request['phone'],
'city' => $request['city'],
'state' => $request['state'],
'password' => Hash::make($request['password']),
]);
if ($request['subscription_type'] == 'premier' && $request['payment_method'] == 'cc') {
$user->newSubscription('default', env('STRIPE_PLAN_ID'))->create($request->input('stripePayment'), [
'email' => $request['email'],
]);
}
if ($user) {
$user->assignRole('subscriber');
Auth::login($user);
return response()->json([
'type' => 'success',
'message' => 'you are all set.',
'url' => '/dashboard'
]);
}
}
Cashier has updated the way it interacts with Stripe due to Strong Customer Authentication (SCA). This means card payments require a different user experience, namely 3D Secure, in order to meet SCA requirements. It may be beneficial to read-up on the Payment Intents API on Stripe and you may be able to work around this by first creating the payment intent with a direct interaction with Stripe and then attaching it to your Laravel user.
The simple solution may be to have a multi step registration process:
Step 1: Collect customer details and create user on Laravel and Stripe
Step 2: Create the payment intent $user->createSetupIntent() and collect payment details and save to customer.
Step 3: Subscribe user to the Cashier Plan
I have managed to create jwtauth to connect my mobile app to octobercms backend
from this reference
but the last_login field is always empty, I believe this is not set by default.
this is authenticated function that I have
use Tymon\JWTAuth\JWTAuth;
public function __construct(JWTAuth $auth)
{
$this->auth = $auth;
}
public function authenticate(Request $request)
{
try {
if (! $token = $this->auth->attempt($request->only('email', 'password'))) {
return response()->json([
'errors' => [
'root' => 'Could not sign you in with those details.',
],
], 401);
}
} catch (JWTException $e) {
return response()->json([
'errors' => [
'root' => 'Failed.',
],
], $e->getStatusCode());
}
return response()->json([
'data' => $request->user(),
'meta' => [
'token' => $token,
],
]);
}
it's called by this route.php from jwtauth folder
Route::group(['prefix' => 'api'], function () {
Route::post('auth/login','Autumn\JWTAuth\Http\Controllers\AuthController#authenticate');
Route::post('auth/register', 'Autumn\JWTAuth\Http\Controllers\AuthController#register');
Route::post('auth/logout', 'Autumn\JWTAuth\Http\Controllers\AuthController#logout');
Route::group(['middleware' => 'jwt.auth'], function () {
Route::get('auth/me', 'Autumn\JWTAuth\Http\Controllers\AuthController#user');
});
how do we set user last_login timestamp?
I hope my question is clear to understand.
added plugin.php where i extended user plugin as requested by #HardikSatasiya since i got exception implementing his suggestion
use System\Classes\PluginBase;
use Rainlab\User\Controllers\Users as UsersController;
use Rainlab\User\Models\User as UserModels;
use Event;
class Plugin extends PluginBase
{
public function registerComponents()
{
}
public function registerSettings()
{
}
public function boot()
{
UserModels::extend(function($model){
$model->bindEvent('model.beforeSave',function() use ($model) {
$users = \BackendAuth::getUser();
$model->backend_users_id = $users->id;
//above line result exception when calling method as #HardikSatasiya suggested
if(!empty($model->avatar)){
$model->image_path = $model->avatar->getPath();
}
if(!empty($model->groups)){
$model->membership = $model->groups[0]['name'];
}
});
$model->addJsonable('users_detail','membership');
});
UsersController::extendFormFields(function($form,$model,$context){
$form->addTabFields([
'users_detail[0][gender]' => [
'label' => 'Jenis Kelamin',
'span' => 'left',
'tab' => 'User Profile',
'type' => 'radio',
'options' => [
'Pria' => 'Pria',
'Wanita' => 'Wanita'
]
],
'users_detail[0][ttl]' => [
'label' => 'Tempat/Tanggal Lahir',
'type' => 'text',
'span' => 'left',
'tab' => 'User Profile'
],
]);
});
}
i add additional fields to user table by this separate plugin..
Ok, may be because internal hooks are not called when this plugin externally logsin user.
May be we need to call it manually, this code snippet can do it, just put given code after successful login.
// this will fire hooks and update `last_login`
// get authenticated user from the jwt authmanager
$user = $this->auth->authenticate($token);
$user->afterLogin();
Added in your code below.
public function authenticate(Request $request)
{
try {
if (! $token = $this->auth->attempt($request->only('email', 'password'))) {
return response()->json([
'errors' => [
'root' => 'Could not sign you in with those details.',
],
], 401);
}
} catch (JWTException $e) {
return response()->json([
'errors' => [
'root' => 'Failed.',
],
], $e->getStatusCode());
}
// this will fire hooks and update `last_login`
// get authenticated user from the jwt authmanager
$user = $this->auth->authenticate($token);
$user->afterLogin();
// ^ this code
return response()->json([
'data' => $request->user(),
'meta' => [
'token' => $token,
],
]);
}
this snippet will update last_login as expected. i did not test it but it will work as it should.
if any doubt or problem please comment.
I've an issue that cant understand,
I'm trying to send axios post requests using Vuejs to Laravel,
as is they describe :
install the axios package.
add the token to the header (by default is added in bootstrap).
my issue when i send the post request
the first is done but if i will send another one it gives me the
TokenMismatchException
please help me
the code in my vue file
login() {
this.userNotExiste = null;
var app = this
axios.post('/user/login', {email: this.email, password: this.password})
.then(function (response) {
if (response.data.userConnected) {
app.userConnected = response.data.userConnected;
setTimeout(function () {
window.location.href = window.location;
}, 1000);
}
})
.catch(function (error) {
if (error.response) {
if (!_.isEmpty(error.response.data))
if (!_.isEmpty(error.response.data.messages)) {
if (!_.isEmpty(error.response.data.messages.email)) app.loginErrors.email = error.response.data.messages.email[0]
if (!_.isEmpty(error.response.data.messages.password)) app.loginErrors.password = error.response.data.messages.password[0]
}
if (!_.isEmpty(error.response.data.userNotExiste)) app.userNotExiste = error.response.data.userNotExiste
} else if (error.request) {
console.log(error.request)
} else {
console.log('Contact : contact#33sprog.com')
}
})
}
in my laravel section
public function login(Request $request)
{
$validation = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required',
], [
'email.email' => 'Entrer adresse email correct',
'email.required' => 'Veuillez saisir une adresse email',
'password.required' => 'Veillez saisir votre mot de passe',
]);
if ($validation->fails()) {
return response()->json([
'messages' => $validation->messages(),
], 400);
}
$user = Auth::attempt(['email' => $request->email, 'password' => $request->password]);
if (!$user) {
return response()->json([
'userNotExiste' => 'Adresse email ou mot de passe incorrecte',
], 400);
}
return response()->json(['userConnected' => 'Vous etes bien connecte'], 200);
}
at my php file
at my bootstrap.js
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
Thanks for helping
I have created my API for logging users into my application, but then it responds with the else part as the response
{"error":true,"message":"Check your username or password"}
below is my controller
public function getLogin()
{
$user = array(
'username' => Input::get('username'),
'password' => Input::get('password')
);
if (Auth::attempt($user))
{
$user = User::find(Auth::user()->id);
$role = $user->roles;
if ($role[0]->name == 'Customer')
{
return Response::json(['error' => false, 'message' => 'Customer Logged in successfully', "user"=>$user]);
}
else
{
return Response::json(['error'=>true, 'message'=>'Check your login details']);
}
}
else
{
return Response::json(['error' => true, 'message' => 'Check your username or password']);
}
}