Laravel 9: testing get profile (by slug) for created row - php

I wrote test:
public function test_hello_world(){
$test = User::create(['name' => 'Test',
'email' => 'test#test.com',
'password' => 'password',
]);
Profile::create([
'user_id' => $test->id,
'name' => 'Test',
'slug' => 'test'
]);
$this->get('/profile/test')
->assertStatus(200);
}
What this code should testing? After get to this url it should display details about profile. If profile with this slug doesn't exist, we have error 404. In this test I create user and profile table (this 2 tables is connection) but after run test I have the error:
Expected response status code [200] but received 404. Failed
asserting that 200 is identical to 404.
Why I have this error since I created profile with this slug? For me the best option will be create testing database with a lot of records and conduct all test on it. Is it possible? How do that?
#Edit
I have a route and controller's method which display user's profile. If I go (in web browser) to localhost/profile/slug, it works, if this profile exist. My controller's method look like this:
public function show($slug) {
$profile = Profile::where('slug', $slug)
->firstOrFail();
return Inertia::render('Profile/Single', [
'profile' => $profile,
]);
}
And route:
Route::get('/profile/{slug}',
[ProfileController::class, 'show'])
->name('profile.show');

According to your requirement you have to create route for getting profile from slug name. You did wrong in single function. Without creating route it will not worked.
So below example may work for you.
For example:-
For creating data
public function createData(){
$user = User::create(['name' => 'Test',
'email' => 'test#test.com',
'password' => 'password',
]);
Profile::create([
'user_id' => $user->id,
'name' => 'Test',
'slug' => 'test'
]);
return redirect()->back()->with('success', 'Data created');
}
For Getting Data
public function getDataBySlug($slug){
$profile = Profile::where('slug',$slug)->firstOrFail();
return redirect('/dashboard')->with('slug', $slug);
}
In route file
you have to mention table name and column name {profile:slug} instead of id
Route::get('/profile/create', 'Controller#createData');
Route::get('/profile/{profile:slug}', 'Controller#getDataBySlug');
Your route definition is wrong please do as above

Related

I cannot approve incoming creator applications gives 500 | SERVER ERROR

I have a Laravel 8 project. There is a feature to approve incoming creator references. However, when I press the create button when we want to approve the incoming applications, 500 | It gives a SERVER ERROR error.
When I look from Sentry, it shows the error as follows:
ErrorException creators_store
Undefined variable $user
CreatorController::store
public function store(Request $request){
$request->validate([
'name' => 'required',
'email' => 'required|email'
]);
$subscriber = User::where('email','=',$request->email)->get()->first();
$form_id = $request->form_id;
if($subscriber!=null){
// Already registered user
$subscriber->update([
'role_id' => 3,
'name' => $request->name,
]);
$subscriber = User::findorfail($subscriber->id);
$subscriber->profile_token = env('FRONTEND_PATH').'creator-profile-form?token='.base64_encode($subscriber->email.'/'.$subscriber->id);
Mail::send(['html'=>'email.creators.register'], ['creator' => $subscriber], function($message) use($subscriber){
$message->to($subscriber->email, $subscriber->name)->subject
('Welcome to the Creator Community');
$message->from('creatorcommunity#omnicourse.io','Omnicourse Creator Community');
});
}else{
// New Creator
$pass = random_int(100000, 999999);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($pass),
'role_id' => 3,
]);
}
if($form_id!=null){
//Formdan geldi
$form = CreatorApplicationForm::findorfail($form_id);
$form->update([
'creator_id' => $user->id
]);
}
return redirect('/admin-panel/creators');
}
It was giving a similar error before, but it was because that mailgun service was not paid for. We paid for the service, but this time it started to give an error like this, but we used the same codes before and it did not give an error. I don't understand why it gives an error even though we haven't made any code changes.
Anyone know the reason or solution for this?
The issue here is that you are creating a user in the else statement, so if it never reaches the else statement (because it is true) you will never have $user.
You can either rewrite your controller somehow or do something like
if(!isset($user)){
$user = [some universal hardcode];
}

