phplaravelvue.jsmulti-tenantsaas

Why do api routes in tenant.php with Laravel VueJs are working with 200 OK status code in network tools but I'm receiving a blade as a response?


First of all, I'd like to comment on this that I'm working on a project based on Laravel VueJs with tenancy for laravel v3 package.

To get into context, I can perfectly log in on my name@example.com account registered at any created tenant on local development but after logging in, I'm struggling mainly with TypeError: Cannot read properties of undefined (reading 'xxxxx') in console with all the api-related and VueJs routes. I have been digging deeper over the problem and got into a conclusion.

TypeError: Cannot read properties of undefined (reading 'xxxxx')

And with that, I figured out my GET route with GetUserAuth as uri at 'api' middleware on tenant.php is recognized but isn't calling the method associated to it but throwing as a status code 200 OK. Instead, the response is a blade as in the following picture.

Where Respuesta is Response

It's also important to mention I've set up Laravel Passport according to the stancl/tenancy v3 documentation, specifically using Passport in the tenant application only with shared passport encryption keys.

The following code refers to my tenant.php

<?php

declare(strict_types=1);

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
use Stancl\Tenancy\Middleware\PreventAccessFromCentralDomains;
use App\Http\Controllers\UserController;

/*
|--------------------------------------------------------------------------
| Tenant Routes
|--------------------------------------------------------------------------
|
| Here you can register the tenant routes for your application.
| These routes are loaded by the TenantRouteServiceProvider.
|
| Feel free to customize them however you want. Good luck!
|
*/

Route::middleware(['api', InitializeTenancyByDomain::class, PreventAccessFromCentralDomains::class])->group(
    function ()
    {
        /*auth middleware api passport token*/
        Route::middleware('auth:api')->get('/user', function (Request $request) {
            return $request->user();
        });
        
        // Other routes

        Route::middleware(['auth:api', 'Is_Active'])->group(function ()
        {
            //Other routes

            //------------------------------- Users --------------------------\\

            Route::get('GetUserRole', [UserController::class, "GetUserRole"]);
            Route::get('GetUserAuth', [UserController::class, "GetUserAuth"]);
            Route::get("/GetPermissions", [UserController::class, "GetPermissions"]);
            Route::resource('users', UserController::class);
            Route::put('users/Activated/{id}', [UserController::class, "IsActivated"]);
            Route::get('users/export/Excel', [UserController::class, "exportExcel"]);
            Route::get('users/Get_Info/Profile', [UserController::class, "GetInfoProfile"]);
            Route::put('updateProfile/{id}', [UserController::class, "updateProfile"]);
        });
    });

Route::middleware(['web', InitializeTenancyByDomain::class, PreventAccessFromCentralDomains::class])->group(
     function ()
     {
          // Web routes   
     });

The following one is referring to the code located at C:/project-root/resources/src/store/modules/auth.js

import Vue from 'vue'
import Vuex from 'vuex'
// import VueCookie from 'vue-cookie'
import axios from 'axios'
import router from "./../../router";
Vue.use(Vuex)
// Vue.use(VueCookie)


const state = {
    // token: Vue.cookie.get('Stocky_token'),
    isAuthenticated:false,
    Permissions: null,
    user: {},
    loading: false,
    error: null,
    notifs:0,
};


const getters = {
    isAuthenticated: state => state.isAuthenticated,
    currentUser: state => state.user,
    currentUserPermissions: state => state.Permissions,
    loading: state => state.loading,
    notifs_alert: state => state.notifs,
    error: state => state.error
};

const mutations = {
    setLoading(state, data) {
        state.loading = data;
        state.error = null;
    },
    setError(state, data) {
        state.error = data;
        state.loggedInUser = null;
        state.loading = false;
    },
    clearError(state) {
        state.error = null;
    },
    // setLoginCred(state, payload) {
    //     state.token = payload.token;
    //     // state.isAuthenticated = true;
    // },

    setPermissions(state, Permissions) {
        state.Permissions = Permissions;
        // state.user = user;
    },


    setUser(state, user) {
        state.user = user;
    },

    // SET_AUTHENTICATED(state, isAuthenticated) {
    //     state.isAuthenticated = isAuthenticated;
    // },

    Notifs_alert(state, notifs) {
        state.notifs = notifs;
    },

    logout(state) {
        // state.token = null;
        state.user = null;
        state.Permissions = null;
        // state.isAuthenticated = false;
        // Vue.cookie.delete('Stocky_token');
        state.loggedInUser = null;
        state.loading = false;
        state.error = null;
    },
};

