[FEATURE] Wizard to add OpenID to backend user 21/21621/13
authorChristian Weiske <cweiske@cweiske.de>
Sun, 23 Jun 2013 19:08:07 +0000 (21:08 +0200)
committerStefan Neufeind <typo3.neufeind@speedpartner.de>
Thu, 17 Oct 2013 08:38:54 +0000 (10:38 +0200)
Adds an OpenID wizard button to the be_user's tx_openid_openid field.

The wizard allows to enter an OpenID URL, processes the OpenID login
and finally sets the OpenID in the backend user edit form and
backend user settings form.

This helps registering OpenIDs of providers that hand out different
claimed OpenID URLs for each domain, like Google does.

Resolves: #49310
Releases: 6.2
Change-Id: I953bcfc0df640dc7632f4b78b43f7945606cb7e9
Reviewed-on: https://review.typo3.org/21621
Reviewed-by: Philipp Gampe
Tested-by: Philipp Gampe
Reviewed-by: Helmut Hummel
Tested-by: Fabien Udriot
Reviewed-by: Stefan Neufeind
Tested-by: Stefan Neufeind
typo3/sysext/openid/Classes/OpenidModuleSetup.php
typo3/sysext/openid/Classes/Wizard.php [new file with mode: 0644]
typo3/sysext/openid/Resources/Private/Language/Wizard.xlf [new file with mode: 0644]
typo3/sysext/openid/Resources/Private/Templates/Wizard/Content.html [new file with mode: 0644]
typo3/sysext/openid/Resources/Public/StyleSheets/Wizard.css [new file with mode: 0644]
typo3/sysext/openid/ext_tables.php
typo3/sysext/openid/wizard/conf.php [new file with mode: 0644]
typo3/sysext/openid/wizard/index.php [new file with mode: 0644]

index c67421f..caa77a7 100644 (file)
@@ -53,7 +53,23 @@ class OpenidModuleSetup {
         */
        public function renderOpenID(array $parameters, \TYPO3\CMS\Setup\Controller\SetupModuleController $parent) {
                $openid = $GLOBALS['BE_USER']->user['tx_openid_openid'];
-               return '<input id="field_tx_openid_openid"' . $GLOBALS['TBE_TEMPLATE']->formWidth(20) . ' type="text" name="data[be_users][tx_openid_openid]"' . ' value="' . htmlspecialchars($openid) . '" />';
+               $add = htmlspecialchars(
+                       $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:addopenid')
+               );
+
+               return '<input id="field_tx_openid_openid"' .
+                       $GLOBALS['TBE_TEMPLATE']->formWidth(20) .
+                       ' type="text" name="data[be_users][tx_openid_openid]"' .
+                       ' value="' . htmlspecialchars($openid) . '" />' .
+                       '&nbsp;&nbsp;<a href="#" onclick="' .
+                       'vHWin=window.open(\'../typo3/mod.php\?' .
+                       'M=openid_wizard&' .
+                       'P[itemName]=data%5Bbe_users%5D%5Btx_openid_openid%5D\'' .
+                       ',null,\'width=600,height=400,status=0,menubar=0,scrollbars=0\');' .
+                       'vHWin.focus();return false;' .
+                       '">' .
+                       '<img src="../typo3/sysext/openid/ext_icon.gif" alt="' . $add . '" title="' . $add . '"/>' .
+                       '</a>';
        }
 
 }