laravel validator for rest api

I am trying to follow best practice for REST api on CRUD.
GET: users/ -> all
GET: users/:id -> one specific user.
POST: users/ -> add one
PUT: users/:id -> update specific user.
DELETE: users/:id -> delete one user.
On laravel 8 I want to validate the url :id using the validator, so I have like this on delete user:
$validator = Validator::make(['id' => $request->id], [
'id' => 'exists:users,id,deleted_at,NULL',
]);
And this way to update a user:
$validator = Validator::make(array_merge($request->all(), ['id' => $request->id]), [
'id' => 'required|exists:users,id,deleted_at,NULL',
'name' => 'required',
'surname' => 'required',
'email' => 'required|email:rfc,dns'
]);
As you can see I have to put the id on an array and/or merge with the $request->all().
There is any way in laravel to do this with the request?
I have found 3 ways by Laravel:
$request->add(['variable' => 'value']);
$request->merge(["key"=>"value"]);
$request->request->set(key, value);
But a solution for adding route params to the request before hitting the controller method would be even great.
You can update the request object on the fly and add the ID field, before you validate it, something like
$request['id'] = $id;
// note: the $id is your function's parameter name
$validator = Validator::make(array_merge($request->all()), [
'id' => 'required|exists:users,id,deleted_at,NULL',
'name' => 'required',
'surname' => 'required',
'email' => 'required|email:rfc,dns'
]);
You can do it like you are doing, but doing it with route model binding would be the way to go.
Now when you want to update a user by sending a PUT to /users/:id, and the user does not exist you will get a 422. But what you really want would be a 404.
With route model binding, Laravel will check if the model exists for you and abort with a 404 when it does not.
If route model binding is not an option, you can also just not validate the id with the validator and retrieve the user with User::findOrFail($request->input('id')), the framework will then still abort with a 404 if it can't be found.

My Laravel test is returning a 302 redirect rather than a 403 forbidden status

I have a Model called Type with a title field and a pretty_slug field.
I have a test that is checking that a user can not update a Type instance:
<?
public function test_user_cannot_put_update_page() {
$type = Type::factory()->make([
'title' => 'Original type',
]);
$type->save();
$response = $this->put(route('types.update', [
'pretty_slug' => $type->pretty_slug,
'title' => 'New type',
]));
$response->assertForbidden();
$this->assertDatabaseHas('types', [
'title' => 'Original type'
]);
}
If I do dd($response->getContent()); I can see that a redirect is happening:
Now the weird thing is that I have the exact same for another Model called Level:
<?
public function test_user_cannot_put_update_page() {
$level = Level::factory()->make([
'title' => 'Original level',
]);
$level->save();
$response = $this->put(route('levels.update', [
'pretty_slug' => $level->pretty_slug,
'title' => 'New level',
]));
$response->assertForbidden();
$this->assertDatabaseHas('levels', [
'title' => 'Original level'
]);
}
The Model Level is exactly the same as Type: the same Controller, the same Trait shared, same Policy, same Tests, same routes… I have other Models called Idea, Concept and Episode that have the exact same behavior.
All tests pass, except for my Type Model:
I have no idea why this particular types.update route is not working. It should return a 302 but is instead redirecting.
It is working when I use the webform: the Type instance updates correctly. But the test is failing.
How can I debug this test? Where do I look for an issue in my code?
Thanks for any help.
EDIT 1: added controller and routes
I think the problem is the 'levels.update' route might be protected by the auth middleware.
Since there is no user logged in, the auth middleware will attempt to redirect to the login page instead.
I like IGP's answer. But if that's not it, you might want to check your host configs. Apache or Nginx, or whatever you're using. It could be the route is being called via http and your server is redirecting to https, or visa versa.
Thanks to #Aless55, I found the issue: it was the validation of my Type model that was preventing me from updating the instance.
I looked into the StoreType file, in which I had:
'order' => 'required|numeric',
This means the order field is required. But when I tried calling the types.update route, I wasn't including that field.
One solution would have been to make that field optional. But I ended up including the order field in my test:
$response = $this->put(route('types.update', [
'pretty_slug' => $type->pretty_slug,
'title' => 'Alex new type',
'order' => 1,
]));

