From 357e5c9ea2be8871310f01dc26ab556d23538ffe Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Fri, 2 May 2025 22:16:26 +0300 Subject: [PATCH] dispatch... --- .../resources/locales/en_US/orcid_source.po | 8 ++ .../OrcidSourceCollectorsController.php | 112 ++++++++++-------- .../src/Model/Table/OrcidSourcesTable.php | 17 ++- .../OrcidSourceCollectors/dispatch.inc | 50 ++++---- .../OrcidSource/webroot/css/orcid-source.css | 21 ++++ .../OrcidSource/webroot/img/orcid_128x128.png | Bin 0 -> 1090 bytes 6 files changed, 129 insertions(+), 79 deletions(-) create mode 100644 app/plugins/OrcidSource/webroot/css/orcid-source.css create mode 100644 app/plugins/OrcidSource/webroot/img/orcid_128x128.png diff --git a/app/plugins/OrcidSource/resources/locales/en_US/orcid_source.po b/app/plugins/OrcidSource/resources/locales/en_US/orcid_source.po index cf2fab0d3..a19d45509 100644 --- a/app/plugins/OrcidSource/resources/locales/en_US/orcid_source.po +++ b/app/plugins/OrcidSource/resources/locales/en_US/orcid_source.po @@ -72,3 +72,11 @@ msgstr "Obtained ORCID {0} via authenticated OAuth flow" msgid "information.orcid_source.identifier" msgstr "ORCID Identifier" + +msgid "information.OrcidSourceCollectors.authenticate" +msgstr "Authenticate with ORCID" + +msgid "information.OrcidSourceCollectors.sign_in" +msgstr "Sign in with your ORCID account to securely verify your ORCID iD." + + diff --git a/app/plugins/OrcidSource/src/Controller/OrcidSourceCollectorsController.php b/app/plugins/OrcidSource/src/Controller/OrcidSourceCollectorsController.php index b824e9e31..880e01872 100644 --- a/app/plugins/OrcidSource/src/Controller/OrcidSourceCollectorsController.php +++ b/app/plugins/OrcidSource/src/Controller/OrcidSourceCollectorsController.php @@ -40,12 +40,27 @@ use OrcidSource\Lib\Enum\OrcidSourceScopeEnum; class OrcidSourceCollectorsController extends StandardEnrollerController { + protected $OrcidSources; + public $paginate = [ 'order' => [ 'OrcidSourceCollectors.id' => 'asc' ] ]; + /** + * Callback run prior to the request action. + * + * @since COmanage Registry v5.2.0 + * @param EventInterface $event Cake Event + */ + public function beforeFilter(\Cake\Event\EventInterface $event) + { + $this->OrcidSources = TableRegistry::getTableLocator()->get('OrcidSource.OrcidSources'); + + return parent::beforeFilter($event); + } + /** * Callback run prior to the request render. * @@ -85,7 +100,7 @@ public function dispatch(string $id) { $this->set('vv_op', $op); - $oricdSource = $this->OrcidSourceCollectors->get( + $oricdSourceEntity = $this->OrcidSourceCollectors->get( (int)$id, [ 'contain' => [ @@ -93,18 +108,38 @@ public function dispatch(string $id) { ]] ); - $ServerModel = $oricdSource->external_identity_source->orcid_source->server->plugin; - $PluginServers = $this->getTableLocator()->get($ServerModel); + $ServerModel = $oricdSourceEntity->external_identity_source->orcid_source->server->plugin; + $PluginServersTable = TableRegistry::getTableLocator()->get($ServerModel); + $serverId = $oricdSourceEntity->external_identity_source->orcid_source->server->id; + $PluginServerEntity = $PluginServersTable ->find() + ->where(['server_id' => $serverId]) + ->first(); - $oauthServer = $this->Oauth2Servers->get($oricdSource->external_identity_source->orcid_source->server->id); - $this->set('vv_config', $oricdSource); + $this->set('vv_config', $oricdSourceEntity); + $this->set('vv_config_server', $PluginServerEntity); $this->set('controller', $this); - try { // Let's authenticate first - $this->authenticate($id, $oricdSource, $code); + if ($op == 'authenticate') { + $this->authenticate($id, $PluginServerEntity); + } else if (!empty($code)) { + $response = $PluginServersTable->exchangeCode( + $id, + $code, + $this->OrcidSources->redirectUri( + [ + $id, + '?' => ['petition_id' => $petition->id], + ] + ), + ); + + // Use the response and save the data to petitions table + } else { + // Fall Through. Let the view render + } } catch(\OverflowException $e) { @@ -125,58 +160,37 @@ public function dispatch(string $id) { /** - * Authenticate using OAuth2 Authorization Code flow. + * Authenticate the user with ORCID OAuth2 server * - * 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) + * @param string|int $id ID of the collector + * @param EntityInterface $serverCfg ORCID Server configuration * @return void - * @since COmanage Registry v5.2.0 + * @throws \Exception If authentication fails + * @throws \OverflowException If source key is already attached + * @since COmanage Registry v5.2.0 */ - protected function authenticate(string|int $id, EntityInterface $oscfg, ?string $code): void + protected function authenticate(string|int $id, EntityInterface $serverCfg): 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', + $petition = $this->getPetition(); + $callback = $this->OrcidSources->redirectUri([ $id, - '?' => ['osid' => $oscfg->id], - ]; - + '?' => ['petition_id' => $petition->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); + $scope = OrcidSourceScopeEnum::DEFAULT_SCOPE; + if (!empty($serverCfg->scope_inherit)) { + $scope = $serverCfg->scope_inherit; } -// $response = $this->Oauth2Server->exchangeCode($cfg['Oauth2Server']['id'], -// $this->request->query['code'], -// $redirectUri, -// false); + $url = $serverCfg->url . '/authorize?'; + $url .= 'client_id=' . $serverCfg->clientid; + $url .= '&response_type=code'; + $url .= '&scope=' . str_replace(' ', '%20', $scope); + $url .= '&redirect_uri=' . urlencode($redirectUri); + + $this->redirect($url); } /** diff --git a/app/plugins/OrcidSource/src/Model/Table/OrcidSourcesTable.php b/app/plugins/OrcidSource/src/Model/Table/OrcidSourcesTable.php index 72ab0c3b1..7070ca925 100644 --- a/app/plugins/OrcidSource/src/Model/Table/OrcidSourcesTable.php +++ b/app/plugins/OrcidSource/src/Model/Table/OrcidSourcesTable.php @@ -1,6 +1,6 @@ 'OrcidSource', @@ -153,6 +156,10 @@ public function redirectUri(): string 'action' => 'dispatch', ]; + if (!empty($extra)) { + $callback = array_merge($callback, $extra); + } + return Router::url($callback, true); } @@ -194,7 +201,7 @@ public function inventory( * * @since COmanage Registry v5.2.0 * @param OrcidSource $OrcidSource OrcidSource configuration entity - * @param array $result Array of Env attributes + * @param array $result Array of Orcid attributes * @return array Entity record (in array format) */ diff --git a/app/plugins/OrcidSource/templates/OrcidSourceCollectors/dispatch.inc b/app/plugins/OrcidSource/templates/OrcidSourceCollectors/dispatch.inc index 21f13cbc3..ac5f61145 100644 --- a/app/plugins/OrcidSource/templates/OrcidSourceCollectors/dispatch.inc +++ b/app/plugins/OrcidSource/templates/OrcidSourceCollectors/dispatch.inc @@ -31,34 +31,34 @@ declare(strict_types = 1); if($vv_action !== 'dispatch') { return; } + +// Load view dependencies +$this->Html->css('OrcidSource/orcid-source', ['block' => true]); + // Make the Form fields editable $this->Field->enableFormEditMode(); -ksort($vv_orcid_source_vars); -$previousKey = ''; + +// The first time we will suppress default submit +$suppress_submit = true; +$btnAuthenticateLabel = '' + . __d('orcid_source', 'information.OrcidSourceCollectors.authenticate'); + +print $this->Form->hidden('op', ['value' => 'authenticate']); + // Render the parsed variables ?>
- ORCID logo -

Authenticate with ORCID

-

Sign in with your ORCID account to securely verify your ORCID iD.

- -
+ Html->image('OrcidSource.orcid_128x128.png', ['alt' => 'Logo', 'class' => 'mb-3']) ?> +

+

+ Form->button( + $btnAuthenticateLabel, + [ + 'escapeTitle' => false, + 'type' => 'submit', + 'class' => 'spin submit-button btn btn-primary d-flex mx-auto', + ] + ) + ?> +
- - \ No newline at end of file diff --git a/app/plugins/OrcidSource/webroot/css/orcid-source.css b/app/plugins/OrcidSource/webroot/css/orcid-source.css new file mode 100644 index 000000000..6b4e72ce3 --- /dev/null +++ b/app/plugins/OrcidSource/webroot/css/orcid-source.css @@ -0,0 +1,21 @@ +.text-center img { + width: 72px; +} + +.text-center h2 { + color: #68b245; +} + +#orcid-auth-btn { + color: white; + font-weight: bolder; +} + +.material-symbols-outlined { + font-size: 22px; + vertical-align: middle; +} + +#orcid-result { + color: #198754; +} diff --git a/app/plugins/OrcidSource/webroot/img/orcid_128x128.png b/app/plugins/OrcidSource/webroot/img/orcid_128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..484207317d1e6a078df9a8cab6bf7c57dc6d68dc GIT binary patch literal 1090 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&B?tI~xB}^A=PZdw|NsC0`RDVO zpU>WXyY=$(xyK(4-g~?C#;X;VpU*k_c*5}q&4=!m@41z|{d(NSD?w{6x&lq!DqJoA zv__yL$S;^dK*7KvAfce4fByRY=kLE)mTKx^U|_EEba4!+xOH~+-A#)OcpALf^TV#J%yZ%b}$uX-N2O=kH z`;}xi9+@_4^;a&Yl@c;t%r1o*Ax@h%wPn0A^1iyK@Pp8~ls9KTYm1ofagAM3enITs zv8=B~Y?BhMWWV4NX!N^b>Ctw3WyZG&Q}%W#uU0S&U8eM7m7?X>aF^eF5(V*wZ@s17 zH1x(^_|NXPZ^Pl?r6<0T8b;_I((`}yoiWLWAi<}bO$ z$q)WXY-MJVoNXQM(R4Xbn8EMtT+T}gkI&g_7%&;kn`knD$#{v=YImI+1Hod2iwYte zTHhD2ObR@r)A-MfBmEld#RJBAk1Z1a7oRzN=3slFclkf<-Pn|te-{IZ5*#ywgM_KJ0qyV(|+eSH7z zvkTLS(j$Ee=L#+JS~yt*?9EO%<#d`YWGFh?nDO_s=YvUH3eLsL+kNK*NzGtM;E-fl zTV%#)@?zdur^D(Gtaowu-1^LUph(=pcIWD7H%5sQ)>EH~?wF*#DYP$`p(;ztiggWB z@n?2^X#?(xKYS@H4EfiTn10Ce1TiVEV=-ddyyd{B{Ty3@n8a7HKT%)!Skyw8$uII| z>j@+7idO}Bk^Cwa?6XThJ0wN0R=v_T(Ryw>At2guoylT`V^(_pdN2C?AKWrC@7vJ$ zc*iV7TgjIjc%}!ZEXr?J`}|o2gz;HZ^K#)#s043cgXi zSF3_$m#IZXq%p@9VaZL7r=Bn!zj&NwtTH!=E6`b)(cz+&r=>KtTY7o(q?;~A-t~;; zGtQ}-@oIgX;`ee%*vl<(FOQ_Xyps3wN!iOUbuXFNUkdR*R1$w_B!AOsxfl2JDo^p< zoYQ}Mira8aui+BkdusaMQ{r}~r`P@efAsyMr~mgevfjVhD7+;|5130CJYD@<);T3K F0RSEm@=E{! literal 0 HcmV?d00001