/** * @test * @functional */ public function testGetVersions() { $list = Script::find(null, null, null, 10); $this->assertInternalType('array', $list->getArrayCopy()); $this->assertInternalType('integer', count($list)); $this->assertInternalType('integer', $list->count()); try { /* @var $script Script */ $script = Script::findOne([]); } catch (\Exception $e) { $this->markTestSkipped($e->getMessage()); } if (!$script) { $this->markTestSkipped("There are no scripts so it can not proceed"); } $versions = $script->getVersions()->getArrayCopy(); $this->assertInternalType('array', $versions); }
/** * @test * * @throws \Scalr\Exception\ModelException */ public function testComplex() { $user = $this->getUser(); $environment = $this->getEnvironment(); $fictionController = new ApiController(); //test script post $data = ['name' => 'test-post', 'description' => 'test-post', 'timeoutDefault' => 1000, 'blockingDefault' => true, 'osType' => 'linux']; $response = $this->postScript($data); $this->assertEquals(201, $response->status, $this->printResponseError($response)); $scriptId = $response->getBody()->data->id; /* @var $script Script */ $script = Script::findPk($scriptId); $this->assertNotEmpty($script); $this->scriptToDelete($scriptId); $this->assertObjectEqualsEntity($data, $script); //post environment-scoped script $data['scope'] = ScopeInterface::SCOPE_ENVIRONMENT; $response = $this->postScript($data); $this->assertEquals(201, $response->status, $this->printResponseError($response)); $scriptId = $response->getBody()->data->id; $script = Script::findPk($scriptId); $this->assertNotEmpty($script); $this->scriptToDelete($scriptId); $this->assertObjectEqualsEntity($data, $script); //post script already existing $data = ['id' => $script->id, 'name' => 'test-post-existing', 'description' => 'test-post-existing', 'osType' => 'linux', 'scope' => ScopeInterface::SCOPE_ENVIRONMENT]; $response = $this->postScript($data); $this->assertEquals(201, $response->status, $this->printResponseError($response)); $scriptId = $response->getBody()->data->id; $this->scriptToDelete($scriptId); $this->assertNotEquals($data['id'], $scriptId); unset($data['id']); $scriptData = $data; $scriptData['accountId'] = $user->getAccountId(); $scriptData['envId'] = $environment->id; $scriptData['os'] = $data['osType']; unset($scriptData['osType'], $scriptData['scope']); $envScript = $this->createEntity(new Script(), $scriptData); //post script with name already exists in current (environment) scope $data['name'] = 'test-post-existing'; $response = $this->postScript($data); $this->assertErrorMessageContains($response, 409, ErrorMessage::ERR_UNICITY_VIOLATION); $envScript->delete(); //post script with properties that not existing $data = ['name' => 'test-post-not-existing-field', 'description' => 'test-post-not-existing-field', 'foo' => 'bar', 'osType' => 'linux']; $response = $this->postScript($data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //post script without required fields $data = ['name' => 'foobar', 'description' => 'test-post-no-scope']; $response = $this->postScript($data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //test script fetch $response = $this->getScript($script->id); $this->assertEquals(200, $response->status, $this->printResponseError($response)); $this->assertObjectEqualsEntity($response->getBody()->data, $script); //test fetch script that doe not exists $response = $this->getScript(Script::findOne([], null, ['id' => false])->id + 1); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); //test script modify $data = ['name' => 'test-modify', 'description' => 'test-modify', 'timeoutDefault' => 0, 'blockingDefault' => false]; $response = $this->modifyScript($script->id, $data); $this->assertEquals(200, $response->status, $this->printResponseError($response)); $this->assertObjectEqualsEntity($response->getBody()->data, Script::findPk($script->id)); //modify property that does not exists $data = ['foo' => 'bar']; $response = $this->modifyScript($script->id, $data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //modify properties that not alterable $scriptAdapter = new ScriptAdapter($fictionController); $adapterRules = $scriptAdapter->getRules(); $publicProperties = $adapterRules[BaseAdapter::RULE_TYPE_TO_DATA]; $alterableProperties = $adapterRules[ApiEntityAdapter::RULE_TYPE_ALTERABLE]; $nonAlterableProperties = array_diff(array_values($publicProperties), $alterableProperties); foreach ($nonAlterableProperties as $property) { $data = [$property => 'foo']; $response = $this->modifyScript($script->id, $data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); } //modify script that does not exists $data = ['name' => 'test-modify-not-found']; $response = $this->modifyScript(Script::findOne([], null, ['id' => false])->id + 1, $data); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); //modify Scalr-scoped script /* @var $script Script */ $script = static::createEntity(new Script(), ['name' => "{$this->uuid}-script", 'description' => "{$this->uuid}-description", 'createdById' => $user->getId()]); //modify Scalr-scoped script $data = ['name' => 'test-modify-scalr-scoped']; $response = $this->modifyScript($script->id, $data); $this->assertErrorMessageContains($response, 403, ErrorMessage::ERR_PERMISSION_VIOLATION, 'Insufficient permissions'); /* @var $script Script */ $script = static::createEntity(new Script(), ['name' => "{$this->uuid}-script", 'description' => "{$this->uuid}-description", 'accountId' => $user->getAccountId(), 'createdById' => $user->getId()]); //test have access to all listed scripts $scripts = $this->listScripts(); foreach ($scripts as $script) { $this->assertTrue(Script::findPk($script->id)->hasAccessPermissions($user), "Script id: {$script->id}"); } //test convertible data filters $mergedLists = array_merge($this->listScripts(['scope' => ScopeInterface::SCOPE_SCALR]), $this->listScripts(['scope' => ScopeInterface::SCOPE_ENVIRONMENT]), $this->listScripts(['scope' => ScopeInterface::SCOPE_ACCOUNT])); foreach ($mergedLists as $script) { $this->assertTrue(Script::findPk($script->id)->hasAccessPermissions($user), "Script id: {$script->id}"); } //test list scripts filters $filterable = $scriptAdapter->getRules()[ApiEntityAdapter::RULE_TYPE_FILTERABLE]; /* @var $script Script */ foreach ($scripts as $script) { foreach ($filterable as $property) { $filterValue = $script->{$property}; $listResult = $this->listScripts([$property => $filterValue]); if (!static::isRecursivelyEmpty($filterValue)) { foreach ($listResult as $filtered) { $this->assertEquals($filterValue, $filtered->{$property}, "Property '{$property}' mismatch"); } } } $response = $this->getScript($script->id); $this->assertEquals(200, $response->status, $this->printResponseError($response)); $dbScript = Script::findPk($script->id); $this->assertObjectEqualsEntity($response->getBody()->data, $dbScript, $scriptAdapter); } //test have write access to environments and account scoped scripts foreach (array_merge($this->listScripts(['scope' => ScopeInterface::SCOPE_ENVIRONMENT]), $this->listScripts(['scope' => ScopeInterface::SCOPE_ACCOUNT])) as $script) { $this->assertTrue(Script::findPk($script->id)->hasAccessPermissions($user, null, true)); } $listUri = static::getUserApiUrl("/scripts"); //test invalid filters $response = $this->request($listUri, Request::METHOD_GET, ['foo' => 'bar']); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //test invalid filters values $response = $this->request($listUri, Request::METHOD_GET, ['scope' => 'foobar']); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_VALUE); //delete script /* @var $script Script */ $script = static::createEntity(new Script(), ['name' => "{$this->uuid}-script", 'description' => "{$this->uuid}-description", 'envId' => $environment->id, 'createdById' => $user->getId()]); $response = $this->deleteScript($script->id); $this->assertEquals(200, $response->status, $this->printResponseError($response)); //delete scalr-scoped script $scripts = $this->listScripts(['scope' => ScopeInterface::SCOPE_SCALR]); $script = array_shift($scripts); $response = $this->deleteScript($script->id); $this->assertErrorMessageContains($response, 403, ErrorMessage::ERR_PERMISSION_VIOLATION); //delete script that does not exists $response = $this->deleteScript(Script::findOne([], null, ['id' => false])->id + 1); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); }
/** * @test */ public function testComplex() { /* @var Script $script */ $script = static::generateScripts([['os' => 'linux']])[0]; /* @var ScriptVersion $version */ $version = static::generateVersions($script, [['content' => '#!/bin/sh']])[0]; $adapter = $this->getAdapter('OrchestrationRules\\FarmRoleScript'); /* @var User $user */ $user = $this->getUser(); $environment = $this->getEnvironment(); /* @var $farm Farm */ $farm = static::createEntity(new Farm(), ['changedById' => $user->getId(), 'name' => "{$this->uuid}-farm", 'description' => "{$this->uuid}-description", 'envId' => $environment->id, 'accountId' => $user->getAccountId(), 'createdById' => $user->getId()]); $farmRole = $this->createTestFarmRole($farm); static::createEntity(new FarmRoleScript(), ['farmRoleId' => $farmRole->id, 'scriptId' => $script->id, 'farmId' => $farm->id]); //test get endpoint $filterable = $adapter->getRules()[ApiEntityAdapter::RULE_TYPE_FILTERABLE]; $rules = $this->listRules($farmRole->id); foreach ($rules as $rule) { foreach ($filterable as $property) { $filterValue = $rule->{$property}; $listResult = $this->listRules($farmRole->id, [$property => $filterValue]); if (!static::isRecursivelyEmpty($filterValue)) { foreach ($listResult as $filtered) { $this->assertEquals($filterValue, $filtered->{$property}, "Property '{$property}' mismatch"); } } } $response = $this->getRule($farmRole->id, $rule->id); $this->assertEquals(200, $response->status, $this->printResponseError($response)); $dbRule = FarmRoleScript::findPk($rule->id); $this->assertObjectEqualsEntity($response->getBody()->data, $dbRule, $adapter); } $scalrFRScriptData = ['trigger' => ['triggerType' => FarmRoleScriptAdapter::TRIGGER_SINGLE_EVENT, 'event' => ['id' => 'HostInit']], 'target' => ['targetType' => FarmRoleScriptAdapter::TARGET_NAME_TRIGGERING_SERVER], 'action' => ['actionType' => FarmRoleScriptAdapter::ACTION_SCRIPT, 'scriptVersion' => ['script' => ['id' => $script->id], 'version' => $version->version]]]; $localFRScriptData = ['trigger' => ['triggerType' => FarmRoleScriptAdapter::TRIGGER_ALL_EVENTS], 'target' => ['targetType' => FarmRoleScriptAdapter::TARGET_NAME_NULL], 'action' => ['actionType' => FarmRoleScriptAdapter::ACTION_URI, 'path' => 'https://example.com']]; //post scalr rule $response = $this->postRule($farmRole->id, $scalrFRScriptData); $this->assertEquals(201, $response->status, $this->printResponseError($response)); $ruleId = $response->getBody()->data->id; /* @var $rule FarmRoleScript */ $rule = FarmRoleScript::findPk($ruleId); $this->assertNotEmpty($rule); $this->ruleToDelete($ruleId); $this->assertObjectEqualsEntity($scalrFRScriptData, $rule, $adapter); //post local rule $response = $this->postRule($farmRole->id, $localFRScriptData); $this->assertEquals(201, $response->status, $this->printResponseError($response)); $ruleId = $response->getBody()->data->id; /* @var $rule FarmRoleScript */ $rule = FarmRoleScript::findPk($ruleId); $this->assertNotEmpty($rule); $this->ruleToDelete($ruleId); $this->assertObjectEqualsEntity($localFRScriptData, $rule, $adapter); //post rule already existing $data = $scalrFRScriptData; $data['id'] = $ruleId; $response = $this->postRule($farmRole->id, $data); $this->assertEquals(201, $response->status, $this->printResponseError($response)); $ruleId = $response->getBody()->data->id; $this->ruleToDelete($ruleId); $this->assertNotEquals($data['id'], $ruleId); //post rule with script that does not exists $data = $scalrFRScriptData; $data['action']['scriptVersion']['script']['id'] = Script::findOne([], null, ['id' => true])->id + 1; $response = $this->postRule($farmRole->id, $data); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); //post rule with version that does not exists $data = $scalrFRScriptData; $data['action']['scriptVersion']['version'] = Script::findPk($data['action']['scriptVersion']['script']['id'])->getLatestVersion()->version + 1; $response = $this->postRule($farmRole->id, $data); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); //post rule with properties that not existing $data = $scalrFRScriptData; $data['foo'] = 'bar'; $response = $this->postRule($farmRole->id, $data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //post rule without required fields $data = $localFRScriptData; unset($data['action']); $response = $this->postRule($farmRole->id, $data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //post rule with invalid field $data = $localFRScriptData; $data['action'] = ''; $response = $this->postRule($farmRole->id, $data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //modify rule //TODO::ape add modify rule //fetch rule $response = $this->getRule($farmRole->id, $rule->id); $this->assertEquals(200, $response->status, $this->printResponseError($response)); $this->assertObjectEqualsEntity($response->getBody()->data, $rule, $adapter); //fetch rule that doe not exists $response = $this->getRule($farmRole->id, FarmRoleScript::findOne([], null, ['id' => false])->id + 1); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); //fetch rule with missmatch farm role id $response = $this->getRule(FarmRole::findOne([], null, ['id' => false])->id + 1, $rule->id); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_VALUE); //test have access to all listed rules $rules = $this->listRules($farmRole->id); foreach ($rules as $rule) { $this->assertTrue(FarmRoleScript::findPk($rule->id)->hasAccessPermissions($user)); } //test invalid filters $url = self::getUserApiUrl("/farm-roles/{$farmRole->id}/orchestration-rules/"); $response = $this->request($url, Request::METHOD_GET, ['foo' => 'bar']); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); $response = $this->request($url, Request::METHOD_GET, ['scope' => 'foobar']); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //delete script /* @var $rule FarmRoleScript */ $rule = static::createEntity(new FarmRoleScript(), ['farmRoleId' => $farmRole->id, 'scriptId' => $script->id, 'farmId' => $farm->id]); $response = $this->deleteRule($farmRole->id, $rule->id); $this->assertEquals(200, $response->status, $this->printResponseError($response)); //delete script that does not exists $response = $this->deleteRule($farmRole->id, FarmRoleScript::findOne([], null, ['id' => false])->id + 1); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); }
/** * @param int $scriptId * @param string $name * @throws Scalr_Exception_Core * @throws Scalr_UI_Exception_NotFound */ public function xForkAction($scriptId, $name) { $this->request->restrictAccess('SCRIPTS', 'FORK'); if (!$name) { throw new Scalr_Exception_Core('Name cannot be null'); } /* @var $script Script */ $script = Script::findPk($scriptId); if (!$script) { throw new Scalr_UI_Exception_NotFound(); } $script->checkPermission($this->user, $this->getEnvironmentId(true)); $criteria = []; $criteria[] = ['name' => $name]; switch ($this->request->getScope()) { case Script::SCOPE_ENVIRONMENT: $criteria[] = ['envId' => $this->getEnvironmentId(true)]; $criteria[] = ['accountId' => $this->user->getAccountId()]; break; case Script::SCOPE_ACCOUNT: $criteria[] = ['envId' => null]; $criteria[] = ['accountId' => $this->user->getAccountId()]; break; case Script::SCOPE_SCALR: $criteria[] = ['envId' => null]; $criteria[] = ['accountId' => null]; break; } if (Script::findOne($criteria)) { throw new Scalr_Exception_Core('Script name must be unique within current scope'); } $forkedScript = $script->fork($name, $this->user, $this->getEnvironmentId(true)); $this->response->success('Script successfully forked'); $this->response->data(['script' => array_merge($this->getScript($forkedScript), $this->getScriptInfo($forkedScript))]); }
/** * {@inheritdoc} * @see \Scalr\Api\DataType\ApiEntityAdapter::validateEntity() */ public function validateEntity($entity) { if (!$entity instanceof Script) { throw new InvalidArgumentException(sprintf("First argument must be instance of Scalr\\Model\\Entity\\Script class")); } if ($entity->id !== null) { if (!Script::findPk($entity->id)) { throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, sprintf("Could not find out the Script with ID: %d", $entity->id)); } } if (empty($entity->name)) { throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Property name cannot be empty"); } else { switch ($entity->getScope()) { case ScopeInterface::SCOPE_ACCOUNT: $existed = Script::findOne([['name' => $entity->name], ['accountId' => $this->controller->getUser()->accountId], ['envId' => null]]); break; case ScopeInterface::SCOPE_ENVIRONMENT: $existed = Script::findOne([['name' => $entity->name], ['accountId' => $this->controller->getUser()->accountId], ['envId' => $this->controller->getEnvironment()->id]]); break; case ScopeInterface::SCOPE_SCALR: $existed = Script::findOne([['name' => $entity->name], ['accountId' => null], ['envId' => null]]); break; } /* @var $existed Script */ if (!empty($existed) && $entity->id !== $existed->id) { throw new ApiErrorException(409, ErrorMessage::ERR_UNICITY_VIOLATION, "Script '{$entity->name}' already exists on scope {$existed->getScope()}"); } } if (empty($entity->os)) { throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property osType"); } else { if (!in_array($entity->os, [Script::OS_LINUX, Script::OS_WINDOWS])) { throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Invalid osType"); } } //NOTE: scalr-scope currently restricted in APIv2 switch ($entity->getScope()) { case ScopeInterface::SCOPE_ENVIRONMENT: if (!$this->controller->getEnvironment()) { throw new ApiErrorException(403, ErrorMessage::ERR_SCOPE_VIOLATION, "Invalid scope"); } break; case ScopeInterface::SCOPE_ACCOUNT: if ($this->controller->getEnvironment()) { throw new ApiErrorException(403, ErrorMessage::ERR_SCOPE_VIOLATION, "Invalid scope"); } break; case ScopeInterface::SCOPE_SCALR: case ScopeInterface::SCOPE_FARM: case ScopeInterface::SCOPE_FARMROLE: case ScopeInterface::SCOPE_ROLE: case ScopeInterface::SCOPE_SERVER: throw new ApiErrorException(403, ErrorMessage::ERR_SCOPE_VIOLATION, "Invalid scope"); default: throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Invalid scope"); } if (!$this->controller->hasPermissions($entity, true)) { //Checks entity level write access permissions throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, "Insufficient permissions"); } }
/** * @test */ public function testComplex() { $user = $this->getUser(); $environment = $this->getEnvironment(); $fictionController = new ApiController(); //foreach iterates through values in order of ads //we need to remove rules first, then - scripts //we initialize data set for removal with non-existing rule $this->ruleToDelete(-1); /* @var $roles Role[] */ $roles = $this->getTestRoles(); /* @var $role Role */ $role = array_shift($roles); /* @var $scalrRole Role */ $scalrRole = Role::findOne([['envId' => null, 'accountId' => null]]); /* @var $script Script */ $script = static::createEntity(new Script(), ['name' => 'test-role-scripts', 'description' => 'test-role-scripts', '']); $isWindows = $role->getOs()->family == 'windows'; /* @var $version ScriptVersion */ $version = static::createEntity(new ScriptVersion(), ['scriptId' => $script->id, 'version' => $script->getLatestVersion()->version + 1, 'content' => $isWindows ? '#!cmd' : '#!/bin/sh']); $script->os = $isWindows ? 'windows' : 'linux'; $script->save(); $scalrRoleScriptData = ['trigger' => ['type' => RoleScriptAdapter::TRIGGER_SINGLE_EVENT, 'event' => ['id' => 'HostInit']], 'target' => ['type' => RoleScriptAdapter::TARGET_TRIGGERING_FARM_ROLE], 'action' => ['actionType' => RoleScriptAdapter::ACTION_SCRIPT, 'scriptVersion' => ['script' => ['id' => $script->id], 'version' => $version->version]]]; $localRoleScriptData = ['trigger' => ['type' => RoleScriptAdapter::TRIGGER_ALL_EVENTS], 'target' => ['type' => RoleScriptAdapter::TARGET_NULL], 'action' => ['actionType' => RoleScriptAdapter::ACTION_URI, 'uri' => 'https://example.com']]; //post scalr rule $response = $this->postRule($role->id, $scalrRoleScriptData); $this->assertEquals(201, $response->status, $this->printResponseError($response)); $ruleId = $response->getBody()->data->id; /* @var $rule RoleScript */ $rule = RoleScript::findPk($ruleId); $this->assertNotEmpty($rule); $this->ruleToDelete($ruleId); $this->assertObjectEqualsEntity($scalrRoleScriptData, $rule); //post local rule $response = $this->postRule($role->id, $localRoleScriptData); $this->assertEquals(201, $response->status, $this->printResponseError($response)); $ruleId = $response->getBody()->data->id; /* @var $rule RoleScript */ $rule = RoleScript::findPk($ruleId); $this->assertNotEmpty($rule); $this->ruleToDelete($ruleId); $this->assertObjectEqualsEntity($localRoleScriptData, $rule); //post rule to environment-scoped role $response = $this->postRule($scalrRole->id, $scalrRoleScriptData); $this->assertErrorMessageContains($response, 403, ErrorMessage::ERR_PERMISSION_VIOLATION); //post rule already existing $data = $scalrRoleScriptData; $data['id'] = $ruleId; $response = $this->postRule($role->id, $data); $this->assertEquals(201, $response->status, $this->printResponseError($response)); $ruleId = $response->getBody()->data->id; $this->ruleToDelete($ruleId); $this->assertNotEquals($data['id'], $ruleId); //post rule with script that does not exists $data = $scalrRoleScriptData; $data['action']['scriptVersion']['script']['id'] = Script::findOne([], ['id' => true])->id + 1; $response = $this->postRule($role->id, $data); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); //post rule with version that does not exists $data = $scalrRoleScriptData; $data['action']['scriptVersion']['version'] = Script::findPk($data['action']['scriptVersion']['script']['id'])->getLatestVersion()->version + 1; $response = $this->postRule($role->id, $data); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); //post rule with properties that not existing $data = $scalrRoleScriptData; $data['foo'] = 'bar'; $response = $this->postRule($role->id, $data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //post rule without required fields $data = $localRoleScriptData; unset($data['action']); $response = $this->postRule($role->id, $data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //post rule with invalid field $data = $localRoleScriptData; $data['action'] = ''; $response = $this->postRule($role->id, $data); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //fetch rule $response = $this->getRule($role->id, $rule->id); $this->assertEquals(200, $response->status, $this->printResponseError($response)); $this->assertObjectEqualsEntity($response->getBody()->data, $rule); //fetch rule that doe not exists $response = $this->getRule($role->id, RoleScript::findOne([], ['id' => ''])->id + 1); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); //fetch rule with missmatch role id $response = $this->getRule(Role::findOne([], ['id' => ''])->id + 1, $rule->id); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_VALUE); //test have access to all listed rules $rules = $this->listRules($role->id); foreach ($rules as $rule) { $this->assertTrue(RoleScript::findPk($rule->id)->hasAccessPermissions($user)); } $listUri = static::getUserApiUrl("/scripts"); //test invalid filters $response = $this->request($listUri, Request::METHOD_GET, ['foo' => 'bar']); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE); //test invalid filters values $response = $this->request($listUri, Request::METHOD_GET, ['scope' => 'foobar']); $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_VALUE); //delete script /* @var $rule RoleScript */ $rule = static::createEntity(new RoleScript(), ['roleId' => $role->id, 'scriptId' => $script->id]); $response = $this->deleteRule($role->id, $rule->id); $this->assertEquals(200, $response->status, $this->printResponseError($response)); //delete scalr-scoped script /* @var $rule RoleScript */ $rule = static::createEntity(new RoleScript(), ['roleId' => $scalrRole->id, 'scriptId' => $script->id, 'version' => -1]); $response = $this->deleteRule($scalrRole->id, $rule->id); $this->assertErrorMessageContains($response, 403, ErrorMessage::ERR_PERMISSION_VIOLATION); //delete script that does not exists $response = $this->deleteRule($role->id, RoleScript::findOne([], ['id' => ''])->id + 1); $this->assertErrorMessageContains($response, 404, ErrorMessage::ERR_OBJECT_NOT_FOUND); }
/** * @param int $id * @param string $name * @param string $description * @param int $isSync * @param bool $allowScriptParameters * @param int $envId optional * @param int $timeout optional * @param int $version * @param RawData $content * @param string $tags * @param string $uploadType optional * @param string $uploadUrl optional * @param FileUploadData $uploadFile optional * @param bool $checkScriptParameters optional * @throws Scalr_UI_Exception_NotFound * @throws Scalr_Exception_InsufficientPermissions * @throws Exception */ public function xSaveAction($id, $name, $description, $isSync = 0, $allowScriptParameters = false, $envId = NULL, $timeout = NULL, $version, RawData $content, $tags, $uploadType = NULL, $uploadUrl = NULL, FileUploadData $uploadFile = NULL, $checkScriptParameters = false) { $this->request->restrictAccess(Acl::RESOURCE_ADMINISTRATION_SCRIPTS, Acl::PERM_ADMINISTRATION_SCRIPTS_MANAGE); $validator = new Validator(); $validator->validate($name, 'name', Validator::NOEMPTY); if ($uploadType && $uploadType == 'URL') { $validator->validate($uploadUrl, 'uploadUrl', Validator::URL); if (!$validator->isValid($this->response)) { return; } } if ($uploadType) { $content = false; if ($uploadType == 'URL') { $content = @file_get_contents($uploadUrl); $validator->validate($content, 'uploadUrl', Validator::NOEMPTY, [], 'Invalid source'); } else { if ($uploadType == 'File') { $content = $uploadFile; $validator->validate($content, 'uploadFile', Validator::NOEMPTY, [], 'Invalid source'); } else { $validator->addError('uploadType', 'Invalid source for script'); } } } $envId = $envId ? $this->user->getDefaultEnvironment($envId)->id : NULL; $content = str_replace("\r\n", "\n", $content); $tagsResult = []; foreach (explode(',', $tags) as $t) { $t = trim($t); if ($t) { if (!preg_match('/^[a-zA-Z0-9-]{3,10}$/', $t)) { $validator->addError('tags', sprintf('Invalid name for tag: %s', $t)); } $tagsResult[] = $t; } } $tags = $tagsResult; $criteria = []; $criteria[] = ['name' => $name]; if ($id) { $criteria[] = ['id' => ['$ne' => $id]]; } switch ($this->request->getScope()) { case Script::SCOPE_ENVIRONMENT: $criteria[] = ['envId' => $envId]; $criteria[] = ['accountId' => $this->user->getAccountId()]; break; case Script::SCOPE_ACCOUNT: $criteria[] = ['envId' => null]; $criteria[] = ['accountId' => $this->user->getAccountId()]; break; case Script::SCOPE_SCALR: $criteria[] = ['envId' => null]; $criteria[] = ['accountId' => null]; break; } if (Script::findOne($criteria)) { $validator->addError('name', 'Script name must be unique within current scope'); } if (!$validator->isValid($this->response)) { return; } /* @var $script Script */ if ($id) { $script = Script::findPk($id); if (!$script) { throw new Scalr_UI_Exception_NotFound(); } $script->checkPermission($this->user, $envId); if (!$script->accountId && $this->user->getType() != Scalr_Account_User::TYPE_SCALR_ADMIN) { throw new Scalr_Exception_InsufficientPermissions(); } } else { $script = new Script(); $script->accountId = $this->user->getAccountId() ? $this->user->getAccountId() : NULL; $script->createdById = $this->user->getId(); $script->createdByEmail = $this->user->getEmail(); $script->envId = $envId; $version = 1; } //check variables in script content if (!$id && $checkScriptParameters && !$allowScriptParameters) { $scriptHasParameters = Script::hasVariables($content); if (!$scriptHasParameters) { /* @var $scriptVersion ScriptVersion */ foreach ($script->getVersions() as $scriptVersion) { if ($scriptVersion->version != $version) { $scriptHasParameters = Script::hasVariables($scriptVersion->content); if ($scriptHasParameters) { break; } } } } if ($scriptHasParameters) { $this->response->data(['showScriptParametersConfirmation' => true]); $this->response->failure(); return; } } $script->name = $name; $script->description = $description; $script->timeout = $timeout ? $timeout : NULL; $script->isSync = $isSync == 1 ? 1 : 0; $script->allowScriptParameters = $allowScriptParameters ? 1 : 0; $script->os = !strncmp($content, '#!cmd', strlen('#!cmd')) || !strncmp($content, '#!powershell', strlen('#!powershell')) ? Script::OS_WINDOWS : Script::OS_LINUX; $script->save(); $scriptVersion = NULL; if ($version) { $scriptVersion = $script->getVersion($version); } if (!$scriptVersion && $script->getLatestVersion()->content !== $content) { $scriptVersion = new ScriptVersion(); $scriptVersion->scriptId = $script->id; $scriptVersion->version = $script->getLatestVersion()->version + 1; } if ($scriptVersion) { $scriptVersion->changedById = $this->user->getId(); $scriptVersion->changedByEmail = $this->user->getEmail(); $scriptVersion->content = $content; $scriptVersion->save(); } if ($this->user->getAccountId()) { Tag::setTags($tags, $this->user->getAccountId(), Tag::RESOURCE_SCRIPT, $script->id); } $this->response->success('Script successfully saved'); $this->response->data(['script' => array_merge($this->getScript($script), $this->getScriptInfo($script))]); }