diff --git a/ProcessMaker/Enums/ScriptExecutorType.php b/ProcessMaker/Enums/ScriptExecutorType.php
new file mode 100644
index 0000000000..c59fe1e168
--- /dev/null
+++ b/ProcessMaker/Enums/ScriptExecutorType.php
@@ -0,0 +1,9 @@
+cacheResponse($this->response);
+ $response = $this->cacheResponse();
return [
'type' => '.' . \get_class($this),
diff --git a/ProcessMaker/Http/Controllers/Api/ScriptController.php b/ProcessMaker/Http/Controllers/Api/ScriptController.php
index 7580b33bff..2e7fc5c5dc 100644
--- a/ProcessMaker/Http/Controllers/Api/ScriptController.php
+++ b/ProcessMaker/Http/Controllers/Api/ScriptController.php
@@ -18,6 +18,7 @@
use ProcessMaker\Models\ScriptCategory;
use ProcessMaker\Models\User;
use ProcessMaker\Query\SyntaxError;
+use ProcessMaker\Services\ScriptMicroserviceService;
use ProcessMaker\Traits\ProjectAssetTrait;
class ScriptController extends Controller
@@ -286,6 +287,12 @@ public function execution($key)
return response()->json(Cache::get("srn.{$key}"));
}
+ public function microserviceExecution(Request $request)
+ {
+ $scriptMicroserviceService = new ScriptMicroserviceService();
+ $scriptMicroserviceService->handle($request);
+ }
+
/**
* Get a single script in a process.
*
diff --git a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php
index e625ac01d8..118e1301e7 100644
--- a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php
+++ b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php
@@ -103,6 +103,7 @@ public function index(Request $request)
*/
public function store(Request $request)
{
+ $request->request->add(['type' => 'custom']);
$this->checkAuth($request);
$request->validate(ScriptExecutor::rules());
diff --git a/ProcessMaker/Jobs/RunScriptTask.php b/ProcessMaker/Jobs/RunScriptTask.php
index 1d4c7a632c..5558c23fa5 100644
--- a/ProcessMaker/Jobs/RunScriptTask.php
+++ b/ProcessMaker/Jobs/RunScriptTask.php
@@ -5,6 +5,7 @@
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Log;
+use ProcessMaker\Enums\ScriptExecutorType;
use ProcessMaker\Exception\ConfigurationException;
use ProcessMaker\Exception\ScriptException;
use ProcessMaker\Facades\WorkflowManager;
@@ -32,9 +33,9 @@ class RunScriptTask extends BpmnAction implements ShouldQueue
/**
* Create a new job instance.
*
- * @param \ProcessMaker\Models\Process $definitions
- * @param \ProcessMaker\Models\ProcessRequest $instance
- * @param \ProcessMaker\Models\ProcessRequestToken $token
+ * @param Definitions $definitions
+ * @param ProcessRequest $instance
+ * @param ProcessRequestToken $token
* @param array $data
*/
public function __construct(Definitions $definitions, ProcessRequest $instance, ProcessRequestToken $token, array $data, $attemptNum = 1)
@@ -68,6 +69,7 @@ public function action(ProcessRequestToken $token = null, ScriptTaskInterface $e
}
$errorHandling = null;
+ $scriptExecutor = null;
try {
if (empty($scriptRef)) {
$code = $element->getScript();
@@ -86,6 +88,7 @@ public function action(ProcessRequestToken $token = null, ScriptTaskInterface $e
if (!$script) {
throw new ConfigurationException(__('Script ":id" not found', ['id' => $scriptRef]));
}
+ $scriptExecutor = $script->scriptExecutor;
$script = $script->versionFor($instance);
}
@@ -95,9 +98,22 @@ public function action(ProcessRequestToken $token = null, ScriptTaskInterface $e
$this->unlock();
$dataManager = new DataManager();
$data = $dataManager->getData($token);
- $response = $script->runScript($data, $configuration, $token->getId(), $errorHandling->timeout());
-
- $this->updateData($response);
+ $metadata = [
+ 'script_task' => [
+ 'script_id' => $scriptRef,
+ 'definition_id' => $this->definitionsId,
+ 'instance_id' => $this->instanceId,
+ 'token_id' => $this->tokenId,
+ 'data' => $data,
+ 'attempts' => $this->attemptNum,
+ ],
+ ];
+ $response = $script->runScript($data, $configuration, $token->getId(), $errorHandling->timeout(), 0, $metadata);
+
+ if (!config('script-runner-microservice.enabled') ||
+ ($scriptExecutor && $scriptExecutor->type === ScriptExecutorType::Custom)) {
+ $this->updateData($response);
+ }
} catch (ConfigurationException $exception) {
$this->unlock();
$this->updateData(['output' => $exception->getMessageForData($token)]);
diff --git a/ProcessMaker/Jobs/TestScript.php b/ProcessMaker/Jobs/TestScript.php
index 0e9b2b3fe9..23c56de091 100644
--- a/ProcessMaker/Jobs/TestScript.php
+++ b/ProcessMaker/Jobs/TestScript.php
@@ -7,6 +7,7 @@
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
+use ProcessMaker\Enums\ScriptExecutorType;
use ProcessMaker\Events\ScriptResponseEvent;
use ProcessMaker\Models\Script;
use ProcessMaker\Models\User;
@@ -60,8 +61,17 @@ public function handle()
try {
// Just set the code but do not save the object (preview only)
$this->script->code = $this->code;
- $response = $this->script->runScript($this->data, $this->configuration);
- $this->sendResponse(200, $response);
+ $metadata = [
+ 'nonce' => $this->nonce,
+ 'current_user' => $this->current_user?->id,
+ ];
+ $response = $this->script->runScript($this->data, $this->configuration, '', null, 0, $metadata);
+ \Log::debug('Response api microservice: ' . print_r($response, true));
+
+ if (!config('script-runner-microservice.enabled') ||
+ $this->script->scriptExecutor && $this->script->scriptExecutor->type === ScriptExecutorType::Custom) {
+ $this->sendResponse(200, $response);
+ }
} catch (Throwable $exception) {
$this->sendResponse(500, [
'exception' => get_class($exception),
diff --git a/ProcessMaker/Models/Script.php b/ProcessMaker/Models/Script.php
index 8b900db30e..31c71ddaae 100644
--- a/ProcessMaker/Models/Script.php
+++ b/ProcessMaker/Models/Script.php
@@ -149,7 +149,7 @@ public static function rules($existing = null)
* @param array $data
* @param array $config
*/
- public function runScript(array $data, array $config, $tokenId = '', $timeout = null)
+ public function runScript(array $data, array $config, $tokenId = '', $timeout = null, $sync = 1, $metadata = [])
{
if (!$timeout) {
$timeout = $this->timeout;
@@ -158,14 +158,14 @@ public function runScript(array $data, array $config, $tokenId = '', $timeout =
if (!$this->scriptExecutor) {
throw new ScriptLanguageNotSupported($this->language);
}
- $runner = new ScriptRunner($this->scriptExecutor);
+ $runner = new ScriptRunner($this);
$runner->setTokenId($tokenId);
$user = User::find($this->run_as_user_id);
if (!$user) {
throw new ConfigurationException('A user is required to run scripts');
}
- return $runner->run($this->code, $data, $config, $timeout, $user);
+ return $runner->run($this->code, $data, $config, $timeout, $user, $sync, $metadata);
}
/**
diff --git a/ProcessMaker/Models/ScriptExecutor.php b/ProcessMaker/Models/ScriptExecutor.php
index f5d8b34346..64ad0cee7f 100644
--- a/ProcessMaker/Models/ScriptExecutor.php
+++ b/ProcessMaker/Models/ScriptExecutor.php
@@ -4,6 +4,8 @@
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Validation\Rule;
+use Illuminate\Validation\Rules\Enum;
+use ProcessMaker\Enums\ScriptExecutorType;
use ProcessMaker\Exception\ScriptLanguageNotSupported;
use ProcessMaker\Facades\Docker;
use ProcessMaker\Traits\Exportable;
@@ -56,7 +58,7 @@ class ScriptExecutor extends ProcessMakerModel
use HideSystemResources;
protected $fillable = [
- 'title', 'description', 'language', 'config', 'is_system',
+ 'title', 'description', 'language', 'config', 'is_system', 'type',
];
public static function install($params)
@@ -146,6 +148,11 @@ public static function rules($existing = null)
'required',
Rule::in(Script::scriptFormatValues()),
],
+ 'type' => [
+ 'sometimes',
+ new Enum(ScriptExecutorType::class),
+ 'nullable',
+ ],
];
}
diff --git a/ProcessMaker/Models/ScriptExecutorVersion.php b/ProcessMaker/Models/ScriptExecutorVersion.php
index e3ae78b721..076952bb6e 100644
--- a/ProcessMaker/Models/ScriptExecutorVersion.php
+++ b/ProcessMaker/Models/ScriptExecutorVersion.php
@@ -7,7 +7,7 @@
class ScriptExecutorVersion extends ProcessMakerModel
{
protected $fillable = [
- 'title', 'description', 'language', 'config', 'draft', 'is_system',
+ 'title', 'description', 'language', 'config', 'draft', 'is_system', 'type',
];
/**
diff --git a/ProcessMaker/Models/ScriptVersion.php b/ProcessMaker/Models/ScriptVersion.php
index d1c946b24c..d6b8e9e838 100644
--- a/ProcessMaker/Models/ScriptVersion.php
+++ b/ProcessMaker/Models/ScriptVersion.php
@@ -50,7 +50,7 @@ public function parent()
* @param array $data
* @param array $config
*/
- public function runScript(array $data, array $config, $tokenId = '', $timeout = null)
+ public function runScript(array $data, array $config, $tokenId = '', $timeout = null, $sync = 1, $metadata = [])
{
$script = $this->parent->replicate();
$except = $script->getGuarded();
@@ -58,7 +58,7 @@ public function runScript(array $data, array $config, $tokenId = '', $timeout =
$script->$prop = $this->$prop;
}
- return $script->runScript($data, $config, $tokenId, $timeout);
+ return $script->runScript($data, $config, $tokenId, $timeout, $sync, $metadata);
}
/**
diff --git a/ProcessMaker/ScriptRunners/Base.php b/ProcessMaker/ScriptRunners/Base.php
index 0db1bb0511..c609f3a0d6 100644
--- a/ProcessMaker/ScriptRunners/Base.php
+++ b/ProcessMaker/ScriptRunners/Base.php
@@ -65,7 +65,7 @@ public function __construct(ScriptExecutor $scriptExecutor)
* @return array
* @throws RuntimeException
*/
- public function run($code, array $data, array $config, $timeout, ?User $user)
+ public function run($code, array $data, array $config, $timeout, ?User $user, $sync, $metadata)
{
$isNayra = $this->scriptExecutor->language === self::NAYRA_LANG;
diff --git a/ProcessMaker/ScriptRunners/ScriptMicroserviceRunner.php b/ProcessMaker/ScriptRunners/ScriptMicroserviceRunner.php
new file mode 100644
index 0000000000..26b3caa32f
--- /dev/null
+++ b/ProcessMaker/ScriptRunners/ScriptMicroserviceRunner.php
@@ -0,0 +1,167 @@
+language = strtolower($script->language ?? $script->scriptExecutor->language);
+ }
+
+ public function getAccessToken()
+ {
+ if (Cache::has('keycloak.access_token')) {
+ return Cache::get('keycloak.access_token');
+ }
+
+ $response = Http::asForm()->post(config('script-runner-microservice.keycloak.base_url'), [
+ 'grant_type' => 'password',
+ 'client_id' => config('script-runner-microservice.keycloak.client_id'),
+ 'client_secret' => config('script-runner-microservice.keycloak.client_secret'),
+ 'username' => config('script-runner-microservice.keycloak.username'),
+ 'password' => config('script-runner-microservice.keycloak.password'),
+ ]);
+
+ if ($response->successful()) {
+ Cache::put('keycloak.access_token', $response->json()['access_token'], $response->json()['expires_in'] - 60);
+ }
+
+ return Cache::get('keycloak.access_token');
+ }
+
+ public function getScriptRunner()
+ {
+ $response = Cache::remember('script-runner-microservice.script-languages', now()->addDay(), function () {
+ return Http::withToken($this->getAccessToken())
+ ->get(config('script-runner-microservice.base_url') . '/scripts')->collect();
+ });
+
+ return $response->filter(function ($item) {
+ return $item['language'] == $this->language;
+ })->first();
+ }
+
+ public function run($code, array $data, array $config, $timeout, $user, $sync, $metadata)
+ {
+ Log::debug('Language: ' . $this->language);
+ Log::debug('Sync: ' . $sync);
+ Log::debug('Metadata: ' . print_r($metadata, true));
+
+ $scriptRunner = $this->getScriptRunner();
+
+ if (!$scriptRunner) {
+ throw new ConfigurationException('No exists script executor for this language: ' . $this->language);
+ }
+ $metadata = array_merge($this->getMetadata($user), $metadata);
+ $environmentVariables = $this->getEnvironmentVariables($user);
+
+ $payload = [
+ 'version' => config('script-runner-microservice.version') ?? $this->getProcessMakerVersion(),
+ 'language' => $scriptRunner['language'],
+ 'metadata'=> $metadata,
+ 'data' => !empty($data) ? $this->sanitizeCss($data) : new stdClass(),
+ 'config' => !empty($config) ? $config : new stdClass(),
+ 'script' => base64_encode(str_replace("'", ''', $code)),
+ 'secrets' => $environmentVariables,
+ 'callback' => config('script-runner-microservice.callback'),
+ 'callback_secure' => true,
+ 'callback_token' => $environmentVariables['API_TOKEN'],
+ 'debug' => true,
+ 'timeout' => $timeout,
+ 'sync' => $sync,
+ ];
+
+ Log::debug('Payload: ' . print_r($payload, true));
+
+ $response = Http::withToken($this->getAccessToken())
+ ->post(config('script-runner-microservice.base_url') . '/requests/create', $payload);
+
+ $response->throw();
+
+ return $response->json();
+ }
+
+ private function getEnvironmentVariables(User $user)
+ {
+ $variablesParameter = [];
+ EnvironmentVariable::chunk(50, function (Collection $variables) use (&$variablesParameter) {
+ foreach ($variables as $variable) {
+ // Fix variables that have spaces
+ $variablesParameter[str_replace(' ', '_', $variable->name)] = $variable->value;
+ }
+ });
+
+ // Add the url to the host
+ $variablesParameter['HOST_URL'] = config('app.docker_host_url');
+
+ // Create tokens for the SDK if a user is set
+ $token = null;
+ if ($user) {
+ $accessToken = Cache::remember('script-runner-' . $user->id, now()->addWeek(), function () use ($user) {
+ $user->removeOldRunScriptTokens();
+ $token = new GenerateAccessToken($user);
+
+ return $token->getToken();
+ });
+ $variablesParameter['API_TOKEN'] = $accessToken;
+ $variablesParameter['API_HOST'] = config('app.docker_host_url') . '/api/1.0';
+ $variablesParameter['APP_URL'] = config('app.docker_host_url');
+ $variablesParameter['API_SSL_VERIFY'] = (config('app.api_ssl_verify') ? '1' : '0');
+ }
+
+ return $variablesParameter;
+ }
+
+ public function setTokenId($tokenId)
+ {
+ $this->tokenId = $tokenId;
+ }
+
+ public function getProcessMakerVersion()
+ {
+ return Cache::remember('script-runner-microservice.processmaker-version', now()->addDay(), function () {
+ $composer_json_path = json_decode(file_get_contents(base_path() . '/composer.json'));
+
+ return $composer_json_path->version;
+ });
+ }
+
+ public function getMetadata($user)
+ {
+ return [
+ 'script_id' => $this->script->id,
+ 'instance' => config('app.url'),
+ 'user_id' => $user->id,
+ 'user_email' => $user->email,
+ ];
+ }
+
+ public function sanitizeCss($data)
+ {
+ if ($this->language !== 'javascript-ssr') {
+ return $data;
+ }
+ if (array_key_exists('css', $data)) {
+ $data['css'] = false;
+ }
+
+ return $data;
+ }
+}
diff --git a/ProcessMaker/ScriptRunners/ScriptRunner.php b/ProcessMaker/ScriptRunners/ScriptRunner.php
index 97b4ae878d..e40795192c 100644
--- a/ProcessMaker/ScriptRunners/ScriptRunner.php
+++ b/ProcessMaker/ScriptRunners/ScriptRunner.php
@@ -2,7 +2,10 @@
namespace ProcessMaker\ScriptRunners;
+use Illuminate\Contracts\Container\BindingResolutionException;
+use ProcessMaker\Enums\ScriptExecutorType;
use ProcessMaker\Exception\ScriptLanguageNotSupported;
+use ProcessMaker\Models\Script;
use ProcessMaker\Models\ScriptExecutor;
class ScriptRunner
@@ -10,13 +13,13 @@ class ScriptRunner
/**
* Concrete script runner
*
- * @var \ProcessMaker\ScriptRunners\Base
+ * @var Base
*/
private $runner;
- public function __construct(ScriptExecutor $executor)
+ public function __construct(protected Script $script)
{
- $this->runner = $this->getScriptRunner($executor);
+ $this->runner = $this->getScriptRunner($this->script->scriptExecutor);
}
/**
@@ -31,9 +34,9 @@ public function __construct(ScriptExecutor $executor)
* @return array
* @throws \RuntimeException
*/
- public function run($code, array $data, array $config, $timeout, $user)
+ public function run($code, array $data, array $config, $timeout, $user, $sync, $metadata)
{
- return $this->runner->run($code, $data, $config, $timeout, $user);
+ return $this->runner->run($code, $data, $config, $timeout, $user, $sync, $metadata);
}
/**
@@ -41,19 +44,24 @@ public function run($code, array $data, array $config, $timeout, $user)
*
* @param ScriptExecutor $executor
*
- * @return \ProcessMaker\ScriptRunners\Base
- * @throws \ProcessMaker\Exception\ScriptLanguageNotSupported
+ * @return Base|ScriptMicroserviceRunner|MockRunner
+ * @throws ScriptLanguageNotSupported
+ * @throws BindingResolutionException
*/
- private function getScriptRunner(ScriptExecutor $executor)
+ private function getScriptRunner(ScriptExecutor $executor): Base|ScriptMicroserviceRunner|MockRunner
{
- $language = strtolower($executor->language);
- $runner = config("script-runners.{$language}.runner");
- if (!$runner) {
- throw new ScriptLanguageNotSupported($language);
- } else {
- $class = "ProcessMaker\\ScriptRunners\\{$runner}";
+ if (!config('script-runner-microservice.enabled') || $executor->type === ScriptExecutorType::Custom) {
+ $language = strtolower($executor->language);
+ $runner = config("script-runners.{$language}.runner");
+ if (!$runner) {
+ throw new ScriptLanguageNotSupported($language);
+ } else {
+ $class = "ProcessMaker\\ScriptRunners\\{$runner}";
- return app()->make($class, ['scriptExecutor' => $executor]);
+ return app()->make($class, ['scriptExecutor' => $executor]);
+ }
+ } else {
+ return new ScriptMicroserviceRunner($this->script);
}
}
diff --git a/ProcessMaker/Services/ScriptMicroserviceService.php b/ProcessMaker/Services/ScriptMicroserviceService.php
new file mode 100644
index 0000000000..0cb7328bd0
--- /dev/null
+++ b/ProcessMaker/Services/ScriptMicroserviceService.php
@@ -0,0 +1,45 @@
+all();
+ Log::debug('Response microservice executor: ' . print_r($response, true));
+ // If the call is from preview
+ if ($response['metadata']['nonce']) {
+ $status = $response['status'] === 'success' ? 200 : 500;
+ $output = $response['status'] === 'success'
+ ? ['output' => $response['output']]
+ : $response;
+
+ event(new ScriptResponseEvent(
+ User::find($response['metadata']['current_user']),
+ $status,
+ $output,
+ null,
+ $response['metadata']['nonce']));
+ }
+ if (!empty($response['metadata']['script_task'])) {
+ $script = Script::find($response['metadata']['script_task']['script_id']);
+ $definitions = Definitions::find($response['metadata']['script_task']['definition_id']);
+ $instance = ProcessRequest::find($response['metadata']['script_task']['instance_id']);
+ $token = ProcessRequestToken::find($response['metadata']['script_task']['token_id']);
+ if ($response['status'] === 'success') {
+ CompleteActivity::dispatch($definitions, $instance, $token, $response['output'])->onQueue('bpmn');
+ }
+ }
+ }
+}
diff --git a/config/script-runner-microservice.php b/config/script-runner-microservice.php
new file mode 100644
index 0000000000..570a73ace2
--- /dev/null
+++ b/config/script-runner-microservice.php
@@ -0,0 +1,16 @@
+ env('SCRIPT_MICROSERVICE_ENABLED', true),
+ 'base_url' => env('SCRIPT_MICROSERVICE_BASE_URL'),
+ 'callback' => env('SCRIPT_MICROSERVICE_CALLBACK'),
+ 'version' => env('SCRIPT_MICROSERVICE_VERSION'),
+ 'keycloak' => [
+ 'client_id' => env('KEYCLOAK_CLIENT_ID'),
+ 'client_secret' => env('KEYCLOAK_CLIENT_SECRET'),
+ 'redirect' => env('KEYCLOAK_REDIRECT_URI'),
+ 'base_url' => env('KEYCLOAK_BASE_URL'),
+ 'username' => env('KEYCLOAK_USERNAME'),
+ 'password' => env('KEYCLOAK_PASSWORD'),
+ ],
+];
diff --git a/database/migrations/2024_10_15_182703_add_type_column_to_script_executor_versions_table.php b/database/migrations/2024_10_15_182703_add_type_column_to_script_executor_versions_table.php
new file mode 100644
index 0000000000..8654582762
--- /dev/null
+++ b/database/migrations/2024_10_15_182703_add_type_column_to_script_executor_versions_table.php
@@ -0,0 +1,27 @@
+string('type')->nullable()->after('config');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('script_executor_versions', function (Blueprint $table) {
+ $table->dropColumn('type');
+ });
+ }
+};
diff --git a/database/migrations/2024_10_15_182703_add_type_column_to_script_executors_table.php b/database/migrations/2024_10_15_182703_add_type_column_to_script_executors_table.php
new file mode 100644
index 0000000000..37ec329a7d
--- /dev/null
+++ b/database/migrations/2024_10_15_182703_add_type_column_to_script_executors_table.php
@@ -0,0 +1,27 @@
+string('type')->nullable()->after('is_system');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('script_executors', function (Blueprint $table) {
+ $table->dropColumn('type');
+ });
+ }
+};
diff --git a/phpunit.xml b/phpunit.xml
index 231376cc93..fade58e673 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -76,5 +76,8 @@
+
+
+
diff --git a/routes/api.php b/routes/api.php
index 4bc4f33a5f..56151c5420 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -128,6 +128,7 @@
Route::post('scripts/{script}/preview', [ScriptController::class, 'preview'])->name('scripts.preview')->middleware('can:view-scripts,script');
Route::post('scripts/execute/{script_id}/{script_key?}', [ScriptController::class, 'execute'])->name('scripts.execute');
Route::get('scripts/execution/{key}', [ScriptController::class, 'execution'])->name('scripts.execution');
+ Route::post('scripts/microservice/execution', [ScriptController::class, 'microserviceExecution']);
// Script Categories
Route::get('script_categories', [ScriptCategoryController::class, 'index'])->name('script_categories.index')->middleware('can:view-script-categories');
diff --git a/tests/Feature/Api/ScriptsTest.php b/tests/Feature/Api/ScriptsTest.php
index e14f14a78e..bb76dad7db 100644
--- a/tests/Feature/Api/ScriptsTest.php
+++ b/tests/Feature/Api/ScriptsTest.php
@@ -379,16 +379,6 @@ public function testPreviewScript()
ScriptResponseEvent::class,
]);
- $url = route('api.scripts.preview', $this->getScript('lua')->id);
- $response = $this->apiCall('POST', $url, ['data' => '{}', 'code' => 'return {response=1}']);
- $response->assertStatus(200);
- Event::assertDispatched(ScriptResponseEvent::class, function ($event) {
- $response = $event->response;
- $nonce = $event->nonce;
-
- return $response['output'] === ['response' => 1];
- });
-
$url = route('api.scripts.preview', $this->getScript('php')->id);
$response = $this->apiCall('POST', $url, [
'data' => '{}',