const actions = {

    // setLoginCred(context, payload) {
    //     context.commit('setLoading', true)
    //     context.commit('setLoginCred', payload)
    // },

    async refreshUserPermissions(context) {

        await axios.get("GetUserAuth").then((userAuth) => {
            let Permissions = userAuth.data.permissions
            let user = userAuth.data.user
            let notifs = userAuth.data.notifs

            // context.commit('SET_AUTHENTICATED', true)
            context.commit('setPermissions', Permissions)
            context.commit('setUser', user)
            context.commit('Notifs_alert', notifs)
        }).catch(() => {
            // context.commit('SET_AUTHENTICATED', false)
            context.commit('setPermissions', null)
            context.commit('setUser', null)
            context.commit('Notifs_alert', null)
        });
    },

    logout({ commit }) {

        axios({method:'post',  url: '/logout', baseURL: '' })
          .then((userData) => {
            window.location.href='/login';
        })
    },
};

export default {
    state,
    getters,
    actions,
    mutations
};

And the following one refers to the mentioned before method on UserCon related with the GET route throwing status code 200 OK with a blade as a response

   //------------- GET USER Auth ---------\\

    public function GetUserAuth(Request $request)
    {
        $helpers = new helpers();
        $user['avatar'] = Auth::user()->avatar;
        $user['username'] = Auth::user()->username;
        $user['currency'] = $helpers->Get_Currency();
        $user['logo'] = Setting::first()->logo;
        $user['footer'] = Setting::first()->footer;
        $user['developed_by'] = Setting::first()->developed_by;
        $user['initCCF'] = Auth::user()->initCCF;
        $user['currentCCF'] = Auth::user()->currentCCF;
        $user['finalCCF'] = Auth::user()->finalCCF;
        $user['initCF'] = Auth::user()->initCF;
        $user['currentCF'] = Auth::user()->currentCF;
        $user['finalCF'] = Auth::user()->finalCF;
        $user['warehouse_id'] = Auth::user()->warehouse_id;
        $permissions = Auth::user()->roles()->first()->permissions->pluck('name');
        $products_alerts = product_warehouse::join('products', 'product_warehouse.product_id', '=', 'products.id')
            ->whereRaw('qte <= stock_alert')
            ->where('product_warehouse.deleted_at', null)
            ->count();

        return response()->json([
            'success' => true,
            'user' => $user,
            'notifs' => $products_alerts,
            'permissions' => $permissions,
        ]);
    }

Finally, I'd like to mention that my application with central domain only and a single database was working perfectly but I don't know what could be the problem even debugging, checking all the documentation related and other answered questions but none of those fixed my issue and I need help as soon as possible. Any suggestions or help are welcomed and if you need extra information, please let me know. Thanks in advance for taking your time.


Solution

  • First of all, sorry for my delayed solution.

    For those who are struggling with the same issue I went through the past year using stancl/tenancy v3 package, and as I mentioned in this comment, I'll leave over here my passport.php settings:

    <?php
    
    return [
    
        /*
        |--------------------------------------------------------------------------
        | Encryption Keys
        |--------------------------------------------------------------------------
        |
        | Passport uses encryption keys while generating secure access tokens for
        | your application. By default, the keys are stored as local files but
        | can be set via environment variables when that is more convenient.
        |
        */
    
        'private_key' => env('PASSPORT_PRIVATE_KEY', storage_path('oauth-private.key')),
    
        'public_key' => env('PASSPORT_PUBLIC_KEY', storage_path('oauth-public.key')),
    
        /*
        |--------------------------------------------------------------------------
        | Client UUIDs
        |--------------------------------------------------------------------------
        |
        | By default, Passport uses auto-incrementing primary keys when assigning
        | IDs to clients. However, if Passport is installed using the provided
        | --uuids switch, this will be set to "true" and UUIDs will be used.
        |
        */
    
        'client_uuids' => false,
    
        /*
        |--------------------------------------------------------------------------
        | Personal Access Client
        |--------------------------------------------------------------------------
        |
        | If you enable client hashing, you should set the personal access client
        | ID and unhashed secret within your environment file. The values will
        | get used while issuing fresh personal access tokens to your users.
        |
        */
    
        'personal_access_client' => [
            'id' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_ID'),
            'secret' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET'),
        ],
    
        /*
        |--------------------------------------------------------------------------
        | Passport Storage Driver
        |--------------------------------------------------------------------------
        |
        | This configuration value allows you to customize the storage options
        | for Passport, such as the database connection that should be used
        | by Passport's internal database models which store tokens, etc.
        |
        */
    
        'storage' => [
            'database' => [
                'connection' => null,
            ],
        ],
    
        'key_path' => env('OAUTH_KEY_PATH', storage_path(''))
    ];
    

    Hopefully this will help other developers solve the problem detailed above.

    Best regards,

    Ignacio Y. C.