xref: /plugin/oauth/action/login.php (revision 1fad69881620f751e369f4d6dbf68f887944376e)
1<?php
2
3use dokuwiki\Form\Form;
4use dokuwiki\plugin\oauth\SessionManager;
5use OAuth\Common\Http\Exception\TokenResponseException;
6
7/**
8 * DokuWiki Plugin oauth (Action Component)
9 *
10 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11 * @author  Andreas Gohr <andi@splitbrain.org>
12 */
13class action_plugin_oauth_login extends DokuWiki_Action_Plugin
14{
15    /** @var helper_plugin_oauth */
16    protected $hlp;
17
18    /**
19     * Constructor
20     *
21     * Initializes the helper
22     */
23    public function __construct()
24    {
25        $this->hlp = plugin_load('helper', 'oauth');
26    }
27
28    /**
29     * Registers a callback function for a given event
30     *
31     * @param Doku_Event_Handler $controller DokuWiki's event controller object
32     * @return void
33     */
34    public function register(Doku_Event_Handler $controller)
35    {
36        global $conf;
37        if ($conf['authtype'] != 'oauth') return;
38
39        $conf['profileconfirm'] = false; // password confirmation doesn't work with oauth only users
40
41        $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'handleStart');
42        $controller->register_hook('HTML_LOGINFORM_OUTPUT', 'BEFORE', $this, 'handleOldLoginForm'); // @deprecated
43        $controller->register_hook('FORM_LOGIN_OUTPUT', 'BEFORE', $this, 'handleLoginForm');
44        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleDoLogin');
45    }
46
47    /**
48     * Start an oAuth login or restore  environment after successful login
49     *
50     * @param Doku_Event $event
51     * @return void
52     */
53    public function handleStart(Doku_Event $event)
54    {
55        global $INPUT;
56
57        // login has been done, but there's environment to be restored
58        // TODO when is this the case?
59        $sessionManager = SessionManager::getInstance();
60        if ($sessionManager->getDo() || $sessionManager->getRev()) {
61            $this->restoreSessionEnvironment();
62            return;
63        }
64
65        // see if a login needs to be started
66        $servicename = $INPUT->str('oauthlogin');
67        if ($servicename) $this->startOAuthLogin($servicename);
68    }
69
70    /**
71     * Add the oAuth login links to login form
72     *
73     * @param Doku_Event $event event object by reference
74     * @deprecated can be removed in the future
75     * @return void
76     */
77    public function handleOldLoginForm(Doku_Event $event)
78    {
79        /** @var Doku_Form $form */
80        $form = $event->data;
81        $html = $this->prepareLoginButtons();
82        if (!$html) return;
83
84        $form->_content[] = form_openfieldset(
85            [
86                '_legend' => $this->getLang('loginwith'),
87                'class' => 'plugin_oauth',
88            ]
89        );
90        $form->_content[] = $html;
91        $form->_content[] = form_closefieldset();
92    }
93
94
95    /**
96     * Add the oAuth login links to login form
97     *
98     * @param Doku_Event $event event object by reference
99     * @deprecated can be removed in the future
100     * @return void
101     */
102    public function handleLoginForm(Doku_Event $event)
103    {
104        /** @var Form $form */
105        $form = $event->data;
106        $html = $this->prepareLoginButtons();
107        if (!$html) return;
108
109        $form->addFieldsetOpen($this->getLang('loginwith'))->addClass('plugin_oauth');
110        $form->addHTML($html);
111        $form->addFieldsetClose();
112    }
113
114    /**
115     * Create HTML for the various login buttons
116     *
117     * @return string the HTML
118     */
119    protected function prepareLoginButtons() {
120        $html = '';
121
122        $validDomains = $this->hlp->getValidDomains();
123
124        if (count($validDomains) > 0) {
125            $html .= sprintf($this->getLang('eMailRestricted'), join(', ', $validDomains));
126        }
127
128        foreach ($this->hlp->listServices() as $service) {
129            $html .= $service->loginButton();
130        }
131
132        return $html;
133    }
134
135    /**
136     * When singleservice is wanted, do not show login, but execute login right away
137     *
138     * @param Doku_Event $event
139     * @return bool
140     */
141    public function handleDoLogin(Doku_Event $event)
142    {
143        global $ID;
144
145        if ($event->data != 'login') return true;
146
147        $singleService = $this->getConf('singleService');
148        if (!$singleService) return true;
149
150        $enabledServices = $this->hlp->listServices();
151        if (count($enabledServices) !== 1) {
152            msg($this->getLang('wrongConfig'), -1);
153            return false;
154        }
155
156        $service = array_shift($enabledServices);
157
158        $url = wl($ID, ['oauthlogin' => $service->getServiceID()], true, '&');
159        send_redirect($url);
160        return true; // never reached
161    }
162
163    /**
164     * start the oauth login
165     *
166     * This will redirect to the external service and stop processing in this request.
167     * The second part of the login will happen in auth
168     *
169     * @see auth_plugin_oauth
170     */
171    protected function startOAuthLogin($servicename)
172    {
173        global $ID;
174        $service = $this->hlp->loadService($servicename);
175        if (is_null($service)) return;
176
177        // remember service in session
178        $sessionManager = SessionManager::getInstance();
179        $sessionManager->setServiceName($servicename);
180        $sessionManager->setPid($ID);
181        $sessionManager->saveState();
182
183        try {
184            $service->login(); // redirects
185        } catch (TokenResponseException $e) {
186            $this->hlp->showException($e, 'login failed');
187        }
188    }
189
190    /**
191     * Restore the request environment that had been set before the oauth shuffle
192     */
193    protected function restoreSessionEnvironment()
194    {
195        global $INPUT, $ACT, $TEXT, $PRE, $SUF, $SUM, $RANGE, $DATE_AT, $REV;
196
197        $sessionManager = SessionManager::getInstance();
198        $ACT = $sessionManager->getDo();
199        $_REQUEST = $sessionManager->getRequest();
200
201        $REV = $INPUT->int('rev');
202        $DATE_AT = $INPUT->str('at');
203        $RANGE = $INPUT->str('range');
204        if ($INPUT->post->has('wikitext')) {
205            $TEXT = cleanText($INPUT->post->str('wikitext'));
206        }
207        $PRE = cleanText(substr($INPUT->post->str('prefix'), 0, -1));
208        $SUF = cleanText($INPUT->post->str('suffix'));
209        $SUM = $INPUT->post->str('summary');
210
211        $sessionManager->setDo('');
212        $sessionManager->setRequest([]);
213        $sessionManager->saveState();
214    }
215}
216