Dynamic domain in reset password link Laravel 8 - vue.js

I'm aware that password reset link can be customized by adding the below function in AuthServiceProvider.php
ResetPassword::createUrlUsing(function ($user, string $token) {
return 'https://example.com/reset-password?token='.$token;
});
This is my sendResetPassword function
public function sendResetPassword(Request $request) {
$request->validate(['email' => 'required|email']);
$status = Password::sendResetLink(
$request->only('email')
);
if ($status === Password::RESET_LINK_SENT) {
return response()->json(['message' => __($status)], 200);
} else {
return response()->json(['message' => __($status)], 500);
}
}
Now I'm wondering if there is a way to pass a domain from the sendResetPassword $request to the createUrlUsing function.
The main purpose of this is to avoid hardcoding the frontend URL in my API. I just want that the forgot password form in my frontend sends the email and also the domain.

Not sure if this is the best approach, but as soon I posted the question I found that this is a working solution:
ResetPassword::createUrlUsing(function ($user, string $token) {
return $this->app->request->headers->get('origin').'/reset-password?token='.$token;
});

Related

How authorize for multiple user on Policies in laravel?

Hello i'm trying to authorize 2 differents users to view one of my pages.
On the Policy's view function i passed my two users, and it doesn't worked.
I've tried many ways.
public function view(User $user, Proposal $proposal)
{
return $user->id === $proposal->user_id;
return $user->id === $proposal->annonce->user->id;
}
public function view(User $user, Proposal $proposal)
{
return $user->id === $proposal->user_id; $proposal->annonce->user->id;
}
public function view(User $user, Proposal $proposal)
{
$good_user = $proposal->user_id; $proposal->annonce->user->id;
return $user->id === $good_user;
}
Problem is, in my view the #can(show, $proposal), only authorize the first user i've write on the policy, never the second. Have you got some ideas i could try?
I finally find an answer. I put it here, hoping, one day, it will help someone.
if($user->id === $proposal->user_id) {
return true;
} elseif($user->id === $proposal->annonce->user->id) {
return true;
}
Don't know if it's the best way, but it works ^^

Laravel /broadcasting/auth Always forbidden with 403 Error

I tried many solutions but no one works for me
I've installed Laravel echo and pusher js and Pusher/Pusher
#bootstrap.js
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: true,
});
#.env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=my_id
PUSHER_APP_KEY=my_key
PUSHER_APP_SECRET=my_secret
PUSHER_APP_CLUSTER=eu
my event file NewMessage
class NewMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Message $message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('messages.'. $this->message->to);
}
public function broadcastWith()
{
return ["message" => $this->message];
}
}
channel.php
Broadcast::channel('messages.{id}', function ($user, $id) {
return $user->id === (int) $id;
});
Vue App JS code
mounted(){
Echo.private(`messages${this.user.id}`)
.listen('NewMessage', (e) => {
this.handleIncoming(e.message)
});
},
methods:{
saveNewMessage(msg){
this.messages.push(msg);
},
handleIncoming(message){
if(this.selectedContact && message.from == this.selectedContact.id ){
this.saveNewMessage(message);
return;
}
alert(message.text);
}
}
Api.php
Route::post('/conversation/send', 'Api\ContactController#sendNewMessage');
Contact Controller
public function sendNewMessage(Request $request)
{
$message = Message::create([
'from' => $request->sender_id,
'to' => $request->receiver_id,
'text' => $request->text
]);
broadcast(new NewMessage($message));
return response()->json($message);
}
I also read the official documentation everything is going good but I didn't figure out why, it's a throwing error. Have any idea?
I figure out why it is every time shows auth forbidden or doesn't display auth
Solution:
you need to double-check your PUSHER_APP_KEY because if it is not set correctly, it will through error because our stream not connected with pusher
PUSHER_APP_KEY="PUT KEY HERE"
If you are very sure that your app key is correct then go to the Network tab and click on your pusher app key which like e70ewesdsdssew0
If it is displaying the result like this
{"event":"pusher:connection_established","data":"{\"socket_id\":\"131139.31305364\",\"activity_timeout\":120}"}
your API key is good
if it not correct it will display an error like this
{"event":"pusher:error","data":{"code":4001,"message":"App key 3fdsfdfsdfsd not in this cluster. Did you forget to specify the cluster?"}}
Also, don't forget to put the cluster key
PUSHER_APP_CLUSTER=eu

How to add captcha required only for a particular condition yii2

I am trying make the captcha field required only when the number of failed login attempts exceed 3 times. For which I have written below code till now.
In LoginForm model I have added the below rules
public function rules()
{
return [
[['username', 'password'], 'required'],
['password', 'validatePassword'],
['verifyCode', 'captcha', 'when' => function($model) {
return $this->checkattempts();
}],
];
}
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addLoginAttempt($user->id);
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
public function checkattempts()
{
$user = $this->getUser();
$ip = $this->get_client_ip();
$data = (new Query())->select('*')
->from('login_attempts')
->where(['ip' => $ip])->andWhere(['user_ref_id' => $user->id])
->one();
if($data["attempts"] >=3){
return false;
}else{
return true;
}
}
public function addLoginAttempt($uid) {
$ip = $this->get_client_ip();
$data = (new Query())->select('*')
->from('login_attempts')
->where(['ip' => $ip])->andWhere(['user_ref_id' => $uid])
->one();
if($data)
{
$attempts = $data["attempts"]+1;
#Yii::$app->db->createCommand("UPDATE login_attempts SET attempts=".$attempts." where ip = '$ip' AND user_ref_id=$uid")->execute();
}
else {
Yii::$app->db->createCommand("INSERT into login_attempts (attempts, user_ref_id, ip) VALUES(1,'$uid', '$ip')")->execute();
}
}
Here I am validating the password first. If the password is incorrect then I am incrementing the count by 1. This part is working fine. The count is incrementing successfully.
After this I am trying to get the count of failed attempts while validating captcha using the function checkattempts(), but it is not working.
Can anyone please tell me where I have made mistake.
Thanks in advance.
In your model:
if (!$model->checkattempts())
//show the captcha
Then, in your model rules you'll need something like:
['captcha', 'captcha'],
In your case, what you can do is use different scenarios depending on the user attempts, and in one scenario (more than X attempts) make the captcha required.
More documentation about the captcha and about scenarios.

