/** Handle web API authentication with an OAuth token */ public function handleAuth($params) { $apiArgs = $params['args']; if (array_key_exists('oauth_token', $apiArgs)) { if (Zend_Registry::isRegistered('oauthRequiredScopes')) { $requiredScopes = Zend_Registry::get('oauthRequiredScopes'); } else { $requiredScopes = array(MIDAS_API_PERMISSION_SCOPE_ALL); } $tokenDao = $this->Oauth_Token->getByToken($apiArgs['oauth_token']); if (!$tokenDao || $tokenDao->getType() != MIDAS_OAUTH_TOKEN_TYPE_ACCESS) { throw new Zend_Exception('Invalid OAuth access token', 400); } if ($tokenDao->isExpired()) { throw new Zend_Exception('Token has expired', 403); } $grantedScopes = JsonComponent::decode($tokenDao->getScopes()); if (!in_array(MIDAS_API_PERMISSION_SCOPE_ALL, $grantedScopes)) { foreach ($requiredScopes as $requiredScope) { if (!in_array($requiredScope, $grantedScopes)) { return array('userDao' => null); // Missing required scope, let caller determine permission failure } } } return array('userDao' => $tokenDao->getUser()); } else { return false; // fall through to normal authentication } }
/** Test the AJAX get free space call. */ public function testGetFreeSpace() { $usersFile = $this->loadData('User', 'default'); $user1 = $this->User->load($usersFile[0]->getKey()); $adminUser = $this->User->load($usersFile[2]->getKey()); $commFile = $this->loadData('Community', 'default'); $comm = $this->Community->load($commFile[0]->getKey()); // Exception if no folder id is set $this->resetAll(); $this->dispatchUrl('/' . $this->moduleName . '/folder/getfreespace', $adminUser); $resp = JsonComponent::decode($this->getBody()); $this->assertTrue($resp['status'] == false); $this->assertEquals($resp['message'], 'Missing folderId parameter'); // Exception if invalid folder id is set $this->resetAll(); $this->dispatchUrl('/' . $this->moduleName . '/folder/getfreespace?folderId=-7', $adminUser); $resp = JsonComponent::decode($this->getBody()); $this->assertTrue($resp['status'] == false); $this->assertEquals($resp['message'], 'Invalid folder'); // Exception if no read privileges $this->resetAll(); $this->dispatchUrl('/' . $this->moduleName . '/folder/getfreespace?folderId=' . $user1->getFolderId(), null); $resp = JsonComponent::decode($this->getBody()); $this->assertTrue($resp['status'] == false); $this->assertEquals($resp['message'], 'Invalid policy'); // User with read privileges should be able to get free space $this->resetAll(); $this->dispatchUrl('/' . $this->moduleName . '/folder/getfreespace?folderId=' . $user1->getFolderId(), $user1); $resp = JsonComponent::decode($this->getBody()); $this->assertTrue($resp['status'] == true); // This should also work on non-root folders $this->resetAll(); $this->dispatchUrl('/' . $this->moduleName . '/folder/getfreespace?folderId=1001', $user1); $resp = JsonComponent::decode($this->getBody()); $this->assertTrue($resp['status'] == true); // Should also work for community folders $this->resetAll(); $this->Setting->setConfig('defaultcommunityquota', 12345, $this->moduleName); $commFolders = $comm->getFolder()->getFolders(); $this->dispatchUrl('/' . $this->moduleName . '/folder/getfreespace?folderId=' . $commFolders[0]->getKey(), $adminUser); $resp = JsonComponent::decode($this->getBody()); $this->assertTrue($resp['status'] == true); $this->assertEquals($resp['freeSpace'], 12345); }
/** run a task */ public function taskAction() { $this->requireAdminPrivileges(); $task = $this->getParam('task'); $params = $this->getParam('params'); if (isset($params)) { $params = JsonComponent::decode($params); } else { $params = array(); } if ($this->progressDao) { $params['progressDao'] = $this->progressDao; } $modules = Zend_Registry::get('notifier')->modules; $tasks = Zend_Registry::get('notifier')->tasks; call_user_func(array($modules[$tasks[$task]['module']], $tasks[$task]['method']), $params); $this->disableLayout(); $this->disableView(); }
/** * Helper method to make sure that a web api call failed. */ private function _assertApiFailure() { $json = JsonComponent::decode($this->getBody()); $this->assertEquals($json['stat'], 'fail'); $this->assertTrue($json['code'] != 0); }
/** * The client sends the results to Midas Server (put request). * * @param token * * @param array $args parameters * @throws Exception */ public function resultsserver($args) { $testingmode = false; if (isset($_GET['testingmode']) && $_GET['testingmode'] == 1) { $testingmode = true; } if (!$testingmode && $_SERVER['REQUEST_METHOD'] != 'POST') { throw new Exception('Should be a put request.', MIDAS_INVALID_PARAMETER); } $authComponent = MidasLoader::loadComponent('Authentication'); $userDao = $authComponent->getUser($args, Zend_Registry::get('userSession')->Dao); if ($userDao == false) { throw new Exception('Unable to authenticate as a server. Please check credentials.', MIDAS_INVALID_PARAMETER); } /** @var GroupModel $groupModel */ $groupModel = MidasLoader::loadModel('Group'); $groupServer = $groupModel->load(MIDAS_GROUP_SERVER_KEY); $users = $groupServer->getUsers(); $isServer = false; foreach ($users as $user) { if ($user->getKey() == $userDao->getKey()) { $isServer = true; } } if ($isServer == false) { throw new Exception('Unable to authenticate as a server. Please check credentials.', MIDAS_INVALID_PARAMETER); } if (!file_exists(UtilityComponent::getTempDirectory() . '/remoteprocessing')) { mkdir(UtilityComponent::getTempDirectory() . '/remoteprocessing'); } /** @var RandomComponent $randomComponent */ $randomComponent = MidasLoader::loadComponent('Random'); $destination = UtilityComponent::getTempDirectory() . '/remoteprocessing/' . $randomComponent->generateInt(); while (file_exists($destination)) { $destination = UtilityComponent::getTempDirectory() . '/remoteprocessing/' . $randomComponent->generateInt(); } mkdir($destination); if (!$testingmode) { move_uploaded_file($_FILES['file']['tmp_name'], $destination . '/results.zip'); } if ($testingmode) { return array(); } if (file_exists($destination . '/results.zip')) { mkdir($destination . '/content'); $target_directory = $destination . '/content'; $filter = new Zend_Filter_Decompress(array('adapter' => 'Zip', 'options' => array('target' => $target_directory))); $compressed = $filter->filter($destination . '/results.zip'); if ($compressed && file_exists($target_directory . '/parameters.txt')) { $info = file_get_contents($target_directory . '/parameters.txt'); $info = JsonComponent::decode($info); $job_id = $info['job_id']; /** @var Remoteprocessing_JobModel $jobModel */ $jobModel = MidasLoader::loadModel('Job', 'remoteprocessing'); $jobDao = $jobModel->load($job_id); $jobDao->setStatus(MIDAS_REMOTEPROCESSING_STATUS_DONE); $jobModel->save($jobDao); $info['pathResults'] = $destination . '/content'; $info['log'] = file_get_contents($target_directory . '/log.txt'); $info['userKey'] = $userDao->getKey(); Zend_Registry::get('notifier')->callback($info['resultCallback'], $info); } else { throw new Exception('Error, unable to unzip results.', MIDAS_INVALID_PARAMETER); } } else { throw new Exception('Error, unable to find results.', MIDAS_INVALID_PARAMETER); } $this->_rrmdir($destination); return array(); }
/** Index action */ public function indexAction() { $startTime = time(); $this->disableLayout(); $this->disableView(); $lastStart = $this->Setting->getValueByName('lastrun', $this->moduleName); if ($lastStart !== null && $startTime < (int) $lastStart + 270) { throw new Zend_Exception('The scheduler is already running. Please wait for it to complete before invoking again.'); } ignore_user_abort(true); $this->Setting->setConfig('lastrun', $startTime, $this->moduleName); $id = $this->getParam('id'); if (isset($id)) { $jobs = $this->Scheduler_Job->load($id); if ($jobs == false) { throw new Zend_Exception('Unable to load job'); } $jobs = array($jobs); } else { $jobs = $this->Scheduler_Job->getJobsToRun(1000); } $modules = Zend_Registry::get('notifier')->modules; $tasks = Zend_Registry::get('notifier')->tasks; foreach ($jobs as $job) { if (time() - $startTime > 270) { // After 4.5 minutes, do not start any new tasks break; } $job->setStatus(SCHEDULER_JOB_STATUS_STARTED); if ($job->getRunOnlyOnce() == 0) { $interval = $job->getTimeInterval(); $currTime = time(); $firetime = strtotime($job->getFireTime()) + $interval; while ($firetime < $currTime && $interval > 0) { $firetime += $interval; // only schedule jobs for the future } $job->setFireTime(date('Y-m-d H:i:s', $firetime)); } $job->setTimeLastFired(date('Y-m-d H:i:s')); $this->Scheduler_Job->save($job); try { if (!isset($tasks[$job->getTask()])) { throw new Zend_Exception('Unable to find task ' . $job->getTask()); } $log = call_user_func(array($modules[$tasks[$job->getTask()]['module']], $tasks[$job->getTask()]['method']), JsonComponent::decode($job->getParams())); if ($log && is_string($log) && $log != '') { $this->Scheduler_JobLog->saveLog($job, $log); } } catch (Zend_Exception $exc) { $job->setStatus(SCHEDULER_JOB_STATUS_FAILED); $this->Scheduler_Job->save($job); $this->Scheduler_JobLog->saveLog($job, $exc->getMessage() . ' - ' . $exc->getTraceAsString()); continue; } if ($job->getRunOnlyOnce() == 0) { $job->setStatus(SCHEDULER_JOB_STATUS_TORUN); } else { $job->setStatus(SCHEDULER_JOB_STATUS_DONE); } $this->Scheduler_Job->save($job); } $lastRunSetting = $this->Setting->getDaoByName('lastrun', $this->moduleName); if ($lastRunSetting) { $this->Setting->delete($lastRunSetting); } }
/** Test API submission process. */ public function testAllApiSubmissionProcess() { /** @var $settingModel SettingModel */ $settingModel = MidasLoader::loadModel('Setting'); // register (create user) $this->resetAll(); $this->params = array(); $this->params['securitykey'] = $settingModel->getValueByName(MIDAS_REMOTEPROCESSING_SECURITY_KEY_KEY, 'remoteprocessing'); $this->params['os'] = MIDAS_REMOTEPROCESSING_OS_WINDOWS; $this->request->setMethod('POST'); $this->dispatchUrl('/api/json?method=midas.remoteprocessing.registerserver'); $jsonResults = $this->getBody(); $this->resetAll(); $results = JsonComponent::decode($jsonResults); if ($results['stat'] !== 'ok') { $this->fail($results['message']); } $email = $results['data']['email']; $apikey = $results['data']['apikey']; // authenticate $this->params = array(); $this->params['securitykey'] = $settingModel->getValueByName(MIDAS_REMOTEPROCESSING_SECURITY_KEY_KEY, 'remoteprocessing'); $this->params['email'] = $email; $this->params['apikey'] = $apikey; $this->request->setMethod('POST'); $this->dispatchUrl('/api/json?method=midas.remoteprocessing.registerserver'); $jsonResults = $this->getBody(); $this->resetAll(); $results = JsonComponent::decode($jsonResults); if ($results['stat'] !== 'ok') { $this->fail($results['message']); } $token = $results['data']['token']; // ask action $this->params = array(); $this->params['token'] = $token; $this->params['os'] = '123'; $this->request->setMethod('POST'); $this->dispatchUrl('/api/json?method=midas.remoteprocessing.keepaliveserver'); $jsonResults = $this->getBody(); $this->resetAll(); $results = JsonComponent::decode($jsonResults); if ($results['stat'] !== 'ok') { $this->fail($results['message']); } if ($results['data']['action'] != 'wait') { $this->fail('Should be wait, was ' . $results['data']['action']); } // add a job $scriptParams['script'] = 'script'; $scriptParams['os'] = MIDAS_REMOTEPROCESSING_OS_WINDOWS; $scriptParams['condition'] = ''; $scriptParams['params'] = array(); Zend_Registry::get('notifier')->callback('CALLBACK_REMOTEPROCESSING_ADD_JOB', $scriptParams); $this->params = array(); $this->params['token'] = $token; $this->params['os'] = MIDAS_REMOTEPROCESSING_OS_WINDOWS; $this->request->setMethod('POST'); $this->dispatchUrl('/api/json?method=midas.remoteprocessing.keepaliveserver'); $jsonResults = $this->getBody(); $this->resetAll(); $results = JsonComponent::decode($jsonResults); if ($results['stat'] !== 'ok') { $this->fail($results['message']); } if ($results['data']['action'] != 'process') { $this->fail('Should be process, was ' . $results['data']['action']); } // send results $this->params = array(); $this->params['token'] = $token; $this->params['os'] = MIDAS_REMOTEPROCESSING_OS_WINDOWS; $this->request->setMethod('POST'); $this->dispatchUrl('/api/json?method=midas.remoteprocessing.resultsserver&testingmode=1'); $jsonResults = $this->getBody(); $this->resetAll(); $results = JsonComponent::decode($jsonResults); if ($results['stat'] !== 'ok') { $this->fail($results['message']); } }
/** * Submit login form. Will redirect the user to the redirect_uri on success. * * @param redirect_uri The client's desired redirect URI * @param login The user's login * @param password The user's password * @param allowOrDeny Whether to allow or deny the request. Set to 'Allow' to allow. * @param [state] Opaque state pointer string to be passed back to the client appended to the redirect URI * @throws Zend_Exception */ public function submitAction() { $this->disableLayout(); $this->disableView(); $redirectUri = $this->getParam('redirect_uri'); $scope = $this->getParam('scope'); $clientId = $this->getParam('client_id'); $state = $this->getParam('state'); $login = $this->getParam('login'); $password = $this->getParam('password'); $allow = $this->getParam('allowOrDeny'); if (!isset($clientId)) { throw new Zend_Exception('Must pass a client_id parameter', 400); } if (!isset($login)) { throw new Zend_Exception('Must pass a login parameter', 400); } if (!isset($password)) { throw new Zend_Exception('Must pass a password parameter', 400); } if (!isset($redirectUri)) { throw new Zend_Exception('Must pass a redirect_uri parameter', 400); } if (!isset($scope)) { $scope = JsonComponent::encode(array(MIDAS_API_PERMISSION_SCOPE_ALL)); } if ($allow !== 'Allow') { $url = $redirectUri; $url .= strpos($redirectUri, '?') === false ? '?' : '&'; $url .= 'error=access_denied'; if ($state) { $url .= '&state=' . $state; } echo JsonComponent::encode(array('status' => 'ok', 'redirect' => $url)); return; } $client = $this->Oauth_Client->load($clientId); if (!$client) { $url = $redirectUri; $url .= strpos($redirectUri, '?') === false ? '?' : '&'; $url .= 'error=invalid_request&error_description=' . urlencode('Invalid client_id'); if ($state) { $url .= '&state=' . $state; } echo JsonComponent::encode(array('status' => 'ok', 'redirect' => $url)); return; } $userDao = $this->User->getByEmail($login); if ($userDao === false) { echo JsonComponent::encode(array('status' => 'error', 'message' => 'Invalid username or password')); return; } $instanceSalt = Zend_Registry::get('configGlobal')->password->prefix; $passwordHash = hash($userDao->getHashAlg(), $instanceSalt . $userDao->getSalt() . $password); if ($this->User->hashExists($passwordHash)) { $codeDao = $this->Oauth_Code->create($userDao, $client, JsonComponent::decode($scope)); $url = $redirectUri; $url .= strpos($redirectUri, '?') === false ? '?' : '&'; $url .= 'code=' . $codeDao->getCode(); if ($state) { $url .= '&state=' . $state; } echo JsonComponent::encode(array('status' => 'ok', 'redirect' => $url)); return; } else { echo JsonComponent::encode(array('status' => 'error', 'message' => 'Invalid username or password')); return; } }
/** convertXmlREsults */ public function convertXmlREsults($xml) { /** @var Remoteprocessing_JobModel $jobModel */ $jobModel = MidasLoader::loadmodel('Job', 'remoteprocessing'); /** @var ItemModel $itemModel */ $itemModel = MidasLoader::loadmodel('Item'); $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); if (!$xml) { return; } $return = array(); $return['job'] = $jobModel->load((int) $xml->attributes()->id[0]); $return['params'] = JsonComponent::decode((string) $xml->JobParameters); $return['process'] = array(); $i = 1; foreach ($xml->Process as $process) { $tmp = array(); $tmp['status'] = (string) $process->attributes()->status[0]; $tmp['command'] = trim((string) $process->Command); $tmp['stderr'] = trim((string) $process->Error); $tmp['stdout'] = trim((string) $process->Output); $tmp['xmlStdout'] = simplexml_load_string($tmp['stdout'], 'SimpleXMLElement', LIBXML_NOCDATA); $tmp['time'] = (double) trim(str_replace('s', '', (string) $process->ExecutionTime)); // convert in milliseconds $tmp['output'] = array(); $tmp['parameters'] = array(); foreach ($return['params']['parametersList'] as $key => $parameter) { $tmp['parameters'][$key] = trim($return['params']['optionMatrix'][$i][$key]); } if (isset($return['params']['outputKeys'][$i])) { foreach ($return['params']['outputKeys'][$i] as $itemId) { $tmp['output'][] = $itemModel->load($itemId); } } $return['process'][] = $tmp; ++$i; } return $return; }
/** Test the checkshared action */ public function testCheckSharedAction() { $itemsFile = $this->loadData('Item', 'default'); $usersFile = $this->loadData('User', 'default'); $userWithPermission = $this->User->load($usersFile[0]->getKey()); $itemDao = $this->Item->load($itemsFile[1]->getKey()); $url = '/item/checkshared?itemId=' . $itemDao->getItemId(); $this->dispatchUrl($url, $userWithPermission); $resp = JsonComponent::decode($this->getBody()); $this->assertTrue($resp == false); }
/** * Test the submission of the login form, authorizing the client. */ public function testSubmitAction() { $user = $this->User->load(1); $this->User->changePassword($user, 'myPassword'); // easiest way to set the password $params = array('client_id' => '1000', 'login' => $user->getEmail(), 'password' => 'wrongPass', 'redirect_uri' => 'http://google.com'); $this->_testParamsRequired('/oauth/authorize/submit', $params); $scopes = array(MIDAS_API_PERMISSION_SCOPE_READ_USER_INFO, MIDAS_API_PERMISSION_SCOPE_WRITE_USER_INFO, MIDAS_API_PERMISSION_SCOPE_READ_DATA); // Test with incorrect password $this->resetAll(); $this->params = $params; $this->params['state'] = 'my_state_value'; $this->params['scope'] = JsonComponent::encode($scopes); $this->params['allowOrDeny'] = 'Allow'; $this->dispatchUrl('/oauth/authorize/submit', null); $json = JsonComponent::decode($this->getBody()); $this->assertEquals($json['status'], 'error'); $this->assertEquals($json['message'], 'Invalid username or password'); // Test user denying the request $this->resetAll(); $this->params = $params; $this->params['state'] = 'my_state_value'; $this->params['scope'] = JsonComponent::encode($scopes); $this->params['allowOrDeny'] = 'Deny'; $this->dispatchUrl('/oauth/authorize/submit', null); $json = JsonComponent::decode($this->getBody()); $this->assertEquals($json['status'], 'ok'); $this->assertEquals($json['redirect'], $params['redirect_uri'] . '?error=access_denied&state=' . $this->params['state']); // Test user allowing the request $this->resetAll(); $this->params = $params; $this->params['state'] = 'my_state_value'; $this->params['scope'] = JsonComponent::encode($scopes); $this->params['allowOrDeny'] = 'Allow'; $this->params['password'] = '******'; $this->dispatchUrl('/oauth/authorize/submit', null); /** @var Oauth_CodeModel $codeModel */ $codeModel = MidasLoader::loadModel('Code', 'oauth'); $codeDaos = $codeModel->getByUser($user); $codeDao = end($codeDaos); $json = JsonComponent::decode($this->getBody()); $this->assertEquals($json['status'], 'ok'); $this->assertEquals($json['redirect'], $params['redirect_uri'] . '?code=' . $codeDao->getCode() . '&state=' . $this->params['state']); }