-1

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,
    ],

];

1 Answers1

0

Since you are using api routes (api.php), you can edit cors in config/cors.php file.

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure your settings for cross-origin resource sharing
    | or "CORS". This determines what cross-origin operations may execute
    | in web browsers. You are free to adjust these settings as needed.
    |
    | To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
    |
    */

    'paths' => ['api/*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['POST', 'GET'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => false,

];

In paths, you can specify which routes cors extends to. By default, api/* is already there. Set allow_origins to the endpoints from which requests are allowed (in your case this is http://localhost:3000)

deekep
  • 119
  • 1
  • 7