CakePHP3 BeforeFilter & Auth Redirect

Can anyone help me understand the deal with Cakephp 3.3 and a BeforeFilter/Auth Redirect issue I'm experiencing.
I'm using the default Auth component. I've created a custom component that additionally checks for a session variable (Registration), and if that variable is not set redirects to a page designed to make a selection to set the desired Registration.
Here's my custom component:
<?php
namespace App\Controller\Component;
use Cake\Controller\Component;
use Cake\Network\Request;
class RegistrationCheckComponent extends Component
{
private $_allowedActions = [];
private $_superUserBypass = false;
public $components = ['Auth'];
public function superUserBypass($val = false) {
$this->_superUserBypass = $val;
}
public function allow(Array $allowedActions = []) {
$this->_allowedActions = $allowedActions;
}
public function verify() {
if($this->_superUserBypass) {
return true;
}
$session = $this->request->session();
//if Auth Registration is not set
if(!$session->read('Auth.Registration')) {
//if requested action is not in the array of allowed actions, redirect to select registration
if(!in_array($this->request->param('action'), $this->_allowedActions)) {
return $this->redirect();
};
return true;
}
return true;
}
public function redirect() {
$controller = $this->_registry->getController();
return $controller->redirect($this->config('redirect'));
}
}
Not all controller's require the Registration variable to be set, that's why I decided to go with the component approach. The component is however loaded in the AppController by this line:
$this->loadComponent('RegistrationCheck', ['redirect' => ['controller' => 'Users', 'action' => 'registrations']]);
In the controllers that require the Registration variable to be set, I include the following beforeFilter function:
public function beforeFilter(Event $event) {
parent::beforeFilter($event);
return $this->RegistrationCheck->verify();
}
Now, I've had some Integration Tests defined, here's one of them:
public function testUnauthenticatedEdit()
{
$this->get('/teams/edit');
$this->assertRedirect(['controller' => 'Users', 'action' => 'login']);
}
So, after I implemented my RegistrationCheck component, I ran the Integration Tests. I was expecting the test to pass, it did not. The interesting thing is that it actually returned a redirect to Users->registrations rather than Users->login as I had expected.
It looks to me that the RegistrationCheck redirect is happening before the Auth component redirect. I'm not sure it's a huge deal, because a redirect to registrations without Auth set is going to end up redirecting back to login, but it seems incorrect to ignore it...also, I'd just like to understand a bit more of what is actually going on.
Can anyone suggest changes to my code that would ensure the Auth component is handled before the RegistrationCheck component?
Thanks in advance.
Well, after a little more research, I found the answer I'm looking for here: http://book.cakephp.org/3.0/en/controllers/components/authentication.html#deciding-when-to-run-authentication
Pretty simple really, just wanted to include an answer here for anyone who may stumble across the same question.

How to call a function within the same controller?

I have to call a soap service using laravel and done so correctly. This soap service requires me to send a login request prior to sending any other request.
The code I'm using works, but I want to improve by removing the login from all the functions and creating one function.
I tried changing the following for one function:
public function getcard($cardid)
{
SoapWrapper::add(function ($service) {
$service
->name('IS')
->wsdl(app_path().'\giftcard.wsdl')
->trace(true);
});
$data = [
'UserName' => 'xxxx',
'Password' => 'xxxx',
];
$card = [
'CardId' => $cardid,
];
SoapWrapper::service('IS', function ($service) use ($data,$card) {
$service->call('Login', [$data]);
$cardinfo=$service->call('GetCard', [$card]);
dd($cardinfo->Card);
});
}
Into:
public function login()
{
SoapWrapper::add(function ($service) {
$service
->name('IS')
->wsdl(app_path().'\giftcard.wsdl')
->trace(true);
});
$data = [
'UserName' => 'xxxx',
'Password' => 'xxxx',
];
SoapWrapper::service('IS', function ($service) use ($data) {
return $service->call('Login', [$data]);
//$service->call('Login', [$data]);
//return $service;
});
}
public function getcard($cardid)
{
$this->login();
$card = [
'CardId' => $cardid,
];
$cardinfo=$service->call('GetCard', [$card]);
dd($card);
}
But this doesn't work. I also tried it with the commented out part, but that doesn't work. Both options result in an error that it didn't find 'service'.
I know it has something to do with oop, but don't know any other option.
I took this as an example, but I probably implemented it wrong?
So my question is: How do I reuse the login part for all other functions?
Your return statement in the login() method is within the scope of that closure. You need to return the result of the closure as well.
return SoapWrapper::service('IS', function ($service) use ($data) {
return $service->call('Login', [$data]);
});
EDIT:
To explain a little bit. You have a function:
SoapWrapper::service('IS' ,function() {}
Inside of a function : public function login()
If you need to return data from your login() method, and that data is contained within your SoapWrapper::service() method, then both methods need a return statement