diff --git a/typo3/sysext/openid/Classes/Wizard.php b/typo3/sysext/openid/Classes/Wizard.php
new file mode 100644 (file)
index 0000000..cd86f1f
--- /dev/null
@@ -0,0 +1,218 @@
+<?php
+namespace TYPO3\CMS\Openid;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Christian Weiske <cweiske@cweiske.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Authentication\AbstractUserAuthentication;
+
+/**
+ * OpenID selection wizard for the backend
+ *
+ * @author Christian Weiske <cweiske@cweiske.de>
+ */
+class Wizard extends OpenidService {
+       /**
+        * OpenID of the user after authentication
+        *
+        * @var string
+        */
+       protected $claimedId;
+
+       /**
+        * Name of the form element this wizard should write the OpenID into
+        *
+        * @var string
+        */
+       protected $parentFormItemName;
+
+       /**
+        * Name of the function that needs to be called after setting the value
+        *
+        * @var string
+        */
+       protected $parentFormFieldChangeFunc;
+
+       /**
+        * Run the wizard and output HTML.
+        *
+        * @return void
+        */
+       public function main() {
+               $p = GeneralUtility::_GP('P');
+               if (isset($p['itemName'])) {
+                       $this->parentFormItemName = $p['itemName'];
+               }
+               if (isset($p['fieldChangeFunc']['TBE_EDITOR_fieldChanged'])) {
+                       $this->parentFormFieldChangeFunc = $p['fieldChangeFunc']['TBE_EDITOR_fieldChanged'];
+               }
+
+               if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('tx_openid_mode') === 'finish'
+                       && $this->openIDResponse === NULL
+               ) {
+                       $this->includePHPOpenIDLibrary();
+                       $openIdConsumer = $this->getOpenIDConsumer();
+                       $this->openIDResponse = $openIdConsumer->complete($this->getReturnUrl());
+                       $this->handleResponse();
+                       $this->renderHtml();
+                       return;
+               } elseif (GeneralUtility::_POST('openid_url') != '') {
+                       $this->openIDIdentifier = GeneralUtility::_POST('openid_url');
+                       $this->sendOpenIDRequest();
+
+                       // When sendOpenIDRequest() returns, there was an error
+                       $flashMessageService = GeneralUtility::makeInstance(
+                               'TYPO3\\CMS\\Core\\Messaging\\FlashMessageService'
+                       );
+                       $flashMessage = GeneralUtility::makeInstance(
+                               'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                               sprintf(
+                                       $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:error.setup'),
+                                       htmlspecialchars($this->openIDIdentifier)
+                               ),
+                               $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:title.error'),
+                               \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
+                       );
+                       $flashMessageService->getMessageQueueByIdentifier()->enqueue($flashMessage);
+               }
+               $this->renderHtml();
+       }
+
+       /**
+        * Return URL to this wizard
+        *
+        * @return string Full URL with protocol and hostname
+        */
+       protected function getSelfUrl() {
+               return GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir .
+                       $GLOBALS['MCONF']['_'];
+       }
+
+       /**
+        * Return URL that shall be called by the OpenID server
+        *
+        * @return string Full URL with protocol and hostname
+        */
+       protected function getReturnUrl() {
+               return $this->getSelfURL() .
+                       '&tx_openid_mode=finish' .
+                       '&P[itemName]=' . urlencode($this->parentFormItemName) .
+                       '&P[fieldChangeFunc][TBE_EDITOR_fieldChanged]]=' . urlencode($this->parentFormFieldChangeFunc);
+       }
+
+       /**
+        * Check OpenID response and set flash messages depending on its state
+        *
+        * @return void
+        *
+        * @uses $openIDResponse
+        */
+       protected function handleResponse() {
+               /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
+               $flashMessageService = GeneralUtility::makeInstance(
+                       'TYPO3\\CMS\\Core\\Messaging\\FlashMessageService'
+               );
+               $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
+
+               if (!$this->openIDResponse instanceof \Auth_OpenID_ConsumerResponse) {
+                       $flashMessage = GeneralUtility::makeInstance(
+                               'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                               $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:error.no-response'),
+                               $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:title.error'),
+                               \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
+                       );
+               } elseif ($this->openIDResponse->status == Auth_OpenID_SUCCESS) {
+                       // all fine
+                       $this->claimedId = $this->getSignedParameter('openid_claimed_id');
+                       $flashMessage = GeneralUtility::makeInstance(
+                               'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                               sprintf(
+                                       $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:youropenid'),
+                                       htmlspecialchars($this->claimedId)
+                               ),
+                               $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:title.success'),
+                               \TYPO3\CMS\Core\Messaging\FlashMessage::OK
+                       );
+               } elseif ($this->openIDResponse->status == Auth_OpenID_CANCEL) {
+                       $flashMessage = GeneralUtility::makeInstance(
+                               'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                               $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:error.cancelled'),
+                               $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:title.error'),
+                               \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
+                       );
+               } else {
+                       // another failure. show error message and form again
+                       $flashMessage = GeneralUtility::makeInstance(
+                               'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                               sprintf(
+                                       $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:error.general'),
+                                       htmlspecialchars($this->openIDResponse->status),
+                                       htmlspecialchars($this->openIDResponse->message)
+                               ),
+                               $GLOBALS['LANG']->sL('LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:title.error'),
+                               \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
+                       );
+               }
+
+               $defaultFlashMessageQueue->enqueue($flashMessage);
+       }
+
+       /**
+        * Render HTML with messagse and OpenID form and output it
+        *
+        * @return void
+        */
+       protected function renderHtml() {
+               // use FLUID standalone view for wizard content
+               $view = GeneralUtility::makeInstance('TYPO3\\CMS\\Fluid\\View\\StandaloneView');
+               $view->setTemplatePathAndFilename(
+                       \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('openid') .
+                       'Resources/Private/Templates/Wizard/Content.html'
+               );
+
+               /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
+               $flashMessageService = GeneralUtility::makeInstance(
+                       'TYPO3\\CMS\\Core\\Messaging\\FlashMessageService'
+               );
+               $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
+               $messages = array();
+               foreach ($defaultFlashMessageQueue->getAllMessagesAndFlush() as $message) {
+                       $messages[] = $message->render();
+               }
+               $view->assign('messages', $messages);
+               $view->assign('formAction', htmlspecialchars($this->getSelfURL()));
+               $view->assign('claimedId', $this->claimedId);
+               $view->assign('parentFormItemName', $this->parentFormItemName);
+               $view->assign('parentFormItemNameNoHr', strtr($this->parentFormItemName, array('_hr' => '')));
+               $view->assign('parentFormFieldChangeFunc', $this->parentFormFieldChangeFunc);
+               $view->assign('showForm', TRUE);
+               if (isset($_REQUEST['openid_url'])) {
+                       $view->assign('openid_url', $_REQUEST['openid_url']);
+               }
+
+               header('HTTP/1.0 200 OK');
+               echo $view->render();
+       }
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/openid/Resources/Private/Language/Wizard.xlf b/typo3/sysext/openid/Resources/Private/Language/Wizard.xlf
new file mode 100644 (file)
index 0000000..2a86242
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.0">
+       <file source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:35Z" product-name="openid">
+               <header/>
+               <body>
+                       <trans-unit id="title.error" xml:space="preserve">
+                               <source>Error during OpenID authentication</source>
+                       </trans-unit>
+                       <trans-unit id="title.success" xml:space="preserve">
+                               <source>OpenID authentication successful</source>
+                       </trans-unit>
+                       <trans-unit id="error.cancelled" xml:space="preserve">
+                               <source>OpenID authentication has been cancelled.</source>
+                       </trans-unit>
+                       <trans-unit id="error.general" xml:space="preserve">
+                               <source><![CDATA[Status: %s<br/>Message: %s]]></source>
+                       </trans-unit>
+                       <trans-unit id="error.no-response" xml:space="preserve">
+                               <source>We got no OpenID response.</source>
+                       </trans-unit>
+                       <trans-unit id="error.setup" xml:space="preserve">
+                               <source>Error setting up OpenID authentication for "%s".</source>
+                       </trans-unit>
+                       <trans-unit id="youropenid" xml:space="preserve">
+                               <source><![CDATA[OpenID is: <tt>%s</tt>]]></source>
+                       </trans-unit>
+
+                       <trans-unit id="addopenid" xml:space="preserve">
+                               <source>Add OpenID</source>
+                       </trans-unit>
+
+                       <trans-unit id="html.title" xml:space="preserve">
+                               <source>OpenID registration</source>
+                       </trans-unit>
+                       <trans-unit id="html.description" xml:space="preserve">
+                               <source>Add an OpenID to your backend user. This OpenID can then be used to log in the TYPO3 backend.</source>
+                       </trans-unit>
+                       <trans-unit id="html.openid_url" xml:space="preserve">
+                               <source>OpenID identifier</source>
+                       </trans-unit>
+                       <trans-unit id="html.submit" xml:space="preserve">
+                               <source>Login</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
\ No newline at end of file
diff --git a/typo3/sysext/openid/Resources/Private/Templates/Wizard/Content.html b/typo3/sysext/openid/Resources/Private/Templates/Wizard/Content.html
new file mode 100644 (file)
index 0000000..8341b0d
--- /dev/null
@@ -0,0 +1,46 @@
+<f:be.container pageTitle="{f:translate(key:'LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:html.title')}"
+       includeCssFiles="{
+               0:'{f:uri.resource(extensionName:\'openid\', path:\'StyleSheets/Wizard.css\')}'
+       }"
+>
+       <h1><f:translate key="LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:html.title" /></h1>
+
+       <p><f:translate key="LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:html.description" /></p>
+
+       <f:if condition="{messages->f:count()} > 0">
+               <f:for each="{messages}" as="message">
+                       <f:format.raw>{message}</f:format.raw>
+               </f:for>
+       </f:if>
+       <f:if condition="{claimedId}">
+               <script type="text/javascript">
+                       var form;
+                       if (window.opener.document.editform) {
+                               //normal TCE edit form
+                               <f:if condition="{parentFormItemNameNoHr}">
+                               window.opener.document.editform["{parentFormItemNameNoHr}"].value="{claimedId}";
+                               </f:if>
+                               window.opener.document.editform["{parentFormItemName}"].value="{claimedId}";
+                               <f:if condition="{parentFormFieldChangeFunc}">
+                               window.opener.{parentFormFieldChangeFunc}
+                               </f:if>
+                       } else if (window.opener.document.usersetup) {
+                               //backend user settings
+                               window.opener.document.usersetup["{parentFormItemName}"].value="{claimedId}";
+                       }
+                       window.close();
+               </script>
+       </f:if>
+
+       <f:if condition="{showForm}">
+               <form method="post" action="{formAction}">
+                       <input type="hidden" name="P[itemName]" value="{parentFormItemName}"/>
+                       <input type="hidden" name="P[fieldChangeFunc][TBE_EDITOR_fieldChanged]" value="{parentFormFieldChangeFunc}"/>
+
+                       <label for="openid_url"><f:translate key="LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:html.openid_url" /></label>
+                       <input type="text" name="openid_url" id="openid_url" value="{openid_url}"/>
+
+                       <input type="submit" value="{f:translate(key:'LLL:EXT:openid/Resources/Private/Language/Wizard.xlf:html.submit')}"/>
+               </form>
+       </f:if>
+</f:be.container>
diff --git a/typo3/sysext/openid/Resources/Public/StyleSheets/Wizard.css b/typo3/sysext/openid/Resources/Public/StyleSheets/Wizard.css
new file mode 100644 (file)
index 0000000..6f3ddae
--- /dev/null
@@ -0,0 +1,9 @@
+body {
+       padding: 5px;
+}
+#openid_url {
+       background-image: url('../../../ext_icon.gif');
+       background-position: left 50%; /* LTR */
+       background-repeat: no-repeat;
+       padding-left: 20px;
+}
index f04242e..5515a11 100644 (file)
@@ -12,7 +12,17 @@ $tempColumns = array(
                        'type' => 'input',
                        'size' => '30',
                        // Requirement: unique (BE users are unique in the whole system)
-                       'eval' => 'trim,nospace,unique'
+                       'eval' => 'trim,nospace,unique',
+                       'wizards' => Array(
+                               '_PADDING' => 2,
+                               '0' => Array(
+                                       'type' => 'popup',
+                                       'title' => 'Add OpenID',
+                                       'script' => 'mod.php?M=openid_wizard',
+                                       'icon' => 'EXT:openid/ext_icon.gif',
+                                       'JSopenParams' => ',width=600,height=400,status=0,menubar=0,scrollbars=0',
+                               )
+                       ),
                )
        )
 );
