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 return false; 46 } 47 } 48 49 /** 50 * Enhance function to check against duplicate emails 51 * 52 * @inheritdoc 53 */ 54 public function createUser($user, $pwd, $name, $mail, $grps = null) 55 { 56 if ($this->getUserByEmail($mail)) { 57 msg($this->getLang('emailduplicate'), -1); 58 return false; 59 } 60 61 return parent::createUser($user, $pwd, $name, $mail, $grps); 62 } 63 64 /** 65 * Enhance function to check against duplicate emails 66 * 67 * @inheritdoc 68 */ 69 public function modifyUser($user, $changes) 70 { 71 global $conf; 72 73 if (isset($changes['mail'])) { 74 $found = $this->getUserByEmail($changes['mail']); 75 if ($found && $found != $user) { 76 msg($this->getLang('emailduplicate'), -1); 77 return false; 78 } 79 } 80 81 $ok = parent::modifyUser($user, $changes); 82 83 // refresh session cache 84 touch($conf['cachedir'] . '/sessionpurge'); 85 return $ok; 86 } 87 88 /** 89 * Unset additional stuff in session on logout 90 */ 91 public function logOff() 92 { 93 parent::logOff(); 94 (Session::getInstance())->clear(); 95 } 96 97 // endregion 98 99 /** 100 * Register a new user logged in by oauth 101 * 102 * It ensures the username is unique, by adding a number if needed. 103 * Default and service name groups are set here. 104 * Registration notifications are triggered. 105 * 106 * @param array $userinfo This will be updated with the new username 107 * @param string $servicename 108 * 109 * @return bool 110 * @todo - should this be part of the OAuthManager class instead? 111 */ 112 public function registerOAuthUser(&$userinfo, $servicename) 113 { 114 global $conf; 115 $user = $userinfo['user']; 116 $count = ''; 117 while ($this->getUserData($user . $count)) { 118 if ($count) { 119 $count++; 120 } else { 121 $count = 1; 122 } 123 } 124 $user = $user . $count; 125 $userinfo['user'] = $user; 126 $groups_on_creation = []; 127 $groups_on_creation[] = $conf['defaultgroup']; 128 $groups_on_creation[] = $this->cleanGroup($servicename); // add service as group 129 $userinfo['grps'] = array_merge((array)$userinfo['grps'], $groups_on_creation); 130 131 // the password set here will remain unknown to the user 132 $ok = $this->triggerUserMod( 133 'create', 134 [ 135 $user, 136 auth_pwgen($user), 137 $userinfo['name'], 138 $userinfo['mail'], 139 $groups_on_creation, 140 ] 141 ); 142 if (!$ok) { 143 return false; 144 } 145 146 // send notification about the new user 147 $subscriptionSender = new RegistrationSubscriptionSender(); 148 $subscriptionSender->sendRegister($user, $userinfo['name'], $userinfo['mail']); 149 150 return true; 151 } 152 153 /** 154 * Find a user by email address 155 * 156 * @param $mail 157 * @return bool|string 158 */ 159 public function getUserByEmail($mail) 160 { 161 if ($this->users === null) { 162 $this->loadUserData(); 163 } 164 $mail = strtolower($mail); 165 166 foreach ($this->users as $user => $userinfo) { 167 if (strtolower($userinfo['mail']) == $mail) return $user; 168 } 169 170 return false; 171 } 172 173 /** 174 * Farmer plugin support 175 * 176 * When coming back to farmer instance via OAUTH redirectURI, we need to redirect again 177 * to a proper animal instance detected from $state 178 * 179 * @param $state 180 */ 181 protected function handleFarmState($state) 182 { 183 /** @var \helper_plugin_farmer $farmer */ 184 $farmer = plugin_load('helper', 'farmer', false, true); 185 $data = json_decode(base64_decode(urldecode($state))); 186 if (empty($data->animal) || $farmer->getAnimal() == $data->animal) { 187 return; 188 } 189 $animal = $data->animal; 190 $allAnimals = $farmer->getAllAnimals(); 191 if (!in_array($animal, $allAnimals)) { 192 msg('Animal ' . $animal . ' does not exist!'); 193 return; 194 } 195 global $INPUT; 196 $url = $farmer->getAnimalURL($animal) . '/doku.php?' . $INPUT->server->str('QUERY_STRING'); 197 send_redirect($url); 198 } 199} 200