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_evesso 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'] != 'evesso') 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        global $ID;
43        if (isset($_SESSION[DOKU_COOKIE]['oauth-logout'])){
44            unset($_SESSION[DOKU_COOKIE]['oauth-logout']);
45            send_redirect(wl($ID));
46            return;
47        }
48        if (isset($_SESSION[DOKU_COOKIE]['oauth-done']['do']) || !empty($_SESSION[DOKU_COOKIE]['oauth-done']['rev'])){
49            $this->restoreSessionEnvironment();
50            return;
51        }
52
53        $this->startOAuthLogin();
54    }
55
56    private function startOAuthLogin() {
57        global $INPUT, $ID;
58
59        /** @var helper_plugin_evesso $hlp */
60        $hlp         = plugin_load('helper', 'evesso');
61        $servicename = $INPUT->str('evessologin');
62        $service     = $hlp->loadService($servicename);
63        if(is_null($service)) return;
64
65        // remember service in session
66        session_start();
67        $_SESSION[DOKU_COOKIE]['oauth-inprogress']['service'] = $servicename;
68        $_SESSION[DOKU_COOKIE]['oauth-inprogress']['id']      = $ID;
69        session_write_close();
70
71        $service->login();
72    }
73
74    private function restoreSessionEnvironment() {
75        global $INPUT, $ACT, $TEXT, $PRE, $SUF, $SUM, $RANGE, $DATE_AT, $REV;
76        $ACT = $_SESSION[DOKU_COOKIE]['oauth-done']['do'];
77        $_REQUEST = $_SESSION[DOKU_COOKIE]['oauth-done']['$_REQUEST'];
78
79        $REV   = $INPUT->int('rev');
80        $DATE_AT = $INPUT->str('at');
81        $RANGE = $INPUT->str('range');
82        if($INPUT->post->has('wikitext')) {
83            $TEXT = cleanText($INPUT->post->str('wikitext'));
84        }
85        $PRE = cleanText(substr($INPUT->post->str('prefix'), 0, -1));
86        $SUF = cleanText($INPUT->post->str('suffix'));
87        $SUM = $INPUT->post->str('summary');
88
89        unset($_SESSION[DOKU_COOKIE]['oauth-done']);
90    }
91
92    /**
93     * Save groups for all the services a user has enabled
94     *
95     * @param Doku_Event $event  event object by reference
96     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
97     *                           handler was registered]
98     * @return void
99     */
100    public function handle_usermod(Doku_Event &$event, $param) {
101        global $ACT;
102        global $USERINFO;
103        global $auth;
104        global $INPUT;
105
106        if($event->data['type'] != 'modify') return;
107        if($ACT != 'profile') return;
108
109        // we want to modify the user's groups
110        $groups = $USERINFO['grps']; //current groups
111        if(isset($event->data['params'][1]['grps'])) {
112            // something already defined new groups
113            $groups = $event->data['params'][1]['grps'];
114        }
115
116        /** @var helper_plugin_evesso $hlp */
117        $hlp = plugin_load('helper', 'evesso');
118
119        // get enabled and configured services
120        $enabled  = $INPUT->arr('oauth_group');
121        $services = $hlp->listServices();
122        $services = array_map(array($auth, 'cleanGroup'), $services);
123
124        // add all enabled services as group, remove all disabled services
125        foreach($services as $service) {
126            if(isset($enabled[$service])) {
127                $groups[] = $service;
128            } else {
129                $idx = array_search($service, $groups);
130                if($idx !== false) unset($groups[$idx]);
131            }
132        }
133        $groups = array_unique($groups);
134
135        // add new group array to event data
136        $event->data['params'][1]['grps'] = $groups;
137
138    }
139
140    /**
141     * Add service selection to user profile
142     *
143     * @param Doku_Event $event  event object by reference
144     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
145     *                           handler was registered]
146     * @return void
147     */
148    public function handle_profileform(Doku_Event &$event, $param) {
149        global $USERINFO;
150        /** @var auth_plugin_authplain $auth */
151        global $auth;
152
153        /** @var helper_plugin_evesso $hlp */
154        $hlp = plugin_load('helper', 'evesso');
155
156        /** @var Doku_Form $form */
157        $form =& $event->data;
158        $pos  = $form->findElementByAttribute('type', 'submit');
159
160        $services = $hlp->listServices();
161        if(!$services) return;
162
163        $form->insertElement($pos, form_closefieldset());
164        $form->insertElement(++$pos, form_openfieldset(array('_legend' => $this->getLang('loginwith'), 'class' => 'plugin_evesso')));
165        foreach($services as $service) {
166            $group = $auth->cleanGroup($service);
167            $elem  = form_makeCheckboxField(
168                'oauth_group['.$group.']',
169                1, $service, '', 'simple',
170                array(
171                    'checked' => (in_array($group, $USERINFO['grps'])) ? 'checked' : ''
172                )
173            );
174
175            $form->insertElement(++$pos, $elem);
176        }
177        $form->insertElement(++$pos, form_closefieldset());
178        $form->insertElement(++$pos, form_openfieldset(array()));
179    }
180
181    /**
182     * Add the oAuth login links
183     *
184     * @param Doku_Event $event  event object by reference
185     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
186     *                           handler was registered]
187     * @return void
188     */
189    public function handle_loginform(Doku_Event &$event, $param) {
190        global $conf;
191
192        /** @var helper_plugin_evesso $hlp */
193        $hlp = plugin_load('helper', 'evesso');
194        $singleService = $this->getConf('singleService');
195        $enabledServices = $hlp->listServices();
196
197        /** @var Doku_Form $form */
198        $form =& $event->data;
199        $html = '';
200
201        $validDomains = $hlp->getValidDomains();
202
203        if (count($validDomains) > 0) {
204            $html .= sprintf($this->getLang('eMailRestricted'), join(', ', $validDomains));
205        }
206
207        if ($singleService == '') {
208
209            foreach($hlp->listServices() as $service) {
210                $html .= $this->service_html($service);
211            }
212            if(!$html) return;
213
214        }else{
215            if (in_array($singleService, $enabledServices, true) === false) {
216                msg($this->getLang('wrongConfig'),-1);
217                return;
218            }
219            $form->_content = array();
220            $html = $this->service_html($singleService);
221
222        }
223        $form->_content[] = form_openfieldset(array('_legend' => $this->getLang('loginwith'), 'class' => 'plugin_evesso'));
224        $form->_content[] = $html;
225        $form->_content[] = form_closefieldset();
226    }
227
228    function service_html ($service){
229        global $ID;
230        $html = '';
231        $html .= '<a href="' . wl($ID, array('evessologin' => $service)) . '" class="plugin_evesso_' . $service . '">';
232        $html .= $service;
233        $html .= '</a> ';
234        return $html;
235
236    }
237
238    public function handle_dologin(Doku_Event &$event, $param) {
239        global $lang;
240        global $ID;
241
242        $singleService = $this->getConf('singleService');
243
244        if($event->data == 'logout' && $singleService != '') {
245            session_start();
246            $_SESSION[DOKU_COOKIE]['oauth-logout'] = 'logout';
247            session_write_close();
248        }
249
250        if ($singleService == '') return true;
251
252        $lang['btn_login'] = $this->getLang('loginButton') . $singleService;
253
254        if($event->data != 'login') return true;
255
256
257
258        /** @var helper_plugin_evesso $hlp */
259        $hlp = plugin_load('helper', 'evesso');
260        $enabledServices = $hlp->listServices();
261        if (in_array($singleService, $enabledServices, true) === false) {
262            msg($this->getLang('wrongConfig'),-1);
263            return false;
264        }
265
266        $url = wl($ID, array('evessologin' => $singleService), true, '&');
267        send_redirect($url);
268    }
269
270}
271// vim:ts=4:sw=4:et:
272