@@ -19,7 +19,7 @@ class TenantsVerify extends Command
1919 *
2020 * @var string
2121 */
22- protected $ signature = 'tenants:verify ' ;
22+ protected $ signature = 'tenants:verify {--json : Output the results as JSON} ' ;
2323
2424 /**
2525 * The console command description.
@@ -33,20 +33,29 @@ class TenantsVerify extends Command
3333 *
3434 * @return int
3535 */
36+ private $ jsonData = [];
37+
3638 public function handle ()
3739 {
40+ if (!config ('app.multitenancy ' )) {
41+ $ this ->info ('Multitenancy is disabled ' );
42+
43+ return ;
44+ }
45+
46+ $ errors = [];
3847 $ currentTenant = null ;
3948 if (app ()->has ('currentTenant ' )) {
4049 $ currentTenant = app ('currentTenant ' );
4150 }
4251
43- if (config ( ' app.multitenancy ' ) && !$ currentTenant ) {
52+ if (!$ currentTenant ) {
4453 $ this ->error ('Multitenancy enabled but no current tenant found. ' );
4554
4655 return ;
4756 }
4857
49- $ this -> info ( ' Current Tenant ID: ' . ($ currentTenant ?->id ?? 'NONE ' ));
58+ \Log:: warning ( ' TenantsVerify: Current Tenant ID: ' . ($ currentTenant ?->id ?? 'NONE ' ));
5059
5160 $ paths = [
5261 ['Storage Path ' , storage_path ()],
@@ -55,32 +64,44 @@ public function handle()
5564 ];
5665
5766 // Display paths in a nice table
58- $ this ->table (['Path ' , 'Value ' ], $ paths );
67+ $ this ->infoTable (['Path ' , 'Value ' ], $ paths );
5968
6069 $ configs = [
61- 'app.key ' ,
62- 'app.url ' ,
63- 'app.instance ' ,
64- 'cache.prefix ' ,
65- 'database.redis.options.prefix ' ,
66- 'cache.stores.cache_settings.prefix ' ,
67- 'script-runner-microservice.callback ' ,
68- 'database.connections.processmaker.database ' ,
69- 'logging.channels.daily.path ' ,
70- 'filesystems.disks.public.root ' ,
71- 'filesystems.disks.local.root ' ,
72- 'filesystems.disks.lang.root ' ,
70+ 'app.key ' => null ,
71+ 'app.url ' => null ,
72+ 'app.instance ' => null ,
73+ 'cache.prefix ' => ' tenant_{tenant_id}: ' ,
74+ 'database.redis.options.prefix ' => null ,
75+ 'cache.stores.cache_settings.prefix ' => ' tenant_{tenant_id}:settings ' ,
76+ 'script-runner-microservice.callback ' => null ,
77+ 'database.connections.processmaker.database ' => null ,
78+ 'logging.channels.daily.path ' => base_path () . ' /storage/tenant_{tenant_id}/logs/processmaker.log ' ,
79+ 'filesystems.disks.public.root ' => base_path () . ' /storage/tenant_{tenant_id}/app/public ' ,
80+ 'filesystems.disks.local.root ' => base_path () . ' /storage/tenant_{tenant_id}/app ' ,
81+ 'filesystems.disks.lang.root ' => base_path () . ' /resources/lang/tenant_{tenant_id} ' ,
7382 ];
7483
75- $ configs = array_map (function ($ config ) {
84+ $ configs = array_map (function ($ config ) use ($ configs , $ currentTenant , &$ errors ) {
85+ $ ok = '' ;
86+ if ($ configs [$ config ] !== null ) {
87+ $ expected = str_replace ('{tenant_id} ' , $ currentTenant ->id , $ configs [$ config ]);
88+ if (config ($ config ) === $ expected ) {
89+ $ ok = '✓ ' ;
90+ } else {
91+ $ ok = '✗ ' ;
92+ $ errors [] = 'Expected: ' . $ expected . ' != Actual: ' . config ($ config );
93+ }
94+ }
95+
7696 return [
7797 $ config ,
7898 config ($ config ),
99+ $ ok ,
79100 ];
80- }, $ configs );
101+ }, array_keys ( $ configs) );
81102
82103 // Display configs in a nice table
83- $ this ->table (['Config ' , 'Value ' ], $ configs );
104+ $ this ->infoTable (['Config ' , 'Value ' , ' OK ' ], $ configs );
84105
85106 $ env = EnvironmentVariable::first ();
86107 if (!$ env ) {
@@ -102,10 +123,62 @@ public function handle()
102123 ['Tenant Config Is Cached ' , File::exists (app ()->getCachedConfigPath ()) ? 'Yes ' : 'No ' ],
103124 ['First username (database check) ' , User::first ()?->username ?? 'No users found ' ],
104125 ['Decrypted check ' , substr ($ decrypted , 0 , 50 )],
105- ['Original App URL (landlord) ' , $ currentTenant ?->getOriginalValue('APP_URL ' ) ?? config ('app.url ' )],
126+ // ['Original App URL (landlord)', $currentTenant?->getOriginalValue('APP_URL') ?? config('app.url')],
127+ ['config("app.url") ' , config ('app.url ' )],
128+ ['getenv("APP_URL") ' , getenv ('APP_URL ' )],
129+ ['env("APP_URL") ' , env ('APP_URL ' )],
130+ ['$_SERVER["APP_URL"] ' , $ _SERVER ['APP_URL ' ] ?? 'NOT SET ' ],
131+ ['$_ENV["APP_URL"] ' , $ _ENV ['APP_URL ' ] ?? 'NOT SET ' ],
132+ ['Current PID ' , getmypid ()],
106133 ];
107134
108135 // Display other in a nice table
109- $ this ->table (['Other ' , 'Value ' ], $ other );
136+ $ this ->infoTable (['Other ' , 'Value ' ], $ other );
137+
138+ $ checkUrls = [
139+ 'config("app.url") ' => config ('app.url ' ),
140+ 'getenv("APP_URL") ' => getenv ('APP_URL ' ),
141+ 'env("APP_URL") ' => env ('APP_URL ' ),
142+ '$_SERVER["APP_URL"] ' => $ _SERVER ['APP_URL ' ] ?? 'NOT SET ' ,
143+ '$_ENV["APP_URL"] ' => $ _ENV ['APP_URL ' ] ?? 'NOT SET ' ,
144+ ];
145+
146+ foreach ($ checkUrls as $ key => $ value ) {
147+ if ($ value !== $ currentTenant ?->config['app.url ' ]) {
148+ $ errors [] = 'Expected: ' . $ key . ' to be ' . $ currentTenant ?->config['app.url ' ] . ' but got ' . $ value ;
149+ }
150+ }
151+
152+ $ this ->finish ($ errors );
153+ }
154+
155+ private function finish ($ errors )
156+ {
157+ if (count ($ errors ) > 0 ) {
158+ $ this ->error ('Errors found ' );
159+ } else {
160+ $ this ->info ('No errors found ' );
161+ }
162+
163+ if ($ this ->option ('json ' )) {
164+ $ this ->jsonData ['Errors ' ] = $ errors ;
165+ $ this ->line (json_encode ($ this ->jsonData , JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ));
166+ }
167+ }
168+
169+ private function infoTable ($ headers , $ rows )
170+ {
171+ if ($ this ->option ('json ' )) {
172+ $ section = [];
173+ foreach ($ rows as $ row ) {
174+ $ section [$ row [0 ]] = $ row [1 ];
175+ }
176+ $ this ->jsonData [$ headers [0 ]] = $ section ;
177+ } else {
178+ foreach ($ rows as $ row ) {
179+ \Log::warning ($ row [0 ] . ': ' . $ row [1 ]);
180+ }
181+ $ this ->table ($ headers , $ rows );
182+ }
110183 }
111184}
0 commit comments