/** * Returns the logged in user, or default user if not logged in * * @param TBGRequest $request * @param TBGAction $action * * @return TBGUser */ public static function loginCheck(TBGRequest $request, TBGAction $action) { try { $authentication_method = $action->getAuthenticationMethodForAction(TBGContext::getRouting()->getCurrentRouteAction()); $user = null; $external = false; switch ($authentication_method) { case TBGAction::AUTHENTICATION_METHOD_ELEVATED: case TBGAction::AUTHENTICATION_METHOD_CORE: $username = $request['tbg3_username']; $password = $request['tbg3_password']; if ($authentication_method == TBGAction::AUTHENTICATION_METHOD_ELEVATED) { $elevated_password = $request['tbg3_elevated_password']; } $raw = true; // If no username and password specified, check if we have a session that exists already if ($username === null && $password === null) { if (TBGContext::getRequest()->hasCookie('tbg3_username') && TBGContext::getRequest()->hasCookie('tbg3_password')) { $username = TBGContext::getRequest()->getCookie('tbg3_username'); $password = TBGContext::getRequest()->getCookie('tbg3_password'); $user = TBGUsersTable::getTable()->getByUsername($username); if ($authentication_method == TBGAction::AUTHENTICATION_METHOD_ELEVATED) { $elevated_password = TBGContext::getRequest()->getCookie('tbg3_elevated_password'); if ($user instanceof TBGUser && !$user->hasPasswordHash($password)) { $user = null; } else { if ($user instanceof TBGUser && !$user->hasPasswordHash($elevated_password)) { TBGContext::setUser($user); TBGContext::getRouting()->setCurrentRouteName('elevated_login_page'); throw new TBGElevatedLoginException('reenter'); } } } else { if ($user instanceof TBGUser && !$user->hasPasswordHash($password)) { $user = null; } } $raw = false; if (!$user instanceof TBGUser) { TBGContext::logout(); throw new Exception('No such login'); } } } // If we have authentication details, validate them if (TBGSettings::isUsingExternalAuthenticationBackend() && $username !== null && $password !== null) { $external = true; TBGLogging::log('Authenticating with backend: ' . TBGSettings::getAuthenticationBackend(), 'auth', TBGLogging::LEVEL_INFO); try { $mod = TBGContext::getModule(TBGSettings::getAuthenticationBackend()); if ($mod->getType() !== TBGModule::MODULE_AUTH) { TBGLogging::log('Auth module is not the right type', 'auth', TBGLogging::LEVEL_FATAL); } if (TBGContext::getRequest()->hasCookie('tbg3_username') && TBGContext::getRequest()->hasCookie('tbg3_password')) { $user = $mod->verifyLogin($username, $password); } else { $user = $mod->doLogin($username, $password); } if (!$user instanceof TBGUser) { // Invalid TBGContext::logout(); throw new Exception('No such login'); //TBGContext::getResponse()->headerRedirect(TBGContext::getRouting()->generate('login')); } } catch (Exception $e) { throw $e; } } elseif (TBGSettings::isUsingExternalAuthenticationBackend()) { $external = true; TBGLogging::log('Authenticating without credentials with backend: ' . TBGSettings::getAuthenticationBackend(), 'auth', TBGLogging::LEVEL_INFO); try { $mod = TBGContext::getModule(TBGSettings::getAuthenticationBackend()); if ($mod->getType() !== TBGModule::MODULE_AUTH) { TBGLogging::log('Auth module is not the right type', 'auth', TBGLogging::LEVEL_FATAL); } $user = $mod->doAutoLogin(); if ($user == false) { // Invalid TBGContext::logout(); throw new Exception('No such login'); //TBGContext::getResponse()->headerRedirect(TBGContext::getRouting()->generate('login')); } } catch (Exception $e) { throw $e; } } elseif ($username !== null && $password !== null && !$user instanceof TBGUser) { $external = false; TBGLogging::log('Using internal authentication', 'auth', TBGLogging::LEVEL_INFO); $user = TBGUsersTable::getTable()->getByUsername($username); if (!$user->hasPassword($password)) { $user = null; } if (!$user instanceof TBGUser) { TBGContext::logout(); } } break; case TBGAction::AUTHENTICATION_METHOD_DUMMY: $user = TBGUsersTable::getTable()->getByUserID(TBGSettings::getDefaultUserID()); break; case TBGAction::AUTHENTICATION_METHOD_CLI: $user = TBGUsersTable::getTable()->getByUsername(TBGContext::getCurrentCLIusername()); break; case TBGAction::AUTHENTICATION_METHOD_RSS_KEY: $user = TBGUsersTable::getTable()->getByRssKey($request['rsskey']); break; case TBGAction::AUTHENTICATION_METHOD_APPLICATION_PASSWORD: $user = TBGUsersTable::getTable()->getByUsername($request['api_username']); if (!$user->authenticateApplicationPassword($request['api_token'])) { $user = null; } break; default: if (!TBGSettings::isLoginRequired()) { $user = TBGUsersTable::getTable()->getByUserID(TBGSettings::getDefaultUserID()); } } if ($user instanceof TBGUser) { if (!$user->isActivated()) { throw new Exception('This account has not been activated yet'); } elseif (!$user->isEnabled()) { throw new Exception('This account has been suspended'); } elseif (!$user->isConfirmedMemberOfScope(TBGContext::getScope())) { if (!TBGSettings::isRegistrationAllowed()) { throw new Exception('This account does not have access to this scope'); } } if ($external == false && $authentication_method == TBGAction::AUTHENTICATION_METHOD_CORE) { $password = $user->getHashPassword(); if (!$request->hasCookie('tbg3_username')) { if ($request->getParameter('tbg3_rememberme')) { TBGContext::getResponse()->setCookie('tbg3_username', $user->getUsername()); TBGContext::getResponse()->setCookie('tbg3_password', $user->getPassword()); } else { TBGContext::getResponse()->setSessionCookie('tbg3_username', $user->getUsername()); TBGContext::getResponse()->setSessionCookie('tbg3_password', $user->getPassword()); } } } } elseif (TBGSettings::isLoginRequired()) { throw new Exception('Login required'); } else { throw new Exception('No such login'); } } catch (Exception $e) { throw $e; } return $user; }
public static function processCommit(TBGProject $project, $commit_msg, $old_rev, $new_rev, $date = null, $changed, $author, $branch = null) { $output = ''; TBGContext::setCurrentProject($project); if ($project->isArchived()) { return; } try { TBGContext::getI18n(); } catch (Exception $e) { TBGContext::reinitializeI18n(null); } // Is VCS Integration enabled? if (TBGSettings::get('vcs_mode_' . $project->getID(), 'vcs_integration') == TBGVCSIntegration::MODE_DISABLED) { $output .= '[VCS ' . $project->getKey() . '] This project does not use VCS Integration' . "\n"; return $output; } // Parse the commit message, and obtain the issues and transitions for issues. $parsed_commit = TBGIssue::getIssuesFromTextByRegex($commit_msg); $issues = $parsed_commit["issues"]; $transitions = $parsed_commit["transitions"]; // If no issues exist, we may not be able to continue // if (count($issues) == 0) // { // $output .= '[VCS '.$project->getKey().'] This project only accepts commits which affect issues' . "\n"; // return $output; // } // Build list of affected files $file_lines = preg_split('/[\\n\\r]+/', $changed); $files = array(); foreach ($file_lines as $aline) { $action = mb_substr($aline, 0, 1); if ($action == "A" || $action == "U" || $action == "D" || $action == "M") { $theline = trim(mb_substr($aline, 1)); $files[] = array($action, $theline); } } // Find author of commit, fallback is guest /* * Some VCSes use a different format of storing the committer's name. Systems like bzr, git and hg use the format * Joe Bloggs <*****@*****.**>, instead of a classic username. Therefore a user will be found via 4 queries: * a) First we extract the email if there is one, and find a user with that email * b) If one is not found - or if no email was specified, then instead test against the real name (using the name part if there was an email) * c) the username or full name is checked against the friendly name field * d) and if we still havent found one, then we check against the username * e) and if we STILL havent found one, we use the guest user */ if (preg_match("/(?<=<)(.*)(?=>)/", $author, $matches)) { $email = $matches[0]; // a) $user = TBGUsersTable::getTable()->getByEmail($email); if (!$user instanceof TBGUser) { // Not found by email preg_match("/(?<=^)(.*)(?= <)/", $author, $matches); $author = $matches[0]; } } // b) if (!$user instanceof TBGUser) { $user = TBGUsersTable::getTable()->getByRealname($author); } // c) if (!$user instanceof TBGUser) { $user = TBGUsersTable::getTable()->getByBuddyname($author); } // d) if (!$user instanceof TBGUser) { $user = TBGUsersTable::getTable()->getByUsername($author); } // e) if (!$user instanceof TBGUser) { $user = TBGSettings::getDefaultUser(); } TBGContext::setUser($user); TBGSettings::forceSettingsReload(); TBGContext::cacheAllPermissions(); $output .= '[VCS ' . $project->getKey() . '] Commit to be logged by user ' . $user->getName() . "\n"; if ($date == null) { $date = NOW; } // Create the commit data $commit = new TBGVCSIntegrationCommit(); $commit->setAuthor($user); $commit->setDate($date); $commit->setLog($commit_msg); $commit->setPreviousRevision($old_rev); $commit->setRevision($new_rev); $commit->setProject($project); if ($branch !== null) { $data = 'branch:' . $branch; $commit->setMiscData($data); } $commit->save(); $output .= '[VCS ' . $project->getKey() . '] Commit logged with revision ' . $commit->getRevision() . "\n"; // Iterate over affected issues and update them. foreach ($issues as $issue) { $inst = new TBGVCSIntegrationIssueLink(); $inst->setIssue($issue); $inst->setCommit($commit); $inst->save(); // Process all commit-message transitions for an issue. foreach ($transitions[$issue->getFormattedIssueNo()] as $transition) { if (TBGSettings::get('vcs_workflow_' . $project->getID(), 'vcs_integration') == TBGVCSIntegration::WORKFLOW_ENABLED) { TBGContext::setUser($user); TBGSettings::forceSettingsReload(); TBGContext::cacheAllPermissions(); if ($issue->isWorkflowTransitionsAvailable()) { // Go through the list of possible transitions for an issue. Only // process transitions that are applicable to issue's workflow. foreach ($issue->getAvailableWorkflowTransitions() as $possible_transition) { if (mb_strtolower($possible_transition->getName()) == mb_strtolower($transition[0])) { $output .= '[VCS ' . $project->getKey() . '] Running transition ' . $transition[0] . ' on issue ' . $issue->getFormattedIssueNo() . "\n"; // String representation of parameters. Used for log message. $parameters_string = ""; // Iterate over the list of this transition's parameters, and // set them. foreach ($transition[1] as $parameter => $value) { $parameters_string .= "{$parameter}={$value} "; switch ($parameter) { case 'resolution': if (($resolution = TBGResolution::getResolutionByKeyish($value)) instanceof TBGResolution) { TBGContext::getRequest()->setParameter('resolution_id', $resolution->getID()); } break; case 'status': if (($status = TBGStatus::getStatusByKeyish($value)) instanceof TBGStatus) { TBGContext::getRequest()->setParameter('status_id', $status->getID()); } break; } } // Run the transition. $possible_transition->transitionIssueToOutgoingStepWithoutRequest($issue); // Log an informative message about the transition. $output .= '[VCS ' . $project->getKey() . '] Ran transition ' . $possible_transition->getName() . ' with parameters \'' . $parameters_string . '\' on issue ' . $issue->getFormattedIssueNo() . "\n"; } } } } } $issue->addSystemComment(TBGContext::getI18n()->__('This issue has been updated with the latest changes from the code repository.<source>%commit_msg</source>', array('%commit_msg' => $commit_msg)), $user->getID()); $output .= '[VCS ' . $project->getKey() . '] Updated issue ' . $issue->getFormattedIssueNo() . "\n"; } // Create file links foreach ($files as $afile) { // index 0 is action, index 1 is file $inst = new TBGVCSIntegrationFile(); $inst->setAction($afile[0]); $inst->setFile($afile[1]); $inst->setCommit($commit); $inst->save(); $output .= '[VCS ' . $project->getKey() . '] Added with action ' . $afile[0] . ' file ' . $afile[1] . "\n"; } TBGEvent::createNew('vcs_integration', 'new_commit')->trigger(array('commit' => $commit)); return $output; }
/** * Do login (AJAX call) * * @param TBGRequest $request */ public function runDoLogin(TBGRequest $request) { $i18n = TBGContext::getI18n(); $options = $request->getParameters(); $forward_url = TBGContext::getRouting()->generate('home'); if ($request->hasParameter('persona') && $request['persona'] == 'true') { $url = 'https://verifier.login.persona.org/verify'; $assert = filter_input(INPUT_POST, 'assertion', FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH); //Use the $_POST superglobal array for PHP < 5.2 and write your own filter $params = 'assertion=' . urlencode($assert) . '&audience=' . urlencode(TBGContext::getURLhost() . ':80'); $ch = curl_init(); $options = array(CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_POST => 2, CURLOPT_POSTFIELDS => $params); curl_setopt_array($ch, $options); $result = curl_exec($ch); curl_close($ch); $details = json_decode($result); $user = null; if ($details->status == 'okay') { $user = TBGUser::getByEmail($details->email); if ($user instanceof TBGUser) { TBGContext::getResponse()->setCookie('tbg3_password', $user->getPassword()); TBGContext::getResponse()->setCookie('tbg3_username', $user->getUsername()); TBGContext::getResponse()->setCookie('tbg3_persona_session', true); return $this->renderJSON(array('status' => 'login ok', 'redirect' => in_array($request['referrer_route'], array('home', 'login')))); } } if (!$user instanceof TBGUser) { $this->getResponse()->setHttpStatus(401); $this->renderJSON(array('message' => $this->getI18n()->__('Invalid login'))); } return; } if (TBGSettings::isOpenIDavailable()) { $openid = new LightOpenID(TBGContext::getRouting()->generate('login_page', array(), false)); } if (TBGSettings::isOpenIDavailable() && !$openid->mode && $request->isPost() && $request->hasParameter('openid_identifier')) { $openid->identity = $request->getRawParameter('openid_identifier'); $openid->required = array('contact/email'); $openid->optional = array('namePerson/first', 'namePerson/friendly'); return $this->forward($openid->authUrl()); } elseif (TBGSettings::isOpenIDavailable() && $openid->mode == 'cancel') { $this->error = TBGContext::getI18n()->__("OpenID authentication cancelled"); } elseif (TBGSettings::isOpenIDavailable() && $openid->mode) { try { if ($openid->validate()) { if ($this->getUser()->isAuthenticated() && !$this->getUser()->isGuest()) { if (TBGOpenIdAccountsTable::getTable()->getUserIDfromIdentity($openid->identity)) { TBGContext::setMessage('openid_used', true); throw new Exception('OpenID already in use'); } $user = $this->getUser(); } else { $user = TBGUser::getByOpenID($openid->identity); } if ($user instanceof TBGUser) { $attributes = $openid->getAttributes(); $email = array_key_exists('contact/email', $attributes) ? $attributes['contact/email'] : null; if (!$user->getEmail()) { if (array_key_exists('contact/email', $attributes)) { $user->setEmail($attributes['contact/email']); } if (array_key_exists('namePerson/first', $attributes)) { $user->setRealname($attributes['namePerson/first']); } if (array_key_exists('namePerson/friendly', $attributes)) { $user->setBuddyname($attributes['namePerson/friendly']); } if (!$user->getNickname() || $user->isOpenIdLocked()) { $user->setBuddyname($user->getEmail()); } if (!$user->getRealname()) { $user->setRealname($user->getBuddyname()); } $user->save(); } if (!$user->hasOpenIDIdentity($openid->identity)) { TBGOpenIdAccountsTable::getTable()->addIdentity($openid->identity, $email, $user->getID()); } TBGContext::getResponse()->setCookie('tbg3_password', $user->getPassword()); TBGContext::getResponse()->setCookie('tbg3_username', $user->getUsername()); if ($this->checkScopeMembership($user)) { return true; } return $this->forward(TBGContext::getRouting()->generate(TBGSettings::get('returnfromlogin'))); } else { $this->error = TBGContext::getI18n()->__("Didn't recognize this OpenID. Please log in using your username and password, associate it with your user account in your account settings and try again."); } } else { $this->error = TBGContext::getI18n()->__("Could not validate against the OpenID provider"); } } catch (Exception $e) { $this->error = TBGContext::getI18n()->__("Could not validate against the OpenID provider: %message", array('%message' => htmlentities($e->getMessage(), ENT_COMPAT, TBGContext::getI18n()->getCharset()))); } } elseif ($request->getMethod() == TBGRequest::POST) { try { if ($request->hasParameter('tbg3_username') && $request->hasParameter('tbg3_password') && $request['tbg3_username'] != '' && $request['tbg3_password'] != '') { $user = TBGUser::loginCheck($request, $this); TBGContext::setUser($user); if ($this->checkScopeMembership($user)) { return true; } if ($request->hasParameter('return_to')) { $forward_url = $request['return_to']; } else { if (TBGSettings::get('returnfromlogin') == 'referer') { $forward_url = $request->getParameter('tbg3_referer', TBGContext::getRouting()->generate('dashboard')); } else { $forward_url = TBGContext::getRouting()->generate(TBGSettings::get('returnfromlogin')); } } $forward_url = htmlentities($forward_url, ENT_COMPAT, TBGContext::getI18n()->getCharset()); } else { throw new Exception('Please enter a username and password'); } } catch (Exception $e) { if ($request->isAjaxCall()) { $this->getResponse()->setHttpStatus(401); TBGLogging::log($e->getMessage(), 'openid', TBGLogging::LEVEL_WARNING_RISK); return $this->renderJSON(array("error" => $i18n->__("Invalid login details"))); } else { $this->forward403($e->getMessage()); } } } else { if ($request->isAjaxCall()) { $this->getResponse()->setHttpStatus(401); return $this->renderJSON(array("error" => $i18n->__('Please enter a username and password'))); } else { $this->forward403($i18n->__('Please enter a username and password')); } } if ($this->checkScopeMembership($user)) { return true; } if ($request->isAjaxCall()) { return $this->renderJSON(array('forward' => $forward_url)); } else { $this->forward($this->getRouting()->generate('account')); } }
/** * Login (AJAX call) * * @param TBGRequest $request */ public function runLogin(TBGRequest $request) { $i18n = TBGContext::getI18n(); $this->login_referer = array_key_exists('HTTP_REFERER', $_SERVER) && isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; $options = $request->getParameters(); $forward_url = TBGContext::getRouting()->generate('home'); try { if ($request->getMethod() == TBGRequest::POST) { if ($request->hasParameter('tbg3_username') && $request->hasParameter('tbg3_password')) { $username = $request->getParameter('tbg3_username'); $password = $request->getParameter('tbg3_password'); $user = TBGUser::loginCheck($username, $password, true); $this->getResponse()->setCookie('tbg3_username', $username); $this->getResponse()->setCookie('tbg3_password', TBGUser::hashPassword($password)); TBGContext::setUser($user); if ($request->hasParameter('return_to')) { $forward_url = $request->getParameter('return_to'); } else { if (TBGSettings::get('returnfromlogin') == 'referer') { if ($request->getParameter('tbg3_referer')) { $forward_url = $request->getParameter('tbg3_referer'); } else { $forward_url = TBGContext::getRouting()->generate('dashboard'); } } else { $forward_url = TBGContext::getRouting()->generate(TBGSettings::get('returnfromlogin')); } } } else { throw new Exception($i18n->__('Please enter a username and password')); } } elseif (TBGSettings::isLoginRequired()) { throw new Exception($i18n->__('You need to log in to access this site')); } elseif (!TBGContext::getUser()->isAuthenticated()) { throw new Exception($i18n->__('Please log in')); } elseif (TBGContext::hasMessage('forward')) { throw new Exception($i18n->__(TBGContext::getMessageAndClear('forward'))); } } catch (Exception $e) { if (TBGContext::getRequest()->isAjaxCall() || TBGContext::getRequest()->getRequestedFormat() == 'json') { return $this->renderJSON(array('failed' => true, "error" => $i18n->__($e->getMessage()), 'referer' => $request->getParameter('tbg3_referer'))); } else { $options['error'] = $e->getMessage(); } } if (TBGContext::getRequest()->isAjaxCall() || TBGContext::getRequest()->getRequestedFormat() == 'json') { return $this->renderJSON(array('forward' => $forward_url)); } elseif ($forward_url !== null && $request->getParameter('continue') != true) { $this->forward($forward_url); } $this->options = $options; }