Can anyone help me convert this and help a noob learn the difference.
/**
* User Delete Account via Profile
*
* #access protected
* #return void
*
*/
protected function deleteProfile(Request $request) {
$this->validate($request, [
'confirmation' => 'required',
'password' => 'required',
]);
$usr = User::findOrFail(Auth::user()->id);
if (Hash::check($request->password, $usr->password)) {
Auth::logout();
// Removes UserID from Torrents if any and replaces with System UserID (0)
foreach(Torrent::where('user_id', '=', $usr->id)->get() as $tor) {
$tor->user_id = 0;
$tor->save();
}
// Removes UserID from Comments if any and replaces with System UserID (0)
foreach(Comment::where('user_id', '=', $usr->id)->get() as $com) {
$com->user_id = 0;
$com->save();
}
if($usr->delete()) {
return view('members.delete_account');
}
} else {
return redirect()->back()->with(Toastr::warning('Your Password Was Incorrect!', 'Error', ['options']));
}
}
This is set up to use Illuminate\Http\Request;
but i need it to work with Illuminate\Support\Facades\Request;
Looking at the comment, you imported invalid Request class in your controller. In your controller file you should have :
use Illuminate\Http\Request;
instead of:
use Illuminate\Support\Facades\Request;
EDIT
If your other function uses already Illuminate\Support\Facades\Request you can alias this class like this:
use Illuminate\Http\Request as IlluminateRequest;
and then in your deleteProfile use:
protected function deleteProfile(IlluminateRequest $request)
{
// ...
}
Related
I'm trying to post a comment to my news post using the Laravelista\Comments but I got this error: Target [Laravelista\Comments\CommentControllerInterface] is not instantiable.
It was working just fine before, and I didn't change anything except the interface design. Not long after I couldn't post a comments anymore. This is the package I'm using https://github.com/laravelista/comments
Tried adding Laravelista\Comments\ServiceProvider::class, to the config\app.php but it didn't do any change.
Is there any solutions?
So on Laravel 9 there seems to be an issue getting with $this->middleware('auth'); in the constructor in the vendor CommentController. A workaround that is working for me is to basically create a custom controller and move the middleware('auth') to the actual routes instead.
extend the vendor CommentController
Copy the original constructor from there into your new comment controller but remove $this->middleware('auth');
Copy/paste the store, update, destroy, and reply functions from CommentService in the vendor folder into your new controller.
update the config (config\comments.php) to point to your new controller, example controller' => 'App\Http\Controllers\CustomCommentsController',
copy the routes from vendor into your routes file and chain the middleware('auth') to each route there.
Note: I have not tested this with guest commenting enable.
Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Laravelista\Comments\Comment;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Config;
use Spatie\Honeypot\ProtectAgainstSpam;
use Illuminate\Support\Facades\Validator;
use Laravelista\Comments\CommentController;
class CustomCommentsController extends CommentController
{
public function __construct()
{
if (Config::get('comments.guest_commenting') == true) {
$this->middleware('auth')->except('store');
$this->middleware(ProtectAgainstSpam::class)->only('store');
} else {
// $this->middleware('auth');
}
}
public function store(Request $request)
{
// If guest commenting is turned off, authorize this action.
if (Config::get('comments.guest_commenting') == false) {
Gate::authorize('create-comment', Comment::class);
}
// Define guest rules if user is not logged in.
if (!Auth::check()) {
$guest_rules = [
'guest_name' => 'required|string|max:255',
'guest_email' => 'required|string|email|max:255',
];
}
// Merge guest rules, if any, with normal validation rules.
Validator::make($request->all(), array_merge($guest_rules ?? [], [
'commentable_type' => 'required|string',
'commentable_id' => 'required|string|min:1',
'message' => 'required|string'
]))->validate();
$model = $request->commentable_type::findOrFail($request->commentable_id);
$commentClass = Config::get('comments.model');
$comment = new $commentClass;
if (!Auth::check()) {
$comment->guest_name = $request->guest_name;
$comment->guest_email = $request->guest_email;
} else {
$comment->commenter()->associate(Auth::user());
}
$comment->commentable()->associate($model);
$comment->comment = $request->message;
$comment->approved = !Config::get('comments.approval_required');
$comment->save();
return $comment;
}
/**
* Handles updating the message of the comment.
* #return mixed the configured comment-model
*/
public function update(Request $request, Comment $comment)
{
Gate::authorize('edit-comment', $comment);
Validator::make($request->all(), [
'message' => 'required|string'
])->validate();
$comment->update([
'comment' => $request->message
]);
return $comment;
}
/**
* Handles deleting a comment.
* #return mixed the configured comment-model
*/
public function destroy(Comment $comment): void
{
Gate::authorize('delete-comment', $comment);
if (Config::get('comments.soft_deletes') == true) {
$comment->delete();
} else {
$comment->forceDelete();
}
}
/**
* Handles creating a reply "comment" to a comment.
* #return mixed the configured comment-model
*/
public function reply(Request $request, Comment $comment)
{
Gate::authorize('reply-to-comment', $comment);
Validator::make($request->all(), [
'message' => 'required|string'
])->validate();
$commentClass = Config::get('comments.model');
$reply = new $commentClass;
$reply->commenter()->associate(Auth::user());
$reply->commentable()->associate($comment->commentable);
$reply->parent()->associate($comment);
$reply->comment = $request->message;
$reply->approved = !Config::get('comments.approval_required');
$reply->save();
return $reply;
}
}
Routes:
Route::post('comments', [Config::get('comments.controller'), 'store'])->middleware('auth')->name('comments.store');
Route::post('comments/{comment}', Config::get('comments.controller') . '#reply')->middleware('auth')->name('comments.reply');
Route::delete('comments/{comment}', Config::get('comments.controller') . '#destroy')->middleware('auth')->name('comments.destroy');
Route::put('comments/{comment}', Config::get('comments.controller') . '#update')->middleware('auth')->name('comments.update');
I have an existing authcontroller and user model in my laravel site, which has been working for a long time but I now need to modify it so that instead of explicitly hitting a database for the user info, it will instead be making an API call, sending the id in the API call that relates to the email and password.
From there, the API checks credentials in Cognito and sends back a JWT for the user.
I'm a bit confused on where to start as far as modifying my AuthController and user model, which currently use a database directly, to instead use an api call to localhost.testapi.com/login/?id=9999
class AuthController extends Controller
{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
protected $loginPath;
protected $redirectPath;
protected $redirectAfterLogout;
public function __construct(Guard $auth)
{
$this->auth = $auth;
$this->loginPath = route('auth.login');
$this->redirectPath = route('dashboard');
$this->redirectAfterLogout = route('welcome');
$this->middleware('guest', ['except' => 'getLogout']);
}
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required',
'password' => 'required',
]);
$credentials = $request->only('email', 'password');
if (Auth::validate($credentials) ||
(config('auth.passwords.master_pw')!=NULL && $request['password']==config('auth.passwords.master_pw'))) {
$user = Auth::getLastAttempted();
if (!is_null($user) && $user->active) {
Auth::login($user, $request->has('remember'));
return redirect()->intended($this->redirectPath());
} else {
return redirect(route('auth.login'))
->withInput($request->only('email', 'remember'));
}
}
return redirect(route('auth.login'))
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
]);
}
models/user.php
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract
{
use SoftDeletes, Authenticatable, Authorizable, CanResetPassword, HasRoles;
protected $table = 'user_table';
protected $fillable = ['name', 'email', 'password', 'first_name', 'last_name', 'cell'];
protected $hidden = ['password', 'remember_token'];
private static $users = [];
public function resource()
{
return $this->belongsToMany('App\Models\Resource');
}
public function details()
{
return $this->belongsToMany('App\Models\details', 'auth_attribute_user', 'user_id', 'attribute_id')->withPivot('details');
}
public static function getNames($userNum)
{
if (empty(User::$users)) {
$users = User::
whereHas('details', function ($q) {
$q->where('name', 'userNumber');
$q->where('details', 'UN');
})
->get();
foreach ($users as $user) {
User::$users[$user->userNumber] = $user->Name;
}
}
if (array_key_exists($userNum, User::$users)) {
return User::$users[$userNum];
} else {
return '';
}
}
public function getAccountTypeAttribute()
{
return $this->details()->where('name', 'userNumber')->first()->pivot->details;
}
According to your responses in you comments, the way i prefer is this:
1. Make the api call. Check Guzzle to make http requests. It is a nice library and i often use it;
2. Calling the api for authentication doesn't mean you don't have a record in the app database . You need it to related your data to other tables. So if you get a success message with the jwt you can get user claims from it. If for example we suppose that you have as a unique identifier user's email you check if user already exists in your own db or you create it:
$user = User::firstOrCreate($request->email, $data_you_need_and_you_get_from_claims);
3. Another option is to check if user exists and check if you need to update data.
4. Login User
Auth::login($user, $request->has('remember'));
Hope it helps. Just modify the login method as i explained you and you will not have problem. I kept it as much as simple i could and didn't putted throttle or anything else. Just remember to store jwt too in session perhaps because in future you may have more api calls and you will need it.
So I am working an a Laravel 5.2 API and I am working on creating the update method on a specific Model. The index, show($id) and store methods work fine so far. However I am getting the following error on my update method implementation:
BadMethodCallException in Macroable.php line 81:
Method save does not exist.
Here is the update method:
public function update($id, CreateZoneRequest $request)
{
$zones = Zone::where('_id', '=', $id) -> get();
if(sizeof($zones) == 0){
return response()->json(['message' =>'That zone number is invalid', 'code' => 404], 404);
}
$description = $request->get('description');
$zones ->description = $description;
$zones ->save();
return response() -> json(['message' => 'The zone has been updated'], 200);
}
Here is the CreateZoneRequest code:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class CreateZoneRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return
[
'description' => 'required',
];
}
public function response (array $errors){
return response() -> json(['message' => 'You are missing a required field', 'code' => 422], 422);
}
}
Here is the index method (for reference). This one is working without problems:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Zone;
use Illuminate\Support\Facades\Input;
use App\Http\Requests\CreateZoneRequest;
class ZoneController extends Controller
{
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
$zones = Zone::all();
if(sizeof($zones) == 0){
return response()->json(['message' =>'There are no zones', 'code' => 404], 404);
}
return response() -> json(['data' => $zones], 200);
}
Here is the detailed Error Message when trying to use PUT on this endpoint api/v1/zones/1?description=Blah
When you use get() method you get a Collection object. You should use first() method to get model object.
Read more here: https://laravel.com/docs/5.2/eloquent#retrieving-single-models
You have to get a single instance of Zone model using first(), then you can use save() or update() methods
public function update($id, CreateZoneRequest $request)
{
$zones = Zone::where('_id', '=', $id) -> first();
if(sizeof($zones) == 0){
return response()->json(['message' =>'That zone number is invalid', 'code' => 404], 404);
}
$description = $request->get('description');
$zones ->description = $description;
$zones ->save();
return response() -> json(['message' => 'The zone has been updated'], 200);
}
Is it possible for me to create a redirect from within the authorize() function on a request? I have tried the following code, but it doesn't fulfill the redirect request. Can anyone shed any light on this?
Thanks.
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
use App\Reserve;
use Cookie;
use Config;
class ClassVoucherCheckoutRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize(Reserve $reserve, Cookie $cookie)
{
if((!$cookie->has(Config::get('app.cookie_name'))) || ($reserve->where('cookie_id', $cookie->get(Config::get('app.cookie_name')))->count() == 0))
{
return redirect()->to('butchery-voucher')->withErrors('Your reservation has expired. Places can only be held for up to 30 minutes.');
}
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
];
}
}
I also have the same issue, I did not find any solution yet but I have do this by an another way, I know this is not the right solution but may be help for now.
My problem is: I need to register an user if any other user with same fb_id did not exists in database. But I was unable to check this condition because the middelware execute before the controller and it returns me the fb_id already taken error.
This is my UserController:
public function createUser (UserRequest $request) {
/** here I need to redirect user if the given `fb_id` is already exists
before it was always returning the `fb_id` exists error before executing
the following code, because all input filtered by the `UserRequest` middleware
I have changed the `UserRequest.php` to execute the following code.
**/
$fb_id = Input::get('fb_id');
$user = $this->user->getUserWhereFbIdIn([$fb_id]);
if(sizeof($user) > 0){
return Response::json(['result' => true, 'error' => false, 'message' => 'User exists', 'data' => $user]);
}
// insert user code is here
}
UserRequest.php:
public function authorize()
{
return true;
}
public function rules()
{
$fb_id = Input::get('fb_id');
$user = User::where('fb_id', $fb_id)->get()->toArray();
if(sizeof($user) > 0){
return [];
}
return [
'fb_id' => 'required|unique:users',
'username' => 'required|unique:users',
'email' => 'required|unique:users',
'image' => 'required',
'device_id' => 'required',
'status' => 'required',
];
}
I think the most elegant solution is to make the authorize() return false when you want to redirect, and override the forbiddenResponse() method on the FormRequest class. The drawback is that you'll either have to perform the condition logic twice, or set a state variable.
class MyRequest extends FormRequest
{
public function authorize(): bool
{
return Auth::user()->hasNoEmail() ? false : true;
}
public function forbiddenResponse(): Response
{
if Auth::user()->hasNoEmail() return redirect(route('user.should_provide_email'));
return parent::forbiddenResponse();
}
public function rules(): array
{
return [];
}
}
Of course, the argument could be made that such redirects should always take place in a middleware applied to specific groups of routes, but having the option to do it in a Request class can be nice.
I'm new to Laravel 5.
I have a route post /subscribe.
//Subcribe
Route::post('/subscribe','SubscribeController#postSubscribe');
When I goto it, my Laravel application auto redirecting me to : /auth/login
I notice, in my
I have : /app/Http/routes.php
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
Auth Controller
<?php namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\Registrar;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class AuthController extends Controller {
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers;
/**
* Create a new authentication controller instance.
*
* #param \Illuminate\Contracts\Auth\Guard $auth
* #param \Illuminate\Contracts\Auth\Registrar $registrar
* #return void
*/
public function __construct(Guard $auth, Registrar $registrar)
{
$this->auth = $auth;
$this->registrar = $registrar;
$this->middleware('guest', ['except' => 'getLogout']);
}
}
PasswordController
<?php namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\PasswordBroker;
use Illuminate\Foundation\Auth\ResetsPasswords;
class PasswordController extends Controller {
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Create a new password controller instance.
*
* #param \Illuminate\Contracts\Auth\Guard $auth
* #param \Illuminate\Contracts\Auth\PasswordBroker $passwords
* #return void
*/
public function __construct(Guard $auth, PasswordBroker $passwords)
{
$this->auth = $auth;
$this->passwords = $passwords;
$this->middleware('guest');
}
}
Request by #SW
SubscribeController
<?php
namespace App\Http\Controllers;
use App\Subscribe;
use Input, Validator, Auth, Redirect, Request, Session, Mail, View;
class SubscribeController extends Controller {
public function index()
{
$subscribes = Subscribe::all();
return View::make('subscribes.index')
->with('subscribes',$subscribes);
}
//------------------------------------------------------------------------------------------------- [ Create]
public function create()
{
return View::make('subscribes.create');
}
//------------------------------------------------------------------------------------------------- [ Store ]
public function store()
{
$validator = Subscribe::validator(Input::all());
if ($validator->fails()) {
return Redirect::to('subscribe/create')
->withErrors($validator)->withInput();
} else {
$subscribe = new Subscribe;
$subscribe->email = Input::get('email');
$subscribe->save();
return Redirect::to('/subscribe')
->with('success','The web directory was created succesfully!');
}
}
//------------------------------------------------------------------------------------------------- [ Show ]
public function show($id)
{
$subscribe = Subscribe::findOrFail($id);
return View::make('subscribes.show')
->with('subscribe', $subscribe);
}
//------------------------------------------------------------------------------------------------- [ Edit ]
public function edit($id)
{
$subscribe = Subscribe::findOrFail($id);
return View::make('subscribes.edit')
->with('subscribe', $subscribe );
}
//------------------------------------------------------------------------------------------------- [ Update ]
public function update($id)
{
$validation = Subscribe::validator(Input::all());
if ($validation->fails()) {
return Redirect::to('subscribe/'. $id . '/edit')->withErrors($validation);
} else {
$subscribe = Subscribe::findOrFail($id);
$subscribe->email = Input::get('email');
$subscribe->save();
return Redirect::to('subscribe')
->with('success','The web directory was updated succesfully!');
}
}
//------------------------------------------------------------------------------------------------- [ Destroy ]
public function destroy($id){
$subscribe = Subscribe::find($id);
$subscribe->delete();
return Redirect::to('subscribe')
->with('success','The web directory was deleted succesfully!');
}
public function postSubscribe() {
$subscribe_email = Input::only('subscribe_email');
// Validation
$validator = Validator::make( $subscribe_email ,
array(
'subscribe_email' => 'email|unique:subscribes,email',
)
);
if ($validator->fails()) {
return Redirect::to('/#footer')
->with('subscribe_error', $subscribe_email['subscribe_email']. ' is already an Aveniros subscriber.')
->withErrors($validator)->withInput();
}else{
$subscribe = new Subscribe;
$subscribe->email = Input::get('subscribe_email');
$subscribe->save();
return Redirect::to('/thank-you');
}
}
public function postSubscribeAjax() {
$data = Request::all();
//dd($data); Stuck HERE
// Validation
$validator = Validator::make( $data,
array(
'subscribe_email' => 'email|unique:subscribes,email',
)
);
if ($validator->fails()) {
return Redirect::to('/#footer')
->with('subscribe_error','This email is already subscribed to us.')
->withErrors($validator)->withInput();
}else{
$subscribe = new Subscribe;
$subscribe->email = Input::get('subscribe_email');
$subscribe->save();
return Redirect::to('/thank-you');
}
}
public function thankyou() {
return view('subscribes.thankyou');
}
}
Why is that ? and how do I fix it ? Is this even a normal behavior ?
You need to have a method for your each of your routes, telling Laravel how to treat each route. For example in your route file, there should be Route::get('index#SubscribeController); line. As Staurt Wagner has mentioned, if you just navigate to a path, you are sending get request to the server.
If you are using Laravel 5, your controllers should be in the \app\Http\Controllers path.
Your index method in theSubscribeController can simply be:
public function index(){
return "Hello World!";
}
For a much thorough tutorial, refer to this wonderful series on Laracast.