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