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.
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.
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.