-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
922 additions
and
267 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
216 changes: 216 additions & 0 deletions
216
app/plugins/OrcidSource/src/Controller/OrcidSourceCollectorsController.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,216 @@ | ||
| <?php | ||
| /** | ||
| * COmanage Registry Orcid Source Collectors Controller | ||
| * | ||
| * 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-plugins | ||
| * @since COmanage Registry v5.2.0 | ||
| * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) | ||
| */ | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace OrcidSource\Controller; | ||
|
|
||
| use App\Controller\StandardEnrollerController; | ||
| use App\Lib\Enum\PetitionActionEnum; | ||
| use Cake\Datasource\EntityInterface; | ||
| use Cake\Event\EventInterface; | ||
| use Cake\Http\Response; | ||
| use Cake\ORM\TableRegistry; | ||
| use Cake\Routing\RouteBuilder; | ||
| use Cake\Routing\Router; | ||
| use OrcidSource\Lib\Enum\OrcidSourceScopeEnum; | ||
|
|
||
| class OrcidSourceCollectorsController extends StandardEnrollerController { | ||
| public $paginate = [ | ||
| 'order' => [ | ||
| 'OrcidSourceCollectors.id' => 'asc' | ||
| ] | ||
| ]; | ||
|
|
||
| /** | ||
| * Callback run prior to the request render. | ||
| * | ||
| * @param EventInterface $event Cake Event | ||
| * | ||
| * @return Response|void | ||
| * @since COmanage Registry v5.2.0 | ||
| */ | ||
|
|
||
| public function beforeRender(EventInterface $event) { | ||
| $link = $this->getPrimaryLink(true); | ||
|
|
||
| if(!empty($link->value)) { | ||
| $this->set('vv_bc_parent_obj', $this->OrcidSourceCollectors->EnrollmentFlowSteps->get($link->value)); | ||
| $this->set('vv_bc_parent_displayfield', $this->OrcidSourceCollectors->EnrollmentFlowSteps->getDisplayField()); | ||
| $this->set('vv_bc_parent_primarykey', $this->OrcidSourceCollectors->EnrollmentFlowSteps->getPrimaryKey()); | ||
| } | ||
|
|
||
| return parent::beforeRender($event); | ||
| } | ||
|
|
||
| /** | ||
| * Dispatch an Enrollment Flow Step. | ||
| * | ||
| * @since COmanage Registry v5.2.0 | ||
| * @param string $id Env Source Collector ID | ||
| */ | ||
|
|
||
| public function dispatch(string $id) { | ||
| $request = $this->getRequest(); | ||
| $session = $request->getSession(); | ||
| $username = $session->read('Auth.external.user'); | ||
|
|
||
| $op = $this->requestParam('op'); | ||
| $code = $this->getRequest()->getQuery('code') ?? null; | ||
| $petition = $this->getPetition(); | ||
|
|
||
| $this->set('vv_op', $op); | ||
|
|
||
| $oricdSource = $this->OrcidSourceCollectors->get( | ||
| (int)$id, | ||
| [ | ||
| 'contain' => [ | ||
| 'ExternalIdentitySources' => ['OrcidSources' => ['Servers']] | ||
| ]] | ||
| ); | ||
|
|
||
| $ServerModel = $oricdSource->external_identity_source->orcid_source->server->plugin; | ||
| $PluginServers = $this->getTableLocator()->get($ServerModel); | ||
|
|
||
| $oauthServer = $this->Oauth2Servers->get($oricdSource->external_identity_source->orcid_source->server->id); | ||
|
|
||
| $this->set('vv_config', $oricdSource); | ||
| $this->set('controller', $this); | ||
|
|
||
|
|
||
| try { | ||
| // Let's authenticate first | ||
| $this->authenticate($id, $oricdSource, $code); | ||
|
|
||
| } | ||
| catch(\OverflowException $e) { | ||
| // The requested Source Key is already attached to an External Identity, so we throw | ||
| // an error now rather than wait until finalization | ||
|
|
||
| // Flag the Petition as a duplicate | ||
| $Petitions = TableRegistry::getTableLocator()->get("Petitions"); | ||
| } | ||
| catch(\Exception $e) { | ||
| $this->Flash->error($e->getMessage()); | ||
| } | ||
|
|
||
| // Fall through and let the form render | ||
|
|
||
| $this->render('/Standard/dispatch'); | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * Authenticate using OAuth2 Authorization Code flow. | ||
| * | ||
| * This method handles the OAuth2 authentication process by: | ||
| * 1. Building callback URL for the OAuth2 redirect | ||
| * 2. Redirecting to authorization endpoint on first access | ||
| * 3. Exchanging authorization code for access token on callback | ||
| * | ||
| * @param string|int $id Orcid Source Collector ID | ||
| * @param EntityInterface $oscfg Configuration array containing OAuth2 settings and OrgIdentitySource details | ||
| * @param string|null $code Authorization code returned from OAuth2 server (optional) | ||
| * @return void | ||
| * @since COmanage Registry v5.2.0 | ||
| */ | ||
| protected function authenticate(string|int $id, EntityInterface $oscfg, ?string $code): void | ||
| { | ||
| // We need a different callback URL than what the Oauth2Server config will | ||
| // use, since we're basically creating a runtime Authorization Code flow | ||
| // (while the main config uses a Client Credentials flow). | ||
|
|
||
| $callback = [ | ||
| 'plugin' => 'OrcidSource', | ||
| 'controller' => 'OrcidSourcesCollectors', | ||
| 'action' => 'dispatch', | ||
| $id, | ||
| '?' => ['osid' => $oscfg->id], | ||
| ]; | ||
|
|
||
| // Build the redirect URI | ||
| $redirectUri = Router::url($callback, true); | ||
|
|
||
| if (empty($code)) { | ||
| $scope = OrcidSourceScopeEnum::DEFAULT_SCOPE; | ||
| if (!empty($oscfg->scope_inherit)) { | ||
| $scope = $oscfg->scope_inherit; | ||
| } | ||
|
|
||
|
|
||
| // First time through, redirect to the "authorize" URL | ||
|
|
||
| $url = $oscfg->url . '/authorize?'; | ||
| $url .= 'client_id=' . $oscfg->clientid; | ||
| $url .= '&response_type=code'; | ||
| $url .= '&scope=' . str_replace(' ', '%20', $scope); | ||
| $url .= '&redirect_uri=' . urlencode($redirectUri); | ||
|
|
||
| $this->redirect($url); | ||
| } | ||
|
|
||
| // $response = $this->Oauth2Server->exchangeCode($cfg['Oauth2Server']['id'], | ||
| // $this->request->query['code'], | ||
| // $redirectUri, | ||
| // false); | ||
| } | ||
|
|
||
| /** | ||
| * Indicate whether this Controller will handle some or all authnz. | ||
| * | ||
| * @since COmanage Registry v5.2.0 | ||
| * @param EventInterface $event Cake event, ie: from beforeFilter | ||
| * @return string "no", "open", "authz", or "yes" | ||
| */ | ||
|
|
||
| public function willHandleAuth(\Cake\Event\EventInterface $event): string { | ||
| $request = $this->getRequest(); | ||
| $action = $request->getParam('action'); | ||
|
|
||
| if($action == 'dispatch') { | ||
| // We need to perform special logic (vs StandardEnrollerController) | ||
| // to ensure that web server authentication is triggered. | ||
| // (This is the same logic as IdentifierCollectorsController.) | ||
| // XXX We could maybe move this into StandardEnrollerController with a flag like | ||
| // $this->alwaysAuthDispatch(true); | ||
|
|
||
| // To start, we trigger the parent logic. This will return | ||
| // notauth: Some error occurred, we don't want to override this | ||
| // authz: No token in use | ||
| // yes: Token validated | ||
|
|
||
| $auth = parent::willHandleAuth($event); | ||
|
|
||
| // The only status we need to override is 'yes', since we always want authentication | ||
| // to run in order to be able to grab $REMOTE_USER. | ||
|
|
||
| return ($auth == 'yes' ? 'authz' : $auth); | ||
| } | ||
|
|
||
| return parent::willHandleAuth($event); | ||
| } | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.