Skip to content

CFM-28_Setup_Command #30

Merged
merged 1 commit into from Aug 18, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/resources/locales/en_US/command.po
Expand Up @@ -51,6 +51,12 @@ 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"

Expand Down
3 changes: 3 additions & 0 deletions app/resources/locales/en_US/default.po
Expand Up @@ -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"
Expand Down
120 changes: 49 additions & 71 deletions app/src/Command/SetupCommand.php
Expand Up @@ -18,124 +18,102 @@
* 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\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;
}

/**
* 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]));
}
}
}
2 changes: 1 addition & 1 deletion app/src/Command/TransmogrifyCommand.php
Expand Up @@ -451,7 +451,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"]));
}

Expand Down
56 changes: 40 additions & 16 deletions app/src/Model/Table/CosTable.php
Expand Up @@ -29,6 +29,7 @@

namespace App\Model\Table;

use App\Lib\Enum\StatusEnum;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
Expand Down Expand Up @@ -160,7 +161,7 @@ public function duplicate($id) {
public function findCOmanageCO(Query $query): Query {
return $query->where(['lower(name)' => 'comanage']);
}

/**
* Obtain the set of COs for the specified Identifier. The Identifier must
* be a login identifier, Active, and attached to an Active or Grace Period
Expand Down Expand Up @@ -236,33 +237,35 @@ 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');
}
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');
}

Expand All @@ -289,6 +292,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, ['checkRules' => false])) {
$co_id = $comanage_co->id;
}

return $co_id;
}

/**
* Set validation rules.
Expand Down
2 changes: 1 addition & 1 deletion app/src/Model/Table/TypesTable.php
Expand Up @@ -154,7 +154,7 @@ 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]);

// The current set of types for this model, of the form value => display_name
$current = $table->availableTypes($coId, $attribute);

Expand Down