in my Laravel/react/xampp project i have an error when i try to edit the company info ;
In the terminal when i run php artisan serve it tels me updat and save methodes are not defined . and in my browser when i click save all to edit the company info i get an errore saying : Access to XMLHttpRequest at 'http://localhost:8000/home' (redirected from 'http://localhost:8000/api/update_company') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.s
here is my files that can be helpful :
react component where i fill the form by default by the company stored in localstorage when i first login . the ogic is when i change the form and click save all it will edit the company info in my DB table to :
import React, { useEffect, useState } from "react";
import axios from 'axios'
const Profile = () => {
const companyAuth = localStorage.getItem("company")
console.log(companyAuth)
const token = localStorage.getItem("token")
console.log(token)
const [companyData, setCompanyData] = useState({
company_name: "",
industry: "",
description: "",
company_contact: "",
headquarters: "",
ceo_founder: "",
email: "",
password: "",
});
useEffect(() => {
const storedCompanyData = localStorage.getItem("company");
if (storedCompanyData) {
setCompanyData(JSON.parse(localStorage.getItem("company")));
}
}, []);
const handleInputChange = (event) => {
const { name, value } = event.target;
setCompanyData((prevData) => ({
...prevData,
[name]: value,
}));
};
const handleSubmit = async (e) => {
e.preventDefault();
// console.log("companyData updated ", companyData)
localStorage.setItem("company", companyData);
try {
const response = await axios.put(
"http://localhost:8000/api/update_company",
companyData,
{
headers: {
Authorization: `Bearer ${token}`, // Include the API token
},
}
);
console.log(response.data.message); // Display the response message
} catch (error) {
console.error("Error:", error.response.data);
}
};
return (
<div className="relative bg-blue-600 w-full h-full ">
<div className=" p-10 absolute flex flex-col justify-center items-center w-full">
<div>
<h1 className="text-2xl text-[#FF6600] pb-6">
Company name
</h1>
</div>
<div className="w-full bg-red-6 ">
<form onSubmit={handleSubmit}>
<div className="grid gap-6 mb-6 md:grid-cols-2">
<div>
<label
for="first_name"
className="block mb-2 text-sm font-medium text-[#FF6600]"
>
Company Name
</label>
<input
type="text"
id="first_name"
className="text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
placeholder="John"
name="company_name"
value={companyData.company_name}
onChange={handleInputChange}
/>
</div>
<div>
<label
for="last_name"
className="block mb-2 text-sm font-medium text-[#FF6600]"
>
Industry
</label>
<input
type="text"
id="last_name"
className="text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
placeholder="Doe"
name="industry"
value={companyData.industry}
onChange={handleInputChange}
/>
</div>
<div>
<label
for="company"
className="block mb-2 text-sm font-medium text-[#FF6600]"
>
Description
</label>
<input
type="text"
id="company"
className="text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
placeholder="Flowbite"
name="description"
value={companyData.description}
onChange={handleInputChange}
/>
</div>
<div>
<label
for="phone"
className="block mb-2 text-sm font-medium text-[#FF6600]"
>
Contact
</label>
<input
type="text"
id="phone"
className="text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
placeholder="123-45-678"
name="company_contact"
value={companyData.company_contact}
onChange={handleInputChange}
/>
</div>
<div>
<label
for="website"
className="block mb-2 text-sm font-medium text-[#FF6600]"
>
Headquarters
</label>
<input
type="text"
id="website"
className="text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
placeholder="true/false"
name="headquarters"
value={companyData.headquarters}
onChange={handleInputChange}
/>
</div>
<div>
<label
for="visitors"
className="block mb-2 text-sm font-medium text-[#FF6600]"
>
Ceo Founder
</label>
<input
type="text"
id="visitors"
className="text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
placeholder="Frontend dev"
name="ceo_founder"
value={companyData.ceo_founder}
onChange={handleInputChange}
/>
</div>
</div>
<div className="mb-6">
<label
for="email"
className="block mb-2 text-sm font-medium text-[#FF6600]"
>
Email address
</label>
<input
type="email"
id="email"
className="text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
placeholder="john.doe@company.com"
name="email"
value={companyData.email}
onChange={handleInputChange}
/>
</div>
<div className="mb-6">
<label
for="password"
className="block mb-2 text-sm font-medium text-[#FF6600]"
>
Password
</label>
<input
type="password"
id="password"
className="text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
placeholder="•••••••••"
name="password"
value={companyData.password}
onChange={handleInputChange}
/>
</div>
<div className="mb-6">
<label
for="confirm_password"
className="block mb-2 text-sm font-medium text-[#FF6600]"
>
Confirm password
</label>
<input
type="password"
id="confirm_password"
className="text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
placeholder="•••••••••"
/>
</div>
<button
type="submit"
className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Save all
</button>
</form>
</div>
</div>
</div>
);
};
export default Profile;
here is my api.php :
<?php
use App\Http\Controllers\CompanyAuthController;
use App\Http\Controllers\EmployeeAuthContoller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/
// Authenticate Company
Route::post('/Register', [CompanyAuthController::class, 'register']);
Route::post('/login', [CompanyAuthController::class, 'login']);
Route::post('/logout', [CompanyAuthController::class, 'logout']);
Route::middleware('auth:sanctum')->group(function () {
Route::put('/update_company', [CompanyAuthController::class, 'updateCompany']);
});
// Authenticate Employee
Route::post('/Employee/AddEmployee', [EmployeeAuthContoller::class, 'addEmployeee']);
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
here is my CompanyAuthcontroller.php :
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use App\Models\Company;
use Illuminate\Validation\ValidationException;
class CompanyAuthController extends Controller
{
public function __construct()
{
$this->middleware('guest')->except('logout');
}
protected function guard()
{
return Auth::guard('company');
}
// Register method for API
public function register(Request $request)
{
// ... Registration logic as previously mentioned
// return response()->json(['Message' => 'Connected to DB '], 201);
$validator = Validator::make($request->all(), [
'company_name' => 'required|string',
'industry' => 'required|string',
'description' => 'required|string',
'company_contact' => 'required|string',
'headquarters' => 'required|string',
'ceo_founder' => 'required|string',
'email' => 'required|email|unique:companies',
'password' => 'required|string|min:8',
]);
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
$company = new Company();
$company->company_name = $request->input('company_name');
$company->industry = $request->input('industry');
$company->description = $request->input('description');
$company->company_contact = $request->input('company_contact');
$company->headquarters = $request->input('headquarters');
$company->ceo_founder = $request->input('ceo_founder');
$company->email = $request->input('email');
$company->password = bcrypt($request->input('password'));
// $company->save();
try {
$company->save();
return response()->json(['message' => 'Company account created successfully!'], 201);
} catch (\Exception $e) {
return response()->json(['error' => 'Failed to create Company account'], 500);
}
}
// Login method for API
public function login(Request $request)
{
// ... Login logic as previously mentioned
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$company = Company::where('email', $request->email)->first();
if (!$company || !Hash::check($request->password, $company->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}
if ($company->company_name !== $request->company_name) {
throw ValidationException::withMessages([
'company_name' => ['The provided company name is incorrect.'],
]);
}
$token = $company->createToken('company-token')->plainTextToken;
return response()->json([
'message' => 'Company logged in successfully',
'token' => $token,
'company' => $company,
], 200);
}
public function updateCompany(Request $request)
{
$user = Auth::guard('company')->user(); // Get the authenticated user (company)
if (!$user) {
return response()->json(['message' => 'Unauthenticated.'], 401);
}
// Validate the incoming data
$validator = Validator::make($request->all(), [
'company_name' => 'required|string',
'industry' => 'required|string',
'description' => 'required|string',
'company_contact' => 'required|string',
'headquarters' => 'required|string',
'ceo_founder' => 'required|string',
'email' => 'required|email|unique:companies',
'password' => 'required|string|min:8',
]);
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
$user->update([
'company_name' => $request->input('company_name'),
'industry' => $request->input('industry'),
'description' => $request->input('description'),
'company_contact' => $request->input('company_contact'),
'headquarters' => $request->input('headquarters'),
'ceo_founder' => $request->input('ceo_founder'),
'email' => $request->input('email'),
'password' => $request->input('password'),
]);
// Update the password if provided
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
$user->save();
}
return response()->json(['message' => 'Company information updated successfully!'], 200);
}
// Logout method for API
public function logout(Request $request)
{
// ... Logout logic as previously mentioned
}
}
here is my Company.php model :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
// use Illuminate\Database\Eloquent\Model;
class Company extends Authenticatable
{
use HasFactory, HasApiTokens, Notifiable;
protected $fillable = [
'company_name',
'industry',
'description',
'company_contact',
'headquarters',
'ceo_founder',
'email',
'password'
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
}
here is my auth.php :
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'company' => [
'driver' => 'sanctum', // Use Sanctum driver
'provider' => 'companies', // Use the 'companies' provider
],
'employee' => [
'driver' => 'sanctum', // Use Sanctum driver
'provider' => 'employees', // Use the 'employees' provider
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'companies' => [
'driver' => 'eloquent',
'model' => App\Models\Company::class,
],
'employees' => [
'driver' => 'eloquent',
'table' => App\Models\Employee::class,
],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expiry time is the number of minutes that each reset token will be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
| The throttle setting is the number of seconds a user must wait before
| generating more password reset tokens. This prevents the user from
| quickly generating a very large amount of password reset tokens.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_reset_tokens',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
];
and finaly here is my sanctum.php:
<?php
use Laravel\Sanctum\Sanctum;
return [
/*
|--------------------------------------------------------------------------
| Stateful Domains
|--------------------------------------------------------------------------
|
| Requests from the following domains / hosts will receive stateful API
| authentication cookies. Typically, these should include your local
| and production domains which access your API via a frontend SPA.
|
*/
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
Sanctum::currentApplicationUrlWithPort()
))),
/*
|--------------------------------------------------------------------------
| Sanctum Guards
|--------------------------------------------------------------------------
|
| This array contains the authentication guards that will be checked when
| Sanctum is trying to authenticate a request. If none of these guards
| are able to authenticate the request, Sanctum will use the bearer
| token that's present on an incoming request for authentication.
|
*/
'guard' => ['web'],
/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. If this value is null, personal access tokens do
| not expire. This won't tweak the lifetime of first-party sessions.
|
*/
'expiration' => null,
/*
|--------------------------------------------------------------------------
| Sanctum Middleware
|--------------------------------------------------------------------------
|
| When authenticating your first-party SPA with Sanctum you may need to
| customize some of the middleware Sanctum uses while processing the
| request. You may change the middleware listed below as required.
|
*/
'middleware' => [
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],
];