Skip to content

Commit

Permalink
CFM-363 Enhance related permissions, and move cached EIS record to Ex…
Browse files Browse the repository at this point in the history
…ternal Identity view (take 2) (#160)

* First step in moving the cached EIS Record to the Person/External Identity subnavigation (CFM-363) (#155)

* fix related permissions

* fetch missing person data

* Remove empty entity array

---------

Co-authored-by: Ioannis Igoumenos <ioigoume@gmail.com>
  • Loading branch information
arlen and Ioannis authored Feb 22, 2024
1 parent 959c36e commit 622e15a
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,19 @@ class SqlProvisionersTable extends Table {
'source' => 'People',
'source_table' => 'people',
'related' => [
// We need to process PersonRoles first (last on delete) in case an
// MVEA refers to it
'PersonRoles',
'AdHocAttributes',
'Addresses',
'EmailAddresses',
'ExternalIdentities',
'GroupMembers',
'Identifiers',
'Names',
'Pronouns',
'TelephoneNumbers',
'Urls'
'table' => [
'AdHocAttributes',
'Addresses',
'EmailAddresses',
'ExternalIdentities',
'GroupMembers',
'Identifiers',
'Names',
'PersonRoles',
'Pronouns',
'TelephoneNumbers',
'Urls'
],
]
],
'Groups' => [
Expand All @@ -82,7 +82,9 @@ class SqlProvisionersTable extends Table {
'source' => 'Groups',
'source_table' => 'groups',
'related' => [
'GroupMembers'
'table' => [
'GroupMembers'
],
]
]
];
Expand Down Expand Up @@ -116,15 +118,17 @@ class SqlProvisionersTable extends Table {
'source' => 'ExternalIdentities',
'source_table' => 'external_identities',
'related' => [
'AdHocAttributes',
'Addresses',
'EmailAddresses',
'ExternalIdentityRoles',
'Identifiers',
'Names',
'Pronouns',
'TelephoneNumbers',
'Urls'
'table' => [
'AdHocAttributes',
'Addresses',
'EmailAddresses',
'ExternalIdentityRoles',
'Identifiers',
'Names',
'Pronouns',
'TelephoneNumbers',
'Urls'
],
]
],
'ExternalIdentityRoles' => [
Expand All @@ -133,9 +137,11 @@ class SqlProvisionersTable extends Table {
'source' => 'ExternalIdentityRoles',
'source_table' => 'external_identity_roles',
'related' => [
'AdHocAttributes',
'Addresses',
'TelephoneNumbers'
'table' => [
'AdHocAttributes',
'Addresses',
'TelephoneNumbers'
],
]
],
'GroupMembers' => [
Expand Down Expand Up @@ -166,9 +172,11 @@ class SqlProvisionersTable extends Table {
'source' => 'PersonRoles',
'source_table' => 'person_roles',
'related' => [
'AdHocAttributes',
'Addresses',
'TelephoneNumbers'
'table' => [
'AdHocAttributes',
'Addresses',
'TelephoneNumbers'
],
]
],
'Pronouns' => [
Expand Down
87 changes: 82 additions & 5 deletions app/src/Controller/Component/RegistryAuthComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
use \Cake\Http\Exception\UnauthorizedException;
use \Cake\ORM\ResultSet;
use \Cake\ORM\TableRegistry;
use \Cake\Utility\Inflector;
use \App\Lib\Enum\AuthenticationEventEnum;
use \App\Lib\Enum\SuspendableStatusEnum;
use \App\Lib\Enum\TemplateableStatusEnum;
Expand Down Expand Up @@ -319,6 +320,9 @@ protected function calculatePermissions(?int $id=null): array {

// Is this user a CO Member?
$coMember = $this->isCoMember($controller->getCOID());

// Get the action
$reqAction = $controller->getRequest()->getParam('action');

// Is this record read only?
$readOnly = false;
Expand All @@ -333,8 +337,27 @@ protected function calculatePermissions(?int $id=null): array {
$readOnlyActions = ['view'];

// Pull the record so we can interrogate it

$obj = $table->get($id);

// XXX Get the record along with the contains
// We use findById() rather than get() so we can apply subsequent
// query modifications via traits
$query = $table->findById($id);

// QueryModificationTrait
$getActionMethod = "get{$reqAction}Contains";
if(method_exists($table, $getActionMethod)) {
$query = $query->contain($table->$getActionMethod());
}

try {
// Pull the current record
$obj = $query->firstOrFail();
}
catch(\Exception $e) {
// findById throws Cake\Datasource\Exception\RecordNotFoundException
$this->Flash->error($e->getMessage());
return $this->generateRedirect(null);
}

if(method_exists($obj, "isReadOnly")) {
$readOnly = $obj->isReadOnly();
Expand Down Expand Up @@ -375,9 +398,62 @@ protected function calculatePermissions(?int $id=null): array {

$ret[$action] = $ok;
}

if(!empty($permissions['related']['entity'])) {
foreach($permissions['related']['entity'] as $rtable) {
$RelatedTable = TableRegistry::getTableLocator()->get($rtable);
$rpermissions = $this->getTablePermissions($RelatedTable, $id);
$robj = $obj->get(Inflector::singularize(Inflector::underscore($rtable)));
$rreadOnlyActions = ['view'];

// Is this record read only?
$rreadOnly = false;

// Can this record be deleted?
$rcanDelete = true;

if($robj !== null && method_exists($robj, "isReadOnly")) {
$rreadOnly = $robj->isReadOnly();

if(!empty($rpermissions['readOnly'])) {
// Merge in controller specific actions permitted on read only entities
$rreadOnlyActions = array_merge($rreadOnlyActions, $rpermissions['readOnly']);
}
}

if($robj !== null && method_exists($robj, "canDelete")) {
$rcanDelete = $robj->canDelete();
}

foreach($rpermissions['entity'] as $action => $roles) {
$ok = false;

if((($action != 'delete' || $rcanDelete)
&&
!$rreadOnly) || in_array($action, $rreadOnlyActions)) {
if(is_array($roles)) {
// A list of roles authorized to perform this action, see if the
// current user has any
foreach($roles as $role) {
// eg: $role = "platformAdmin", which corresponds to the variables set, above
if($$role) {
$ok = true;
break;
}
}
} elseif($roles === true) {
// Any authenticated user is permitted
$ok = true;
}
}

$ret[$rtable][$action] = $ok;
}
}
}

if(!empty($permissions['related'])) {
foreach($permissions['related'] as $rtable) {
if(!empty($permissions['related']['table'])) {
foreach($permissions['related']['table'] as $rtable) {
$RelatedTable = TableRegistry::getTableLocator()->get($rtable);
$rpermissions = $this->getTablePermissions($RelatedTable, $id);

Expand All @@ -403,7 +479,8 @@ protected function calculatePermissions(?int $id=null): array {
}
}
}
} else {

} else { // No $id
// Permissions for actions that operate over tables

foreach($permissions['table'] as $action => $roles) {
Expand Down
4 changes: 3 additions & 1 deletion app/src/Model/Table/CosTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ public function initialize(array $config): void {
],
// Related models whose permissions we'll need, typically for table views
'related' => [
'Dashboards'
'table' => [
'Dashboards'
]
]
]);
}
Expand Down
3 changes: 2 additions & 1 deletion app/src/Model/Table/ExtIdentitySourceRecordsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ public function initialize(array $config): void {
]);

$this->setViewContains([
'ExternalIdentitySources'
'ExternalIdentitySources',
'ExternalIdentities' => ['People' => ['PrimaryName']],
]);
/*
// XXX This doesn't seem to correlate to what actually renders?
Expand Down
30 changes: 17 additions & 13 deletions app/src/Model/Table/ExternalIdentitiesTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function initialize(array $config): void {
$this->hasMany('ExternalIdentityRoles')
->setDependent(true)
->setCascadeCallbacks(true);
$this->hasMany('ExtIdentitySourceRecords')
$this->hasOne('ExtIdentitySourceRecords')
->setDependent(true)
->setCascadeCallbacks(true);
$this->hasMany('HistoryRecords')
Expand Down Expand Up @@ -163,18 +163,22 @@ public function initialize(array $config): void {
],
// Related models whose permissions we'll need, typically for table views
'related' => [
'Names',
'Addresses',
'AdHocAttributes',
'EmailAddresses',
'ExternalIdentityRoles',
'ExtIdentitySourceRecords',
'HistoryRecords',
'Identifiers',
'JobHistoryRecords',
'Pronouns',
'TelephoneNumbers',
'Urls'
'entity' => [
'ExtIdentitySourceRecords',
],
'table' => [
'Names',
'Addresses',
'AdHocAttributes',
'EmailAddresses',
'ExternalIdentityRoles',
'HistoryRecords',
'Identifiers',
'JobHistoryRecords',
'Pronouns',
'TelephoneNumbers',
'Urls'
],
]
]);
}
Expand Down
14 changes: 8 additions & 6 deletions app/src/Model/Table/GroupsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,18 @@ public function initialize(array $config): void {
],
// Related models whose permissions we'll need, typically for table views
'related' => [
'table' => [
// XXX As a first pass, this (combined with the implementation in AppController::calculatePermissions)
// will render a link to group-members?group_id=X for all groups in the index view
// groups?co_id=2. This may or may not be right in the long term, eg for private
// groups. Maybe it's OK for now, since all groups are visible to all members of the CO.
'GroupMembers',
'GroupNestings',
'HistoryRecords',
'IdentifierAssignments',
'Identifiers',
'ProvisioningTargets'
'GroupMembers',
'GroupNestings',
'HistoryRecords',
'IdentifierAssignments',
'Identifiers',
'ProvisioningTargets'
],
]
]);
}
Expand Down
4 changes: 3 additions & 1 deletion app/src/Model/Table/IdentifiersTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ public function initialize(array $config): void {
],
// Related models whose permissions we'll need, typically for table views
'related' => [
'AuthenticationEvents'
'table' => [
'AuthenticationEvents'
]
]
]);
}
Expand Down
4 changes: 3 additions & 1 deletion app/src/Model/Table/JobsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ public function initialize(array $config): void {
'readOnly' => ['cancel'],
// Related models whose permissions we'll need, typically for table views
'related' => [
'JobHistoryRecords'
'table' => [
'JobHistoryRecords'
]
]
]);
}
Expand Down
6 changes: 5 additions & 1 deletion app/src/Model/Table/NamesTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ public function initialize(array $config): void {
$this->belongsTo('People');
$this->belongsTo('ExternalIdentities');
$this->belongsTo('Types');

$this->belongsTo('ExtIdentitySourceRecords')
->setClassName('ExtIdentitySourceRecords')
->setForeignKey('source_name_id')
->setProperty('source_name');

$this->setDisplayField('full_name');

$this->setPrimaryLink(['external_identity_id', 'person_id']);
Expand Down
28 changes: 15 additions & 13 deletions app/src/Model/Table/PeopleTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,20 @@ public function initialize(array $config): void {
],
// Related models whose permissions we'll need, typically for table views
'related' => [
'Addresses',
'AdHocAttributes',
'Names',
'EmailAddresses',
'ExternalIdentities',
'HistoryRecords',
'IdentifierAssignments',
'Identifiers',
'PersonRoles',
'ProvisioningTargets',
'TelephoneNumbers',
'Urls'
'table' => [
'Addresses',
'AdHocAttributes',
'Names',
'EmailAddresses',
'ExternalIdentities',
'HistoryRecords',
'IdentifierAssignments',
'Identifiers',
'PersonRoles',
'ProvisioningTargets',
'TelephoneNumbers',
'Urls'
],
]
]);
}
Expand Down Expand Up @@ -660,7 +662,7 @@ public function validationDefault(Validator $validator): Validator {
'content' => ['rule' => 'isInteger']
]);
$validator->notEmptyString('co_id');

$validator->add('status', [
'content' => ['rule' => ['inList', StatusEnum::getConstValues()]]
]);
Expand Down
Loading

0 comments on commit 622e15a

Please sign in to comment.