Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ devhub/pm-font/dist
test-db-snapshot.db
snapshot_*.db
storage/transitions
.envrc
6 changes: 4 additions & 2 deletions ProcessMaker/Console/Commands/CreateDataLakeViews.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,10 @@ protected function getTableColumns(string $tableName): array
*/
protected function getTables(): array
{
$database = \DB::connection()->getDatabaseName();
$tables = array_map(function ($item) {
return $item['name'];
}, Schema::getTables());
}, Schema::getTables($database));

return $tables;
}
Expand All @@ -193,9 +194,10 @@ protected function getTables(): array
*/
protected function getViews(): array
{
$database = \DB::connection()->getDatabaseName();
$views = array_map(function ($item) {
return $item['name'];
}, Schema::getViews());
}, Schema::getViews($database));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getViews returns incompatible data structure breaking view logic

High Severity

The getViews() method now returns a numerically-indexed array of view name strings, but consumers expect an associative array keyed by view name with objects having a getSql() method. In shouldCreate(), the check isset($views[$viewName]) will always fail since the array uses numeric keys, causing views to always be recreated unnecessarily. In the up() method's foreach loop, $viewName becomes numeric indices (0, 1, 2...) instead of actual view names, breaking the dropped table detection logic entirely.

Additional Locations (2)

Fix in Cursor Fix in Web


return $views;
}
Expand Down
98 changes: 46 additions & 52 deletions ProcessMaker/Http/Controllers/Auth/ClientController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,39 @@
namespace ProcessMaker\Http\Controllers\Auth;

use Illuminate\Http\Request;
use Laravel\Passport\Http\Controllers\ClientController as PassportClientController;
use Illuminate\Http\Response;
use Laravel\Passport\ClientRepository;
use ProcessMaker\Events\AuthClientCreated;
use ProcessMaker\Events\AuthClientDeleted;
use ProcessMaker\Events\AuthClientUpdated;
use ProcessMaker\Http\Resources\AuthClient as AuthClientResource;

class ClientController extends PassportClientController
class ClientController
{
/**
* List auth clients
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function __construct(
protected ClientRepository $clients,
protected \Illuminate\Contracts\Validation\Factory $validation,
) {
}

public function index(Request $request)
{
$clients = \Laravel\Passport\Client::where('revoked', false)->get();

return AuthClientResource::collection($clients);
}

/**
* Get an individual auth client
*
* @param \Illuminate\Http\Request $request
* @param string $clientId
* @return array
*/
public function show(Request $request, $clientId)
{
// $client = $this->clients->find($clientId);
$client = parent::show($request, $clientId);
$client = $this->clients->findForUser($clientId, $request->user());

if (!$client) {
return new Response('', 404);
}

return new AuthClientResource($client);
}

/**
* Store a new client.
*
* @param \Illuminate\Http\Request $request
* @return \Laravel\Passport\Client
*/
public function store(Request $request)
{
$this->validate($request);
Expand All @@ -53,36 +44,44 @@ public function store(Request $request)
$password = in_array('password_client', $request->types);
$redirect = in_array('authorization_code_grant', $request->types) ? $request->redirect : '';

$client = $this->clients->create(
$request->user()->getKey(),
$request->name,
$redirect,
null,
$personalAccess,
$password
)->makeVisible('secret');
// Use ClientRepository methods based on type
if ($personalAccess) {
$client = $this->clients->createPersonalAccessClient(
$request->user()->getKey(),
$request->name,
$redirect
);
} elseif ($password) {
$client = $this->clients->createPasswordGrantClient(
$request->user()->getKey(),
$request->name,
$redirect
);
} else {
// Authorization code grant
$client = $this->clients->createAuthorizationCodeGrantClient(
$request->name,
$redirect ? explode(',', $redirect) : [],
true, // confidential
$request->user()
);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Store method silently ignores multiple selected client types

Medium Severity

The store() method uses an if-elseif-else structure that only creates one client type, silently ignoring additional types when multiple are selected. The validation allows multiple types (array|min:1), and the update() method correctly handles both personal_access_client and password_client flags independently. However, store() only honors the first matching type—if both personal access and password are requested, only the personal access client is created. This creates an inconsistency where capabilities available via update are not available during creation.

Fix in Cursor Fix in Web


$client->makeVisible('secret');
AuthClientCreated::dispatch($client->getAttributes());

return new AuthClientResource($client);
}

/**
* Update the given client.
*
* @param \Illuminate\Http\Request $request
* @param string $clientId
* @return \Illuminate\Http\Response|\Laravel\Passport\Client
*/
public function update(Request $request, $clientId)
{
$client = $this->clients->find($clientId);
$client = $this->clients->findForUser($clientId, $request->user());

if (!$client) {
return new Response('', 404);
}

$original_values = $client->getAttributes();

$originalValues = $client->getAttributes();
$this->validate($request);

$personalAccess = in_array('personal_access_client', $request->types);
Expand All @@ -97,33 +96,26 @@ public function update(Request $request, $clientId)
]);

$original = array_intersect_key($client->getOriginal(), $client->getDirty());

$client->save();

AuthClientUpdated::dispatch($clientId, $original, $client->getChanges(), $request->name);

return new AuthClientResource($client);
}

/**
* Delete the given client.
*
* @param \Illuminate\Http\Request $request
* @param string $clientId
* @return null
*/
public function destroy(Request $request, $clientId)
{
$client = $this->clients->find($clientId);
$client = $this->clients->findForUser($clientId, $request->user());

if (!$client) {
return new Response('', 404);
}

$attributes = $client->getAttributes();
$this->clients->delete($client);
AuthClientDeleted::dispatch($client->getAttributes());
AuthClientDeleted::dispatch($attributes);

return response('', 204);
return new Response('', 204);
}

