Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 27 additions & 40 deletions ProcessMaker/Http/Controllers/Admin/TenantQueueController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,12 @@

class TenantQueueController extends Controller
{
/**
* Constructor to check if tenant tracking is enabled.
*/
public function __construct()
{
// Check if tenant job tracking is enabled
$enabled = TenantQueueServiceProvider::enabled();

if (!$enabled) {
if (!app()->runningInConsole()) {
abort(404, 'Tenant queue tracking is disabled');
}
}

// If the route binding has a tenant id, check if the user is allowed to access the tenant queue
if ($id = (int) request()->route('tenantId')) {
if (!TenantQueueServiceProvider::allowAllTenats() && $id !== app('currentTenant')?->id) {
throw new AuthorizationException();
}
}
}

/**
* Show the tenant jobs dashboard.
*/
public function index()
{
if (!Auth::user()->is_administrator) {
throw new AuthorizationException();
}
$this->checkPermissions();

return view('admin.tenant-queues.index');
}
Expand All @@ -53,9 +29,7 @@ public function index()
*/
public function getTenants(): JsonResponse
{
if (!Auth::user()->is_administrator) {
throw new AuthorizationException();
}
$this->checkPermissions();

$tenantsWithJobs = TenantQueueServiceProvider::getTenantsWithJobs();

Expand Down Expand Up @@ -87,9 +61,7 @@ public function getTenants(): JsonResponse
*/
public function getTenantJobs(Request $request, string $tenantId): JsonResponse
{
if (!Auth::user()->is_administrator) {
throw new AuthorizationException();
}
$this->checkPermissions();

$status = $request->get('status');
$limit = min((int) $request->get('limit', 50), 100); // Max 100 jobs
Expand Down Expand Up @@ -125,9 +97,7 @@ public function getTenantStats(string $tenantId): JsonResponse
*/
public function getOverallStats(): JsonResponse
{
if (!Auth::user()->is_administrator) {
throw new AuthorizationException();
}
$this->checkPermissions();

$tenantsWithJobs = TenantQueueServiceProvider::getTenantsWithJobs();

Expand Down Expand Up @@ -163,9 +133,7 @@ public function getOverallStats(): JsonResponse
*/
public function getJobDetails(string $tenantId, string $jobId): JsonResponse
{
if (!Auth::user()->is_administrator) {
throw new AuthorizationException();
}
$this->checkPermissions();

$tenantKey = "tenant_jobs:{$tenantId}:{$jobId}";
$jobData = Redis::hgetall($tenantKey);
Expand Down Expand Up @@ -199,9 +167,7 @@ public function getJobDetails(string $tenantId, string $jobId): JsonResponse
*/
public function clearTenantJobs(string $tenantId): JsonResponse
{
if (!Auth::user()->is_administrator) {
throw new AuthorizationException();
}
$this->checkPermissions();

try {
$pattern = "tenant_jobs:{$tenantId}:*";
Expand All @@ -228,4 +194,25 @@ public function clearTenantJobs(string $tenantId): JsonResponse
return response()->json(['error' => 'Failed to clear tenant job data'], 500);
}
}

private function checkPermissions(): void
{
// Check if tenant job tracking is enabled
$enabled = TenantQueueServiceProvider::enabled();

if (!$enabled) {
throw new AuthorizationException('Tenant queue tracking is disabled');
}

if (!Auth::user()->is_administrator) {
throw new AuthorizationException();
}

// If the route binding has a tenant id, check if the user is allowed to access the tenant queue
if ($id = (int) request()->route('tenantId')) {
if (!TenantQueueServiceProvider::allowAllTenats() && $id !== app('currentTenant')?->id) {
throw new AuthorizationException();
}
}
}
}
7 changes: 1 addition & 6 deletions ProcessMaker/Multitenancy/SwitchTenant.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@ private function overrideConfigs(Application $app, IsTenant $tenant)
'app.instance' => config('app.instance') . '_' . $tenant->id,
];

if (!isset($tenant->config['cache.stores.cache_settings.prefix'])) {
$newConfig['cache.stores.cache_settings.prefix'] =
'tenant_id_' . $tenant->id . ':' . $tenant->getOriginalValue('CACHE_SETTING_PREFIX');
}

if (!isset($tenant->config['script-runner-microservice.callback'])) {
$newConfig['script-runner-microservice.callback'] = str_replace(
$tenant->getOriginalValue('APP_URL'),
Expand All @@ -70,7 +65,7 @@ private function overrideConfigs(Application $app, IsTenant $tenant)

if (!isset($tenant->config['app.docker_host_url'])) {
// There is no specific override in the tenant's config so set it to the app url
$newConfig['app.docker_host_url'] = config('app.docker_host_url', config('app.url'));
$newConfig['app.docker_host_url'] = config('app.url');
}

// Set config from the entry in the tenants table
Expand Down
5 changes: 4 additions & 1 deletion ProcessMaker/Multitenancy/TenantBootstrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ private function setTenantEnvironmentVariables($tenantData)
$this->set('APP_KEY', $this->decrypt($config['app.key']));
$this->set('DB_DATABASE', $tenantData['database']);
$this->set('DB_USERNAME', $tenantData['username'] ?? $this->getOriginalValue('DB_USERNAME'));
$this->set('CACHE_PREFIX', $this->getOriginalValue('CACHE_PREFIX') . 'tenant_' . $tenantData['id'] . ':');

// Do not set REDIS_PREFIX because it is used by the queue (not tenant specific)
$this->set('CACHE_PREFIX', 'tenant_' . $tenantData['id'] . ':' . $this->getOriginalValue('CACHE_PREFIX'));
$this->set('CACHE_SETTING_PREFIX', 'tenant_' . $tenantData['id'] . ':' . $this->getOriginalValue('CACHE_SETTING_PREFIX'));

$encryptedPassword = $tenantData['password'];
$password = null;
Expand Down
2 changes: 1 addition & 1 deletion ProcessMaker/Providers/TenantQueueServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ protected function updateTenantJobLists(string $tenantId, string $jobId, string
} else {
// If job is already in the list, move it to the front (most recent)
Redis::pipeline(function ($pipe) use ($listKey, $jobId) {
$pipe->lrem($listKey, 0, $jobId);
$pipe->lrem($listKey, $jobId, 0);
$pipe->lpush($listKey, $jobId);
$pipe->expire($listKey, 86400); // Expire in 24 hours
});
Expand Down
Loading