diff --git a/app/resources/locales/en_US/command.po b/app/resources/locales/en_US/command.po index 6ed37b16c..23e6fa71b 100644 --- a/app/resources/locales/en_US/command.po +++ b/app/resources/locales/en_US/command.po @@ -51,5 +51,11 @@ msgstr "Calculate changes but do not apply" msgid "se.already" msgstr "Setup appears to have already run" +msgid "se.db.co" +msgstr "Creating COmanage CO" + +msgid "se.db.co.done" +msgstr "COmanage CO created - CO Id: {0}" + msgid "se.salt" msgstr "Generating salt file" diff --git a/app/resources/locales/en_US/default.po b/app/resources/locales/en_US/default.po index fe117035f..6171f63c6 100644 --- a/app/resources/locales/en_US/default.po +++ b/app/resources/locales/en_US/default.po @@ -29,6 +29,9 @@ msgstr "registry" msgid "product.comanage" msgstr "COmanage" +msgid "registry.co.desc" +msgstr "COmanage Registry Internal CO" + # This should match the ISO 639-1 two letter language code for the translation msgid "registry.meta.lang" msgstr "en" diff --git a/app/src/Command/SetupCommand.php b/app/src/Command/SetupCommand.php index 4b00f2911..942a4775d 100644 --- a/app/src/Command/SetupCommand.php +++ b/app/src/Command/SetupCommand.php @@ -18,43 +18,45 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * * @link https://www.internet2.edu/comanage COmanage Project * @package registry * @since COmanage Registry v5.0.0 * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -declare(strict_types = 1); +declare(strict_types=1); namespace App\Command; -use App\Application; +use Cake\ORM\Locator\LocatorAwareTrait; use Cake\Console\Arguments; use Cake\Console\Command; -use Cake\Console\CommandRunner; use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOptionParser; -use Cake\ORM\TableRegistry; use Cake\Utility\Security; -use \App\Lib\Enum\PermissionEnum; +use App\Lib\Enum\PermissionEnum; + -class SetupCommand extends Command { +class SetupCommand extends Command +{ /** * Register command specific options. * - * @since COmanage Registry v6.0.0 - * @param ConsoleOptionParser $parser Console Option Parser + * @param ConsoleOptionParser $parser Console Option Parser + * * @return ConsoleOptionParser Console Option Parser + * @since COmanage Registry v6.0.0 */ - - public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser { + + public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser + { $parser->addOption('admin-username', [ - 'help' => __d('command', 'opt.admin-username') - ])->addOption('force', [ - 'help' => __d('command', 'opt.force'), - 'boolean' => true - ]); + 'help' => __d('command', 'opt.admin-username'), + ])->addOption('force', [ + 'help' => __d('command', 'opt.force'), + 'boolean' => true, + ]); return $parser; } @@ -62,80 +64,57 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar /** * Execute the Setup Command. * + * @param Arguments $args Command Arguments + * @param ConsoleIo $io Console IO + * * @since COmanage Registry v5.0.0 - * @param Arguments $args Command Arguments - * @param ConsoleIo $io Console IO */ - - public function execute(Arguments $args, ConsoleIo $io) { + + public function execute(Arguments $args, ConsoleIo $io) + { global $argv; - + // Check if the security salt file already exists, and if so abort. - - $securitySaltFile = LOCAL . DS . "Config" . DS . "security.salt"; - + + $securitySaltFile = LOCAL . DS . "config" . DS . "security.salt"; + if(file_exists($securitySaltFile)) { $io->out(__d('command', 'se.already')); - + if(!$args->getOption('force')) { exit; } } - - // Before we get going, prompt for whatever information we need in case - // the user hits ctrl-c. - /* - $user = $args->getOption('admin-username'); - - while(!$user) { - $user = $io->ask(__('match.cmd.se.admin.user')); - } - */ - // Set the salt now in case we need it. (Normally this is done in bootstrap.php.) - // We'll write it out after we're done with the database updates. + + // Set the salt now in case we need it. Normally this is done in bootstrap.php. $salt = hash('sha256', Security::randomBytes(64)); Security::setSalt($salt); - - // Perform database related setup. Start by trying to run the database schema. -/* - // Build the runner with an application and root executable name. (based on bin/cake.php) - $runner = new CommandRunner(new Application(dirname(__DIR__) . DS . '..' . DS . 'config'), 'cake'); - $runner->run([ $argv[0], 'database' ]); - - // Create the initial admin permission - $io->out(__('match.cmd.se.admin')); - - $permissionsTable = TableRegistry::get('Permissions'); - $permission = $permissionsTable->newEntity(); - - $permission->username = $user; - $permission->matchgrid_id = null; - $permission->permission = PermissionEnum::PlatformAdmin; - - if(!$permissionsTable->save($permission)) { - throw new \RuntimeException(__('match.er.save', ['Permissions'])); - } - - // Register the current version for future upgrade purposes - // Read the current release from the VERSION file - $versionFile = CONFIG . "VERSION"; - - $targetVersion = rtrim(file_get_contents($versionFile)); - - $metaTable = TableRegistry::get('Meta'); - $metaTable->setUpgradeVersion($targetVersion, true); - */ + // Write out the salt file $io->out(__d('command', 'se.salt')); - - if(file_put_contents($securitySaltFile, $salt)===false) { + + if (file_put_contents($securitySaltFile, $salt) === false) { $err = error_get_last(); throw new \RuntimeException($err[message]); } - - // We set 444 to prevent accidental changing of the salt, but also so the + // We set 444 to prevent accidental changing of the salt, but also so the // web server user can read it if this script is run by (say) root. // We assume we're not installed on a shared, semi-public server. chmod($securitySaltFile, 0444); + + // We need the following: + // - The COmanage CO + // - Register the current version for future upgrade purposes + + // Start with the COmanage CO + + $io->out(__d('command', 'se.db.co')); + + $coTable = $this->getTableLocator()->get("Cos"); + + $co_id = $coTable->setupCOmanageCO(); + if(!is_null($co_id)) { + $io->out(__d('command', 'se.db.co.done', [$co_id])); + } } } \ No newline at end of file diff --git a/app/src/Command/TransmogrifyCommand.php b/app/src/Command/TransmogrifyCommand.php index 9af1f8f70..b4667ac4b 100644 --- a/app/src/Command/TransmogrifyCommand.php +++ b/app/src/Command/TransmogrifyCommand.php @@ -428,7 +428,7 @@ public function execute(Arguments $args, ConsoleIo $io) { $outdb = ConnectionManager::get('default'); $outcfg = $outdb->config(); - if(empty($incfg)) { + if(empty($outcfg)) { throw new \InvalidArgumentException(__d('error', 'db.config', ["default"])); } diff --git a/app/src/Model/Table/CosTable.php b/app/src/Model/Table/CosTable.php index b5f6e9fa1..9f876d08c 100644 --- a/app/src/Model/Table/CosTable.php +++ b/app/src/Model/Table/CosTable.php @@ -29,12 +29,13 @@ namespace App\Model\Table; +use App\Lib\Enum\StatusEnum; use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\ORM\TableRegistry; use Cake\Validation\Validator; -use \App\Lib\Enum\TemplateableStatusEnum; +use App\Lib\Enum\TemplateableStatusEnum; class CosTable extends Table { use \App\Lib\Traits\AutoViewVarsTrait; @@ -158,7 +159,7 @@ public function duplicate($id) { public function findCOmanageCO(Query $query): Query { return $query->where(['lower(name)' => 'comanage']); } - + /** * Callback after model save. * @@ -188,33 +189,39 @@ public function localAfterSave(\Cake\Event\EventInterface $event, \Cake\Datasour /** * Application Rule to determine if the current entity is the COmanage CO. * + * @param Entity $entity Entity to be validated + * @param array $options Application rule options + * + * @return string|bool true if the Rule check passes, false otherwise * @since COmanage Registry v5.0.0 - * @param Entity $entity Entity to be validated - * @param array $options Application rule options - * @return boolean true if the Rule check passes, false otherwise */ - - public function ruleIsCOmanageCO($entity, $options): bool { + + public function ruleIsCOmanageCO($entity, array $options): string|bool { // We want negative logic since we want to fail if we're editing the COmanage CO if($entity->isCOmanageCO()) { - return __d('error', 'edit.comanage'); + // Check if the COmanage CO already exists. + $comanage = $this->find()->where(['lower(name)' => 'comanage'])->count(); + if($comanage > 0) { + return __d('error', 'edit.comanage'); + } } - + return true; } - + /** * Application Rule to determine if the current entity is not Active. * + * @param Entity $entity Entity to be validated + * @param array $options Application rule options + * + * @return bool|string true if the Rule check passes, false otherwise * @since COmanage Registry v5.0.0 - * @param Entity $entity Entity to be validated - * @param array $options Application rule options - * @return boolean true if the Rule check passes, false otherwise */ - - public function ruleIsActive($entity, $options): bool { + + public function ruleIsActive($entity, array $options): bool|string { // We want negative logic since we want to fail if the record is Active - if($entity->status == TemplateableStatusEnum::Active) { + if($entity->status === TemplateableStatusEnum::Active) { return __d('error', 'delete.active'); } @@ -241,6 +248,27 @@ public function setup(int $id): bool { return true; } + + /** + * Perform initial setup for COmanage CO + * + * @since COmanage Registry v5.0.0 + * @return null|int null or the id of the COmanage CO + */ + + public function setupCOmanageCO(): int|null { + $comanage_co = $this->newEmptyEntity(); + $comanage_co->name = __d('command', 'product.comanage'); + $comanage_co->description = __d('command', 'registry.co.desc'); + $comanage_co->status = StatusEnum::Active; + + $co_id = null; + if ($this->save($comanage_co)) { + $co_id = $comanage_co->id; + } + + return $co_id; + } /** * Set validation rules. diff --git a/app/src/Model/Table/TypesTable.php b/app/src/Model/Table/TypesTable.php index 4322c71dd..fda1fbe82 100644 --- a/app/src/Model/Table/TypesTable.php +++ b/app/src/Model/Table/TypesTable.php @@ -154,7 +154,12 @@ public function addDefault(int $coId, string $attribute) { // We need the appropriate model for $attribute to manipulate the default types // $table = (eg) NamesTable $table = TableRegistry::getTableLocator()->get($attr[0]); - + + // Not every Model has default types + if(!method_exists($table, 'availableTypes')) { + return true; + } + // The current set of types for this model, of the form value => display_name $current = $table->availableTypes($coId, $attribute);