1<?php
2/**
3 * DokuWiki Plugin oauth (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr <andi@splitbrain.org>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12class action_plugin_oauth extends DokuWiki_Action_Plugin {
13
14    /**
15     * Registers a callback function for a given event
16     *
17     * @param Doku_Event_Handler $controller DokuWiki's event controller object
18     * @return void
19     */
20    public function register(Doku_Event_Handler $controller) {
21        global $conf;
22        if($conf['authtype'] != 'oauth') return;
23
24        $conf['profileconfirm'] = false; // password confirmation doesn't work with oauth only users
25
26        $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'handle_start');
27        $controller->register_hook('HTML_LOGINFORM_OUTPUT', 'BEFORE', $this, 'handle_loginform');
28        $controller->register_hook('HTML_UPDATEPROFILEFORM_OUTPUT', 'BEFORE', $this, 'handle_profileform');
29        $controller->register_hook('AUTH_USER_CHANGE', 'BEFORE', $this, 'handle_usermod');
30        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_dologin');
31    }
32
33    /**
34     * Start an oAuth login or restore  environment after successful login
35     *
36     * @param Doku_Event $event  event object by reference
37     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
38     *                           handler was registered]
39     * @return void
40     */
41    public function handle_start(Doku_Event &$event, $param) {
42
43        if (isset($_SESSION[DOKU_COOKIE]['oauth-done']['do']) || !empty($_SESSION[DOKU_COOKIE]['oauth-done']['rev'])){
44            $this->restoreSessionEnvironment();
45            return;
46        }
47
48        $this->startOAuthLogin();
49    }
50
51    private function startOAuthLogin() {
52        global $INPUT, $ID;
53
54        /** @var helper_plugin_oauth $hlp */
55        $hlp         = plugin_load('helper', 'oauth');
56        $servicename = $INPUT->str('oauthlogin');
57        $service     = $hlp->loadService($servicename);
58        if(is_null($service)) return;
59
60        // remember service in session
61        session_start();
62        $_SESSION[DOKU_COOKIE]['oauth-inprogress']['service'] = $servicename;
63        $_SESSION[DOKU_COOKIE]['oauth-inprogress']['id']      = $ID;
64        session_write_close();
65
66        $service->login();
67    }
68
69    private function restoreSessionEnvironment() {
70        global $INPUT, $ACT, $TEXT, $PRE, $SUF, $SUM, $RANGE, $DATE_AT, $REV;
71        $ACT = $_SESSION[DOKU_COOKIE]['oauth-done']['do'];
72        $_REQUEST = $_SESSION[DOKU_COOKIE]['oauth-done']['$_REQUEST'];
73
74        $REV   = $INPUT->int('rev');
75        $DATE_AT = $INPUT->str('at');
76        $RANGE = $INPUT->str('range');
77        if($INPUT->post->has('wikitext')) {
78            $TEXT = cleanText($INPUT->post->str('wikitext'));
79        }
80        $PRE = cleanText(substr($INPUT->post->str('prefix'), 0, -1));
81        $SUF = cleanText($INPUT->post->str('suffix'));
82        $SUM = $INPUT->post->str('summary');
83
84        unset($_SESSION[DOKU_COOKIE]['oauth-done']);
85    }
86
87    /**
88     * Save groups for all the services a user has enabled
89     *
90     * @param Doku_Event $event  event object by reference
91     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
92     *                           handler was registered]
93     * @return void
94     */
95    public function handle_usermod(Doku_Event &$event, $param) {
96        global $ACT;
97        global $USERINFO;
98        global $auth;
99        global $INPUT;
100
101        if($event->data['type'] != 'modify') return;
102        if($ACT != 'profile') return;
103
104        // we want to modify the user's groups
105        $groups = $USERINFO['grps']; //current groups
106        if(isset($event->data['params'][1]['grps'])) {
107            // something already defined new groups
108            $groups = $event->data['params'][1]['grps'];
109        }
110
111        /** @var helper_plugin_oauth $hlp */
112        $hlp = plugin_load('helper', 'oauth');
113
114        // get enabled and configured services
115        $enabled  = $INPUT->arr('oauth_group');
116        $services = $hlp->listServices();
117        $services = array_map(array($auth, 'cleanGroup'), $services);
118
119        // add all enabled services as group, remove all disabled services
120        foreach($services as $service) {
121            if(isset($enabled[$service])) {
122                $groups[] = $service;
123            } else {
124                $idx = array_search($service, $groups);
125                if($idx !== false) unset($groups[$idx]);
126            }
127        }
128        $groups = array_unique($groups);
129
130        // add new group array to event data
131        $event->data['params'][1]['grps'] = $groups;
132
133    }
134
135    /**
136     * Add service selection to user profile
137     *
138     * @param Doku_Event $event  event object by reference
139     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
140     *                           handler was registered]
141     * @return void
142     */
143    public function handle_profileform(Doku_Event &$event, $param) {
144        global $USERINFO;
145        /** @var auth_plugin_authplain $auth */
146        global $auth;
147
148        /** @var helper_plugin_oauth $hlp */
149        $hlp = plugin_load('helper', 'oauth');
150
151        /** @var Doku_Form $form */
152        $form =& $event->data;
153        $pos  = $form->findElementByAttribute('type', 'submit');
154
155        $services = $hlp->listServices();
156        if(!$services) return;
157
158        $form->insertElement($pos, form_closefieldset());
159        $form->insertElement(++$pos, form_openfieldset(array('_legend' => $this->getLang('loginwith'), 'class' => 'plugin_oauth')));
160        foreach($services as $service) {
161            $group = $auth->cleanGroup($service);
162            $elem  = form_makeCheckboxField(
163                'oauth_group['.$group.']',
164                1, $service, '', 'simple',
165                array(
166                    'checked' => (in_array($group, $USERINFO['grps'])) ? 'checked' : ''
167                )
168            );
169
170            $form->insertElement(++$pos, $elem);
171        }
172        $form->insertElement(++$pos, form_closefieldset());
173        $form->insertElement(++$pos, form_openfieldset(array()));
174    }
175
176    /**
177     * Add the oAuth login links
178     *
179     * @param Doku_Event $event  event object by reference
180     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
181     *                           handler was registered]
182     * @return void
183     */
184    public function handle_loginform(Doku_Event &$event, $param) {
185        global $conf;
186
187        /** @var helper_plugin_oauth $hlp */
188        $hlp = plugin_load('helper', 'oauth');
189        $singleService = $this->getConf('singleService');
190        $enabledServices = $hlp->listServices();
191
192        /** @var Doku_Form $form */
193        $form =& $event->data;
194        $html = '';
195
196        $validDomains = $hlp->getValidDomains();
197
198        if (count($validDomains) > 0) {
199            $html .= sprintf($this->getLang('eMailRestricted'), join(', ', $validDomains));
200        }
201
202        if ($singleService == '') {
203
204            foreach($hlp->listServices() as $service) {
205                $html .= $this->service_html($service);
206            }
207            if(!$html) return;
208
209        }else{
210            if (in_array($singleService, $enabledServices, true) === false) {
211                msg($this->getLang('wrongConfig'),-1);
212                return;
213            }
214            $form->_content = array();
215            $html = $this->service_html($singleService);
216
217        }
218        $form->_content[] = form_openfieldset(array('_legend' => $this->getLang('loginwith'), 'class' => 'plugin_oauth'));
219        $form->_content[] = $html;
220        $form->_content[] = form_closefieldset();
221    }
222
223    function service_html ($service){
224        global $ID;
225        $html = '';
226        $html .= '<a href="' . wl($ID, array('oauthlogin' => $service)) . '" class="plugin_oauth_' . $service . '">';
227        $html .= $service;
228        $html .= '</a> ';
229        return $html;
230
231    }
232
233    public function handle_dologin(Doku_Event &$event, $param) {
234        global $lang;
235        global $ID;
236
237        $singleService = $this->getConf('singleService');
238        if ($singleService == '') return true;
239
240        $lang['btn_login'] = $this->getLang('loginButton') . $singleService;
241
242        if($event->data != 'login') return true;
243
244
245
246        /** @var helper_plugin_oauth $hlp */
247        $hlp = plugin_load('helper', 'oauth');
248        $enabledServices = $hlp->listServices();
249        if (in_array($singleService, $enabledServices, true) === false) {
250            msg($this->getLang('wrongConfig'),-1);
251            return false;
252        }
253
254        $url = wl($ID, array('oauthlogin' => $singleService), true, '&');
255        send_redirect($url);
256    }
257
258}
259// vim:ts=4:sw=4:et:
260