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 [email protected] 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 IlluminateHttpRequest;
use IlluminateSupportFacadesRoute;
use StanclTenancyMiddlewareInitializeTenancyByDomain;
use StanclTenancyMiddlewarePreventAccessFromCentralDomains;
use AppHttpControllersUserController;
/*
|--------------------------------------------------------------------------
| 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.
2
Answers
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:
Hopefully this will help other developers solve the problem detailed above.
Best regards,
Ignacio Y. C.
A common thing I faced when using tenancy for laravel is the default
Authenticate
middleware included with the SaaS boilderplate you can purchase. It extends the default laravelAuthenticate
and adds this code:This redirects all requests to the
tenant.login
view if theAccept: application/json
header is missing.I can’t really see the headers of the request you’re seding to
GetUserAuth
, but this could be the reason.