private function validate($request)
Expand All @@ -133,9 +125,11 @@ private function validate($request)
'types' => 'array|min:1|required',
'types.*' => 'in:authorization_code_grant,password_client,personal_access_client',
];

if (is_array($request->types) && in_array('authorization_code_grant', $request->types)) {
$rules['redirect'] = 'required|url|max:2000';
}

$this->validation->make($request->all(), $rules, [
'min' => __('The Auth-Client must have at least :min item chosen.'),
])->validate();
Expand Down
4 changes: 2 additions & 2 deletions ProcessMaker/Http/Middleware/AuthenticateSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class AuthenticateSession extends BaseAuthenticateSession
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param Closure $next
*
* @return mixed
* @throws \Illuminate\Auth\AuthenticationException
Expand Down Expand Up @@ -42,7 +42,7 @@ public function handle($request, Closure $next)
$this->storePasswordHashInSession($request);
}

if ($request->session()->get('password_hash_' . $this->auth->getDefaultDriver()) !== $request->user()->getAuthPassword()) {
if ($request->session()->get('password_hash_' . $this->auth->getDefaultDriver()) !== $this->guard()->hashPasswordForCookie($request->user()->getAuthPassword())) {
$this->logout($request);
}

Expand Down
2 changes: 1 addition & 1 deletion ProcessMaker/Jobs/BuildScriptExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class BuildScriptExecutor implements ShouldQueue
protected $userId;

// Do not retry this job if it fails
public $tries = 10;
public $tries = 1;

// Building can take some time
public $timeout = 600;
Expand Down
4 changes: 4 additions & 0 deletions ProcessMaker/Providers/AuthServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public function boot()
{
$this->registerPolicies();

// Explicitly disable client UUIDs to match the database schema (integer id)
// In newer versions of Passport, UUIDs are enabled by default
Passport::$clientUuids = false;

Passport::enablePasswordGrant();

Passport::authorizationView('auth.oauth2.authorize');
Expand Down
4 changes: 2 additions & 2 deletions ProcessMaker/Traits/ExtendedPMQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function useDataStoreTable(Builder $query, string $table, array $map)
*
* @return mixed
*/
public function scopePMQL(Builder $builder, string $query, callable $callback = null, User $user = null)
public function scopePMQL(Builder $builder, string $query, ?callable $callback = null, ?User $user = null)
{
if (!$callback) {
// If a callback isn't passed to the scope, we handle it here
Expand Down Expand Up @@ -97,7 +97,7 @@ private static function getFromExpression($values, $fields)
*
* @return mixed
*/
private function handle(Expression $expression, Builder $builder, User $user = null)
private function handle(Expression $expression, Builder $builder, ?User $user = null)
{
// Setup our needed variables
$field = $expression->field->field();
Expand Down
24 changes: 12 additions & 12 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,34 @@
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": "^8.3",
"php": "^8.4",
"babenkoivan/elastic-scout-driver": "^4.0",
"bacon/bacon-qr-code": "^2.0",
"codegreencreative/laravel-samlidp": "^5.2",
"composer/semver": "^3.4",
"darkaonline/l5-swagger": "^8.6",
"darkaonline/l5-swagger": "^9.0.1",
"doctrine/dbal": "^4.2",
"fakerphp/faker": "^1.24",
"google/apiclient": "^2.18",
"guzzlehttp/guzzle": "^7.9",
"igaster/laravel-theme": "^2.0",
"jenssegers/agent": "^2.6",
"laravel/framework": "^11.44.1",
"laravel/framework": "^12.47",
"laravel/horizon": "^5.30",
"laravel/pail": "^1.2",
"laravel/passport": "^12.3",
"laravel/passport": "^13.4",
"laravel/scout": "^10.11",
"laravel/telescope": "^5.2",
"laravel/tinker": "^2.10",
"laravel/ui": "^4.6",
"lavary/laravel-menu": "^1.8",
"lcobucci/jwt": "^4.2",
"lcobucci/jwt": "^5.6",
"league/commonmark": "^2.7",
"mateusjunges/laravel-kafka": "^2.4",
"mateusjunges/laravel-kafka": "^2.10",
"mittwald/vault-php": "^2.1",
"mustache/mustache": "^2.14",
"openai-php/client": "^0.10.3",
"openai-php/laravel": "^0.10.2",
"openai-php/client": "^0.18.0",
"openai-php/laravel": "^0.18.0",
"paragonie/sodium_compat": "^2.5",
"php-amqplib/php-amqplib": "^3.7",
"php-http/promise": "~1.2.0",
Expand All @@ -48,9 +48,9 @@
"processmaker/docker-executor-php": "1.4.0",
"processmaker/laravel-i18next": "dev-master",
"processmaker/nayra": "1.12.4",
"processmaker/pmql": "1.13.1",
"processmaker/pmql": "1.13.2",
"promphp/prometheus_client_php": "^2.12",
"psr/http-message": "^1.1",
"psr/http-message": "^2.0",
"psr/log": "^3.0",
"psr/simple-cache": "^3.0",
"pusher/pusher-php-server": "^7.2",
Expand All @@ -64,7 +64,7 @@
"spomky-labs/otphp": "^11.3",
"symfony/expression-language": "^7.2",
"symfony/http-foundation": "^7.3",
"teamtnt/laravel-scout-tntsearch-driver": "^14.0",
"teamtnt/laravel-scout-tntsearch-driver": "^15.0",
"twilio/sdk": "^8.3",
"typo3/class-alias-loader": "^1.2",
"whichbrowser/parser": "^2.1"
Expand Down Expand Up @@ -230,4 +230,4 @@
"tbachert/spi": true
}
}
}
}
Loading
Loading