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