Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions app/plugins/TermsAgreer/templates/AgreementCollectors/dispatch.inc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
/**
* COmanage Registry T&C Agreement Colectors Petition Fields
* COmanage Registry T&C Agreement Collectors Petition Fields
* This file is also used during core T&C Review
*
* Portions licensed to the University Corporation for Advanced Internet
* Development, Inc. ("UCAID") under one or more contributor license agreements.
Expand Down Expand Up @@ -51,15 +52,29 @@ print $this->Form->create(null, [
<table>
<tr>
<th><?= __d('controller','TermsAndConditions',[99]) ?></th>
<?php if(!empty($vv_tandc_statuses)): // we are in CO-level T&C review ?>
<th><?= __d('field', 'status'); ?></th>
<th><?= __d('field', 'changelog.actor_identifier'); ?></th>
<th><?= __d('field', 'timestamp.tz', [$vv_tz->getName()]); ?></th>
<?php endif; ?>
<th class="center"><?= __d('operation','review') ?></th>
<th><?= __d('operation','agreement') ?></th>
</tr>

<?php foreach($vv_tandc as $tc): ?>
<?php foreach($vv_tandc as $i => $tc): ?>
<tr class="<?= !empty($tc->url) ? 'tc-url' : 'tc-msp' ?>">
<td>
<?= $tc['description'] ?>
</td>
<?php if(!empty($vv_tandc_statuses)): // we are in CO-level T&C review ?>
<td><?= __d('enumeration', 'TAndCStatusEnum.'.$vv_tandc_statuses[$i]['status']); ?></td>
<td><?= $vv_tandc_statuses[$i]['agreement']->identifier ?? "" ?></td>
<td><?=
!empty($vv_tandc_statuses[$i]['agreement']->created)
? $this->Time->nice($vv_tandc_statuses[$i]['agreement']->created, $vv_tz)
: "";
?></td>
<?php endif; ?>
<td class="center">
<button
data-tc-id="tc<?= $tc['id'] ?>"
Expand All @@ -85,12 +100,18 @@ print $this->Form->create(null, [
<?=
$this->Form->checkbox(
'tc'.$tc['id'],
['id' => 'tc'.$tc['id'], 'class' => 'form-check-input tc-agree-checkbox']
[
'id' => 'tc'.$tc['id'],
'class' => 'form-check-input tc-agree-checkbox',
'checked' => !empty($vv_tandc_statuses) && $vv_tandc_statuses[$i]['status'] == 'Y' ? true : false,
]
) .
$this->Form->label(
'tc'.$tc['id'],
__d('operation','agree'),
['class' => 'form-check-label']
[
'class' => 'form-check-label'
]
)
?>
</div>
Expand All @@ -100,7 +121,6 @@ print $this->Form->create(null, [

</table>


<script>
// Iterate over our T&Cs to see if they're all checked.
function checkAgreements(mode) {
Expand Down
4 changes: 2 additions & 2 deletions app/plugins/TermsAgreer/templates/element/agreeDialog.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@
<button type="button" class="btn-close nospin" data-bs-dismiss="modal" aria-label="<?= __d('operation', 'close'); ?>"></button>
</div>
<div class="modal-body">
<h1 class="tc-agree-dialog-title"><?= $vv_tc->mostly_static_page->title ?></h1>
<h1 class="tc-agree-dialog-title"><?= $vv_tc->mostly_static_page->title ?? '' ?></h1>
<div class="tc-content">
<?= $htmlSanitizer->sanitize($vv_tc->mostly_static_page->body) ?>
<?= $htmlSanitizer->sanitize($vv_tc->mostly_static_page->body ?? '') ?>
</div>
</div>
<div class="modal-footer">
Expand Down
69 changes: 57 additions & 12 deletions app/src/Controller/TermsAndConditionsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
use Cake\Utility\Hash;
use \App\Lib\Enum\ProvisioningContextEnum;
use \App\Lib\Enum\TAndCStatusEnum;
use TermsAgreer\TermsAgreerPlugin;
use TermsAgreer\Lib\Enum\TAndCEnrollmentModeEnum;

class TermsAndConditionsController extends StandardController {
public array $paginate = [
Expand Down Expand Up @@ -146,8 +148,8 @@ public function review() {
// Before we get started, see if a return parameter was requested, and if so if it is permitted.
// If so, we'll override any current return URL. We check the return URL here rather than when
// we're done because URLs stored by AppController are not subject to the allow list check.

$returnUrl = $this->request->getQuery('return');
$request = $this->getRequest();
$returnUrl = $request->getQuery('return');

if(!empty($returnUrl)) {
$returnUrl = base64_decode($returnUrl);
Expand All @@ -160,7 +162,7 @@ public function review() {
if(preg_match($u, $returnUrl)) {
// The requested URL is permitted, so store it in the session, potentially overriding
// the original return URL
$this->request->getSession()->write('TAndC.return', $returnUrl);
$request->getSession()->write('TAndC.return', $returnUrl);
break;
}
}
Expand All @@ -181,23 +183,66 @@ public function review() {

$status = $this->TermsAndConditions->status((int)$personId);

// If there is nothing left to do, redirect to the original request
$done = true;
if($request->is('post')) {
// Walk the set of $status['tandc']s and look for an agreement in the POST data.
$data = $request->getData();

$ok = true;

foreach($status as $s) {
// The post data is keyed on the string "tc" appended to the T&C id,
// and the expected value is "1".

$key = "tc".$s['tandc']->id;

if(!isset($data[$key]) || $data[$key] != "1") {
$ok = false;

foreach($status as $s) {
if($s['status'] != TAndCStatusEnum::Agreed) {
$done = false;
break;
$this->Flash->error(__d('terms_agreer','error.TAndCAgreement.missing', [$s['tandc']->description, $tc->id]));
}
}
}

if($done) {
return $this->redirect($this->request->getSession()->read('TAndC.return'));
if($ok) {
foreach($status as $s) {
$this->log("TCiD: " . $s['tandc']->id);
try {
$this->TermsAndConditions->TAndCAgreements->record(
termsAndConditionsId: (int)$s['tandc']->id,
personId: $personId,
actorPersonId: $personId,
identifier: $this->getRequest()->getSession()->read('Auth.external.user')
);

// Request provisioning on success

$this->llog('trace', "Requesting provisioning after T&C Agreement for Person " . $personId);

$People = TableRegistry::getTableLocator()->get('People');

$People->requestProvisioning(
id: (int)$personId,
context: ProvisioningContextEnum::Automatic
);
} catch(\Exception $e) {
$this->Flash->error($e->getMessage());
return $this->generateRedirect(null);
}
}

// Set the flash message
$this->Flash->success(__d('result', 'TermsAndConditions.recorded'));

// redirect to the original request
return $this->redirect($request->getSession()->read('TAndC.return'));
}
}

$this->set('vv_tandc_statuses', $status);
$this->set('vv_person_id', (int)$personId);

// The default mode for CO and platform wide T&Cs is "Explicit Consent"
$this->set('vv_tandc_mode', TAndCEnrollmentModeEnum::ExplicitConsent);

$this->set('vv_title', __d('controller', 'TermsAndConditions', 99));
}

Expand Down
12 changes: 7 additions & 5 deletions app/src/Model/Table/TermsAndConditionsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public function initialize(array $config): void {
$this->setAllowLookupPrimaryLink(['agree', 'proxy', 'revoke']);
$this->setAllowLookupRelatedPrimaryLink(['status' => ['person_id']]);
$this->setAllowUnkeyedPrimaryLink(['review']);
$this->setAllowEmptyPrimaryLink(['review']);

$this->setIndexContains([
'MostlyStaticPages'
Expand Down Expand Up @@ -181,15 +182,16 @@ public function status(int $personId): array {
// any outdated T&C, we'll pull those separately, below.

$tandc = $this->find()
->contain('MostlyStaticPages')
->where([
'co_id' => $person->co_id,
'status' => SuspendableStatusEnum::Active,
'TermsAndConditions.co_id' => $person->co_id,
'TermsAndConditions.status' => SuspendableStatusEnum::Active,
'OR' => [
'cou_id IS NULL',
'cou_id IN' => array_values($couIds)
'TermsAndConditions.cou_id IS NULL',
'TermsAndConditions.cou_id IN' => array_values($couIds)
]
])
->order('ordr ASC')
->orderBy(['TermsAndConditions.ordr' => 'ASC'])
->all();

if(!empty($tandc)) {
Expand Down
132 changes: 43 additions & 89 deletions app/templates/TermsAndConditions/review.php
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
<?php
/**
* COmanage Registry Terms and Conditions Review View
*
* Portions licensed to the University Corporation for Advanced Internet
* Development, Inc. ("UCAID") under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* UCAID licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.3.0
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/
/**
* COmanage Registry Terms and Conditions Review View
*
* Portions licensed to the University Corporation for Advanced Internet
* Development, Inc. ("UCAID") under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* UCAID licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.3.0
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/

use App\Lib\Enum\TAndCStatusEnum;
use App\Lib\Util\StringUtilities;

use App\Lib\Enum\TAndCStatusEnum;
use App\Lib\Util\StringUtilities;
?>

<div class="page-title-container">
Expand All @@ -35,68 +36,21 @@
</div>
</div>

<?= $this->element('flash') // Flash messages ?>

<!-- Our view is similar to index.php and status.php -->
<?= $this->element('flash') // Flash messages ?>
<?= $this->Form->create(null); // We don't need an object for this form ?>
<div class="table-container">
<table id="termsandconditionsstatus-table" class="index-table list-mode with-actions">
<thead>
<tr>
<th class="with-field-actions"><?= __d('controller', 'TermsAndConditions', [1]); ?></th>
<th><?= __d('field', 'status'); ?></th>
<th><?= __d('field', 'changelog.actor_identifier'); ?></th>
<th><?= __d('field', 'timestamp.tz', [$vv_tz->getName()]); ?></th>
</tr>
</thead>

</tbody>
<?php foreach($vv_tandc_statuses as $t): ?>
<tr>
<td class="with-field-actions">
<div class="field-actions-container">
<div class="field-actions">
<?php
// Build the row actions
$action_args = array();
$action_args['vv_attr_id'] = $t['tandc']->id;
$action_args['vv_actions'] = [];

if($t['status'] != TAndCStatusEnum::Agreed) {
// T&C that are not current can be agreed to

$action_args['vv_actions'][] = [
'order' => $this->Menu->getMenuOrder('Default'),
'icon' => 'signature',
'url' => [
'controller' => 'terms_and_conditions',
'action' => 'agree',
$t['tandc']->id
],
'label' => __d('operation', 'agree'),
'confirm' => [
'dg_body_txt' => __d('operation', 'TermsAndConditions.agree.confirm'),
'dg_confirm_btn' => __d('operation', 'confirm')
]
];
}
<?php
// extract the T&Cs for handoff to the TermsAgreer dispatch template
$vv_tandc = [];
foreach($vv_tandc_statuses as $t) {
$vv_tandc[] = $t['tandc'];
}
include ROOT . DS . 'plugins' . DS . 'TermsAgreer' . DS . 'templates' . DS . 'AgreementCollectors' . DS . 'dispatch.inc';
?>
</div>

if(!empty($action_args['vv_actions'])) {
print $this->element('menuAction', $action_args);
}
?>
</div>
<?= $t['tandc']->description; ?>
</div>
</td>
<td><?= __d('enumeration', 'TAndCStatusEnum.'.$t['status']); ?></td>
<td><?= $t['agreement']->identifier ?? "" ?></td>
<td><?=
!empty($t['agreement']->created)
? $this->Time->nice($t['agreement']->created, $vv_tz)
: "";
?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div id="tandc-review-submit" class="submit">
<input type="submit" value="<?= __d('command','continue') ?>" class="spin submit-button btn btn-primary">
</div>
<?= $this->Form->end(); ?>
4 changes: 2 additions & 2 deletions app/templates/element/javascript.php
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,8 @@
}
});

// Add a .nospin class to all on-page cake error and warning links
$(".cake-error a").addClass('nospin');
// Add a .nospin class to all on-page cake error and warning links (and debugging accordions)
$(".cake-error a, a.cake-debug-collapse").addClass('nospin');

// Add loading animation when a form is submitted, when any item with a "spin" class is clicked,
// or on any anchor tag lacking the .nospin class. We do not automatically add this to buttons
Expand Down
12 changes: 12 additions & 0 deletions app/webroot/css/co-base.css
Original file line number Diff line number Diff line change
Expand Up @@ -2480,6 +2480,18 @@ body.termsandconditions ul.form-list li.fields-url {
.tc-agree-dialog .modal-body h6 {
margin-bottom: 0.5em;
}
/* Terms and Conditions Review hides most interface elements.
XXX If we find there is a general need to hide navigation elements outside of
enrollment flows and T&Cs, we'll do this more generically */
body.termsandconditions.review #top-bar,
body.termsandconditions.review #breadcrumbs,
body.termsandconditions.review #navigation-drawer {
display: none;
}
body.termsandconditions.review #tandc-review-submit {
text-align: right;
margin: 1.5em 0 0;
}
/* MOSTLY STATIC PAGES */
body.pages.logged-out #top-bar,
body.pages.logged-out #breadcrumbs {
Expand Down