diff --git a/Config/Schema/schema.xml b/Config/Schema/schema.xml index e978574..9b65be3 100644 --- a/Config/Schema/schema.xml +++ b/Config/Schema/schema.xml @@ -52,7 +52,7 @@ </index> </table> - <table name="grouper_lite_act_as_people"> + <table name="act_as_people"> <field name="id" type="I"> <key /> <autoincrement /> @@ -63,7 +63,7 @@ <field name="act_as_co_person_id" type="I"> <constraint>REFERENCES cm_co_people(id)</constraint> </field> - <field name="actor_co_person_id" type="I"> + <field name="co_person_id" type="I"> <constraint>REFERENCES cm_co_people(id)</constraint> </field> <field name="created" type="T" /> diff --git a/Controller/GrouperLiteActAsPeopleController.php b/Controller/ActAsPeopleController.php similarity index 59% rename from Controller/GrouperLiteActAsPeopleController.php rename to Controller/ActAsPeopleController.php index d69da89..eb872ff 100644 --- a/Controller/GrouperLiteActAsPeopleController.php +++ b/Controller/ActAsPeopleController.php @@ -2,19 +2,23 @@ App::uses('Validator', 'Vendor/cakephp/Validation'); App::uses('CoGrouperLite', 'GrouperLiteWidget.Model/'); +App::uses('ActAsPerson', 'GrouperLiteWidget.Model/'); App::uses('GrouperGroup', 'GrouperLiteWidget.Model/'); + App::uses('Identifier', 'Model'); -class GrouperLiteActAsPeopleController extends StandardController +class ActAsPeopleController extends GrouperLiteWidgetAppController { public $helpers = ['Html', 'Form', 'Flash']; // Dynamic properties are deprecated, so we will define the property here private $userId; + public $requires_person = true; + public $uses = [ - 'GrouperLiteWidget.GrouperLiteActAsPerson', + 'GrouperLiteWidget.ActAsPerson', 'GrouperLiteWidget.CoGrouperLiteWidget', 'GrouperLiteWidget.GrouperGroup', 'Identifier', @@ -31,7 +35,7 @@ class GrouperLiteActAsPeopleController extends StandardController ]; - public $name = 'GrouperLiteActAsPeople'; + public $name = 'ActAsPeople'; /** * Overrides parent beforeFilter to verify that Session contains the correct API settings. @@ -64,6 +68,61 @@ public function beforeFilter() $this->CoGrouperLiteWidget->setConfig($cfg); } + /** + * Add an ActAs user + * + * @since COmanage Registry v4.4.0 + */ + + public function add(): void + { + $this->layout = null; + $this->autoRender = false; + + if(!$this->request->is('restful') + && !$this->request->is('ajax')) { + throw new RuntimeException('HTTP Method Not Allowed', HttpStatusCodesEnum::HTTP_METHOD_NOT_ALLOWED); + } + + $data = $this->request->data; + + try { + $ret = $this->ActAsPerson->saveAll($data); + } + catch(Exception $e) { + $err = filter_var($e->getMessage(),FILTER_SANITIZE_SPECIAL_CHARS); + } + + if($ret) { + // Reread the data so we account for any normalizations + $args = []; + $args['conditions']['ActAsPerson.id'] = $this->ActAsPerson->id; + $args['contain'] = false; + $data = $this->ActAsPerson->find('first', $args); + $this->Api->restResultHeader(201, "Added"); + $this->set('ActAsPerson', $this->ActAsPerson->id); + $this->response->body(json_encode($data['ActAsPerson'], JSON_THROW_ON_ERROR)); + } else { + $fs = $this->ActAsPerson->invalidFields(); + + if(!empty($fs)) { + $this->Api->restResultHeader(400, 'Invalid Fields'); + $this->set('invalid_fields', $fs); + } elseif ($e + && isset(_txt('en.http.status.codes')[$e->getCode()]) ) { + $this->Api->restResultHeader($e->getCode(), _txt('en.http.status.codes')[$e->getCode()]); + if(!empty($e->getMessage())) { + $this->set('vv_error', $e->getMessage()); + } + } else { + $this->Api->restResultHeader(500, "Other Error"); + } + } + + $this->response->send(); + } + + /** * NOTE: All permissions will be done on the Grouper side. All Authenticated users will be able to * use this plugin for self-admin of groups. @@ -78,12 +137,14 @@ public function beforeFilter() public function isAuthorized(): array|bool { $roles = $this->Role->calculateCMRoles(); + $pids = $this->parsePersonID($this->request->data); + $cfg = $this->CoGrouperLiteWidget->getConfig(); // Find the identifier $args = array(); $args['conditions']['Identifier.type'] = $cfg['CoGrouperLiteWidget']['identifier_type']; $args['conditions']['Identifier.status'] = SuspendableStatusEnum::Active; - $args['conditions']['Identifier.co_person_id'] = $roles['copersonid']; + $args['conditions']['Identifier.co_person_id'] = !empty($roles['copersonid']) ? $roles['copersonid'] : $pids['copersonid']; $args['contain'] = false; $identifiers = $this->Identifier->find('first', $args); @@ -99,7 +160,8 @@ public function isAuthorized(): array|bool $isActAsEligibilityGroupmember = false; if(!empty($eligibleGroup)) { - $isActAsEligibilityGroupmember = $this->GrouperGroup->isGroupMember($this->getUserId(), $eligibleGroup, $cfg); + $isActAsEligibilityGroupmember = $this->GrouperGroup + ->isGroupMember($this->getUserId(), $eligibleGroup, $cfg); } // Determine what operations this user can perform @@ -109,7 +171,9 @@ public function isAuthorized(): array|bool $p['add'] = $isActAsEligibilityGroupmember; $p['delete'] = $isActAsEligibilityGroupmember; $p['edit'] = $isActAsEligibilityGroupmember; - $p['update'] = $isActAsEligibilityGroupmember; + $p['index'] = $isActAsEligibilityGroupmember; + $p['view'] = $isActAsEligibilityGroupmember; + $p['patch'] = $isActAsEligibilityGroupmember; $this->set('permissions', $p); diff --git a/Controller/GrouperGroupsController.php b/Controller/GrouperGroupsController.php index edf0bcf..354c425 100644 --- a/Controller/GrouperGroupsController.php +++ b/Controller/GrouperGroupsController.php @@ -149,6 +149,9 @@ public function beforeRender() { // $this->set('vv_is_template_user', $this->GrouperGroup->isTemplateUser($this->userId ?? '', $cfg) ); // $this->set('vv_is_grouper_visible', $this->GrouperGroup->isGrouperVisible($this->userId ?? '', $cfg)); $this->set('vv_coid', $this->cur_co['Co']['id']); + + $roles = $this->Role->calculateCMRoles(); + $this->set('vv_copersonid', $roles['copersonid'] ?? null); } /** diff --git a/Model/GrouperLiteActAsPerson.php b/Model/ActAsPerson.php similarity index 74% rename from Model/GrouperLiteActAsPerson.php rename to Model/ActAsPerson.php index 4f833e4..15d6299 100644 --- a/Model/GrouperLiteActAsPerson.php +++ b/Model/ActAsPerson.php @@ -1,6 +1,6 @@ <?php /** - * COmanage Registry Grouper Lite GrouperLiteActAsPerson Model + * COmanage Registry Grouper Lite ActAsPerson Model * * Portions licensed to the University Corporation for Advanced Internet * Development, Inc. ("UCAID") under one or more contributor license agreements. @@ -25,21 +25,21 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -class GrouperLiteActAsPerson extends AppModel +class ActAsPerson extends AppModel { - public $name = 'GrouperLiteActAsPerson'; + public $name = 'ActAsPerson'; public $cmPluginHasMany = [ - "CoGrouperLiteWidget" => ["GrouperLiteActAsPerson"], - 'CoPerson' => [ - 'GrouperLiteActAsPerson' => [ - 'className' => 'GrouperLiteActAsPerson', - 'foreignKey' => 'actor_co_person_id' + 'CoGrouperLiteWidget' => ['ActAsPerson'], + 'CoPerson' => [ + 'ActAsPerson' => [ + 'className' => 'ActAsPerson', + 'foreignKey' => 'co_person_id' ] ], - 'CoPerson' => [ - 'GrouperLiteActAsPerson' => [ - 'className' => 'GrouperLiteActAsPerson', + 'CoPerson' => [ + 'ActAsPerson' => [ + 'className' => 'ActAsPerson', 'foreignKey' => 'act_as_co_person_id' ] ] @@ -47,15 +47,11 @@ class GrouperLiteActAsPerson extends AppModel // Association rules from this model to other models public $belongsTo = [ - 'GrouperLiteWidget', 'ActAsCoPerson' => [ 'className' => 'CoPerson', 'foreignKey' => 'act_as_co_person_id' ], - 'ActorCoPerson' => [ - 'className' => 'CoPerson', - 'foreignKey' => 'actor_co_person_id' - ], + 'CoPerson', 'CoGrouperLiteWidget' ]; @@ -71,7 +67,7 @@ class GrouperLiteActAsPerson extends AppModel 'required' => true, 'allowEmpty' => false ], - 'actor_co_person_id' => [ + 'co_person_id' => [ 'rule' => 'numeric', 'required' => true, 'allowEmpty' => false diff --git a/Model/GrouperGroup.php b/Model/GrouperGroup.php index 6f14364..a8f55b8 100644 --- a/Model/GrouperGroup.php +++ b/Model/GrouperGroup.php @@ -554,9 +554,9 @@ public function isGroupMember(string $userId, string $groupName, array $cfg): bo } /** - * Determine if User can use the Grouper Template to create a Working Group. + * Determine if a User can use the Grouper Template to create a Working Group. * - * @param string $userId Id of User + * @param string $userId User ID * @return string T for True and F for False * @throws GrouperLiteWidgetException * diff --git a/Model/GrouperLiteWidget.php b/Model/GrouperLiteWidget.php index 5c38153..d5b8aa3 100644 --- a/Model/GrouperLiteWidget.php +++ b/Model/GrouperLiteWidget.php @@ -39,7 +39,7 @@ class GrouperLiteWidget extends AppModel { public $belongsTo = []; public $hasMany = [ - 'GrouperLiteActAsPerson' => ['dependent' => true] + 'ActAsPerson' => ['dependent' => true] ]; // Validation rules for table elements diff --git a/View/Elements/actAsPeopleAutocomplete.ctp b/View/Elements/actAsPeopleAutocomplete.ctp index 0bf351e..67a0f85 100644 --- a/View/Elements/actAsPeopleAutocomplete.ctp +++ b/View/Elements/actAsPeopleAutocomplete.ctp @@ -14,7 +14,6 @@ $suffix = Configure::read('debug') > 0 ? '?time=' . time() : ''; import Autocomplete from '<?= $this->webroot ?>grouper_lite_widget/js/autocomplete.js<?= $suffix ?>'; import Loader from '<?= $this->webroot ?>grouper_lite_widget/js/loader.js<?= $suffix ?>'; - // XXX Probably move this to comanage.js const provided = { collapsed: <?= $vv_config['CoGrouperLiteWidget']['default_collapse'] == 'collapsed' ? 'true' : 'false' ?>, optAction: "<?= $optAction ?? 'none' ?>", @@ -78,6 +77,7 @@ $suffix = Configure::read('debug') > 0 ? '?time=' . time() : ''; api: { co: <?= $vv_coid ?>, glid: <?= $vv_config['CoGrouperLiteWidget']['id'] ?>, + coPersonId: <?= $vv_copersonid ?>, mode: "<?= PeoplePickerModeEnum::All ?>", base: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups", find: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/findSubscriber/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>", @@ -85,6 +85,7 @@ $suffix = Configure::read('debug') > 0 ? '?time=' . time() : ''; leave: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/leaveGroup/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>", remove: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/removeSubscriber/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>", add: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/addSubscriber/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>", + addActAs: "<?= $this->webroot ?>grouper_lite_widget/act_as_people/add/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>", group: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupSubscribers/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>", memberships: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/groupmemberapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>", managing: "<?= $this->webroot ?>grouper_lite_widget/grouper_groups/usermanagerapi/co:<?= $vv_coid ?>/glid:<?= $vv_config['CoGrouperLiteWidget']['id'] ?>", @@ -94,13 +95,10 @@ $suffix = Configure::read('debug') > 0 ? '?time=' . time() : ''; } const app = Vue.createApp({ - provide: provided, data() { return { loading: false, - search: '', - subscribers: [], - disabled: [], + rawData: [] } }, components: { @@ -109,14 +107,54 @@ $suffix = Configure::read('debug') > 0 ? '?time=' . time() : ''; }, inject: ['txt', 'api'], methods: { - addUser({ name }) { - console.log('test add user') + async addUser(user) { + const { identifier: ident, label, value: id } = user; + this.loading = true; + + // Create form + const formData = new FormData(); + formData.append("act_as_co_person_id", id); + formData.append("co_person_id", this.api.coPersonId); + formData.append("co_grouper_lite_widget_id", this.api.glid); + + // Request URL + const urlString = window.location.protocol + "//" + window.location.host + this.api.addActAs; + const url = new URL(urlString); + + // AJAX Request + const request = new Request(url, { + headers: new Headers({ + 'X-Requested-With': 'XMLHttpRequest', + "Accept": "application/json", + }), + method: "POST", + body: formData + }); + + // Fire request + const resp = await (fetch(request).catch(error => generateFlash('Network Error', 'error'))); + + if (!resp.ok) { + generateFlash('Enabling ActAs User failed', 'error'); + let errorResponse = await resp.json(); + generateFlash(`${errorResponse.message}`, 'error'); + this.loading = false; + return + } + generateFlash('Act As User Enabled', 'success'); + this.rawData = await resp.json(); + this.loading = false; + // Force reload here }, } }); app.config.unwrapInjectedRef = true; + // For core configurations and texts globally + for (const [key, value] of Object.entries(provided)) { + app.provide( key, value); + } // Mount the component and provide a global reference for this app instance. app.mount("#<?= $htmlId ?>-container"); </script>