@@ -37,3 +47,11 @@ $GLOBALS['TYPO3_USER_SETTINGS']['columns']['tx_openid_openid'] = array(
 );
 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToUserSettings('tx_openid_openid', 'after:password2');
 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('_MOD_user_setup', 'EXT:openid/locallang_csh_mod.xlf');
+
+if (TYPO3_MODE === 'BE') {
+       // Register wizard
+       \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModulePath(
+               'openid_wizard',
+               \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY) . 'wizard/'
+       );
+}
diff --git a/typo3/sysext/openid/wizard/conf.php b/typo3/sysext/openid/wizard/conf.php
new file mode 100644 (file)
index 0000000..483b160
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+//required for mod.php
+$MCONF['name'] = 'openid_wizard';
+$MCONF['script'] = '_DISPATCH';
+$MCONF['access'] = '';
+?>
diff --git a/typo3/sysext/openid/wizard/index.php b/typo3/sysext/openid/wizard/index.php
new file mode 100644 (file)
index 0000000..832d87b
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Christian Weiske <cweiske@cweiske.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+define('TYPO3_MOD_PATH', 'sysext/openid/wizard/');
+
+$wizard = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+       'TYPO3\\CMS\\Openid\\Wizard'
+);
+$wizard->main();
+?>
\ No newline at end of file