1<?php 2 3use dokuwiki\plugin\oauth\OAuthManager; 4use dokuwiki\plugin\oauth\Session; 5use dokuwiki\Subscriptions\RegistrationSubscriptionSender; 6use OAuth\Common\Exception\Exception as OAuthException; 7 8/** 9 * DokuWiki Plugin oauth (Auth Component) 10 * 11 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 12 * @author Andreas Gohr <andi@splitbrain.org> 13 */ 14class auth_plugin_oauth extends auth_plugin_authplain 15{ 16 /** @var helper_plugin_oauth */ 17 protected $hlp; 18 19 // region standard auth methods 20 21 /** @inheritDoc */ 22 public function __construct() 23 { 24 parent::__construct(); 25 $this->cando['external'] = true; 26 $this->hlp = $this->loadHelper('oauth'); 27 } 28 29 /** @inheritDoc */ 30 public function trustExternal($user, $pass, $sticky = false) 31 { 32 global $INPUT; 33 34 // handle redirects from farmer to animal wiki instances 35 if ($INPUT->has('state') && plugin_load('helper', 'farmer')) { 36 $this->handleFarmState($INPUT->str('state')); 37 } 38 39 try { 40 // either oauth or "normal" plain auth login via form 41 $om = new OAuthManager(); 42 return $om->continueFlow() || auth_login($user, $pass, $sticky); 43 } catch (OAuthException $e) { 44 $this->hlp->showException($e); 45 auth_logoff(); // clears all session and cookie data 46 return false; 47 } 48 } 49 50 /** 51 * Enhance function to check against duplicate emails 52 * 53 * @inheritdoc 54 */ 55 public function createUser($user, $pwd, $name, $mail, $grps = null) 56 { 57 if ($this->getUserByEmail($mail)) { 58 msg($this->getLang('emailduplicate'), -1); 59 return false; 60 } 61 62 return parent::createUser($user, $pwd, $name, $mail, $grps); 63 } 64 65 /** 66 * Enhance function to check against duplicate emails 67 * 68 * @inheritdoc 69 */ 70 public function modifyUser($user, $changes) 71 { 72 global $conf; 73 74 if (isset($changes['mail'])) { 75 $found = $this->getUserByEmail($changes['mail']); 76 if ($found && $found != $user) { 77 msg($this->getLang('emailduplicate'), -1); 78 return false; 79 } 80 } 81 82 $ok = parent::modifyUser($user, $changes); 83 84 // refresh session cache 85 touch($conf['cachedir'] . '/sessionpurge'); 86 return $ok; 87 } 88 89 /** 90 * Unset additional stuff in session on logout 91 */ 92 public function logOff() 93 { 94 parent::logOff(); 95 (Session::getInstance())->clear(); 96 } 97 98 // endregion 99 100 /** 101 * Register a new user logged in by oauth 102 * 103 * It ensures the username is unique, by adding a number if needed. 104 * Default and service name groups are set here. 105 * Registration notifications are triggered. 106 * 107 * @param array $userinfo This will be updated with the new username 108 * @param string $servicename 109 * 110 * @return bool 111 * @todo - should this be part of the OAuthManager class instead? 112 */ 113 public function registerOAuthUser(&$userinfo, $servicename) 114 { 115 global $conf; 116 $user = $userinfo['user']; 117 $count = ''; 118 while ($this->getUserData($user . $count)) { 119 if ($count) { 120 $count++; 121 } else { 122 $count = 1; 123 } 124 } 125 $user = $user . $count; 126 $userinfo['user'] = $user; 127 $groups_on_creation = []; 128 $groups_on_creation[] = $conf['defaultgroup']; 129 $groups_on_creation[] = $this->cleanGroup($servicename); // add service as group 130 $userinfo['grps'] = array_merge((array)$userinfo['grps'], $groups_on_creation); 131 132 // the password set here will remain unknown to the user 133 $ok = $this->triggerUserMod( 134 'create', 135 [ 136 $user, 137 auth_pwgen($user), 138 $userinfo['name'], 139 $userinfo['mail'], 140 $userinfo['grps'], 141 ] 142 ); 143 if (!$ok) { 144 return false; 145 } 146 147 // send notification about the new user 148 $subscriptionSender = new RegistrationSubscriptionSender(); 149 $subscriptionSender->sendRegister($user, $userinfo['name'], $userinfo['mail']); 150 151 return true; 152 } 153 154 /** 155 * Find a user by email address 156 * 157 * @param $mail 158 * @return bool|string 159 */ 160 public function getUserByEmail($mail) 161 { 162 if ($this->users === null) { 163 $this->loadUserData(); 164 } 165 $mail = strtolower($mail); 166 167 foreach ($this->users as $user => $userinfo) { 168 if (strtolower($userinfo['mail']) == $mail) return $user; 169 } 170 171 return false; 172 } 173 174 /** 175 * Farmer plugin support 176 * 177 * When coming back to farmer instance via OAUTH redirectURI, we need to redirect again 178 * to a proper animal instance detected from $state 179 * 180 * @param $state 181 */ 182 protected function handleFarmState($state) 183 { 184 /** @var \helper_plugin_farmer $farmer */ 185 $farmer = plugin_load('helper', 'farmer', false, true); 186 $data = json_decode(base64_decode(urldecode($state))); 187 if (empty($data->animal) || $farmer->getAnimal() == $data->animal) { 188 return; 189 } 190 $animal = $data->animal; 191 $allAnimals = $farmer->getAllAnimals(); 192 if (!in_array($animal, $allAnimals)) { 193 msg('Animal ' . $animal . ' does not exist!'); 194 return; 195 } 196 global $INPUT; 197 $url = $farmer->getAnimalURL($animal) . '/doku.php?' . $INPUT->server->str('QUERY_STRING'); 198 send_redirect($url); 199 } 200} 201