Trying to store login history inside laravels basic exampel for "manually authenticating users"

I used Laravel's guide to authenticating users manually at this link:
https://laravel.com/docs/7.x/authentication#remembering-users
and now I want to log every login's browser, version, platform, and ip.
My function on login:
public function store(Request $request)
{
$this->validate($request, [
'username' => 'required',
'password' => 'required'
]);
if (Auth::guard('admin')->attempt(['username' => $request->username, 'password' => $request->password, 'status' => 1], $request->remember)) {
$browserDetails = get_browser($request->header('User-Agent'), true);
LoginHistory::create([
'user_id' => auth()->guard('admin')->user()->id,
'user_type' => '2', // Admin = 2
'browser' => $browserDetails['browser'],
'browser_version' => $browserDetails['version'],
'platform' => $browserDetails['platform'],
'ip_address' => $request->ip()
]);
return redirect()->route('admin.dashboard');
}
return redirect()->back()->withErrors('Username or password incorrect.');
}
but I am getting:
ErrorException
Trying to get property 'id' of non-object
on this line:
'user_id' => auth()->guard('admin')->user()->id,
What should I do? The authentication works if I try to access login it will redirect me to dashboard so the session is created, but why can I not access the user id inside this function? It works on the edit admins page showing user id and all information.
use auth()->user()->id. when attempt () is executed and this is successful it performs the authentication

Laravel Eloquent Create does nothing

So I'm learning Laravel, and I'm trying to create a new user in the database using data entered into a form. In my controller, I'm getting the form data fine, passing it to a validator with some rules which pass fine, but then when I try to create the User, nothing gets added to the database and it redirects to the basic "Whoops, looks like something went wrong." error page instead of the page I'm telling it to.
Here's my controller function:
public function doRegister() {
$rules = array(
'fname'=>'required|alpha|min:2',
'lname'=>'required|alpha|min:2',
'email'=>'required|email|unique:users',
'company'=>'required|alpha|min:2',
'password'=>'required|alpha_num|between:6,12|confirmed',
'password_confirmation'=>'required|alpha_num|between:6,12'
);
$validator = Validator::make(Input::all(), $rules);
if($validator->passes()) {
User::create(array(
'fname' => Input::get('fname'),
'lname' => Input::get('lname'),
'email' => Input::get('email'),
'password' => Hash.make(Input::get('password')),
'company' => Input::get('company'),
'created_at' => date('Y-m-d H:m:s'),
'updated_at' => date('Y-m-d H:m:s')
));
return Redirect::to('login')->with('message', 'Thank you for registering!');
} else {
return Redirect::to('register')
->with('message', 'The following errors occurred')
->withErrors($validator)
->withInput(Input::except('password'));
}
}
Removing the User::create() section, the redirect works perfectly fine. Just to start with I've included all the database fields in the fillable array in my User model. Still doesn't work. Any ideas?
Not the direct answer to your question, but the quickest way for you to find it.
Open app.php
edit the last line seen in this picture from (in your case) false to true:
Once done that, laravel will tell you what the error is.
One error for sure is
'password' => Hash.make(Input::get('password')),
should be with ::
'password' => Hash::make(Input::get('password')),
You don't need this:
'created_at' => date('Y-m-d H:m:s'),
'updated_at' => date('Y-m-d H:m:s')
laravel will do this for you!
If it doesn't work after this, try to run
php artisan dump-autoload
from your terminal to generate an optimized class loader!

Categories