public function refreshTokenCallback($accessToken, $refreshToken)
 {
     $account = $this->configuration->getAccount($this->accountId);
     $account->setAccessToken($accessToken);
     $account->setRefreshToken($refreshToken);
     $account->save();
 }
 public function getRefreshToken()
 {
     try {
         return $this->configuration->getEncryptor()->decrypt($this->getAttribute('refreshToken'));
     } catch (\Exception $e) {
         return null;
     }
 }
 public function oauthCallbackAction()
 {
     $session = $this->get('session');
     $token = $session->get('token');
     $accountId = $session->get('account');
     $referrer = $session->get('referrer');
     $external = $session->get('external');
     if ($token == null) {
         throw new UserException("Your session expired, please try again");
     }
     $code = $this->get('request')->query->get('code');
     if (empty($code)) {
         throw new UserException('Could not read from Google API, please try again');
     }
     $googleApi = $this->getGoogleApi();
     try {
         $storageApi = new StorageApi(array('token' => $token, 'userAgent' => $this->componentName));
         /** @var ObjectEncryptor $encryptor */
         $encryptor = $this->get('syrup.object_encryptor');
         $configuration = new Configuration($this->componentName, $encryptor);
         $configuration->setStorageApi($storageApi);
         $tokens = $googleApi->authorize($code, $this->container->get('router')->generate('keboola_google_drive_writer_oauth_callback', array(), UrlGeneratorInterface::ABSOLUTE_URL));
         $googleApi->setCredentials($tokens['access_token'], $tokens['refresh_token']);
         $userData = json_decode($googleApi->request('/oauth2/v2/userinfo')->getBody(), true);
         if ($external) {
             $this->container->get('session')->clear();
             $referrer .= strstr($referrer, '?') ? '&' : '?';
             $referrer .= 'access-token=' . urlencode($this->container->get('syrup.encryptor')->encrypt($tokens['access_token'])) . '&refresh-token=' . urlencode($this->container->get('syrup.encryptor')->encrypt($tokens['refresh_token'])) . '&email=' . $userData['email'];
             return new RedirectResponse($referrer);
         } else {
             $account = $configuration->getAccountBy('accountId', $accountId);
             if (null == $account) {
                 throw new ConfigurationException("Account doesn't exist");
             }
             $account->setGoogleId($userData['id'])->setGoogleName($userData['name'])->setEmail($userData['email'])->setAccessToken($tokens['access_token'])->setRefreshToken($tokens['refresh_token'])->save();
         }
         $this->container->get('session')->clear();
         if ($referrer) {
             return new RedirectResponse($referrer);
         } else {
             return new JsonResponse(array('status' => 'ok'));
         }
     } catch (\Exception $e) {
         throw new SyrupComponentException(500, 'Could not save API tokens', $e);
     }
 }
 public function testRunExternal()
 {
     $processedFiles = $this->storageApiClient->listFiles((new ListFilesOptions())->setTags(['wr-google-drive-processed']));
     foreach ($processedFiles as $f) {
         $this->storageApiClient->deleteFileTag($f['id'], 'wr-google-drive-processed');
     }
     $job = $this->processJob($this->componentName . '/run', ['external' => ['account' => ['email' => $this->email, 'accessToken' => $this->encryptor->encrypt($this->accessToken), 'refreshToken' => $this->encryptor->encrypt($this->refreshToken)], 'query' => '+tags:tde', 'targetFolder' => '0B8ceg4OWLR3ld0czTWxfd3RmQnc']]);
     $this->assertEquals('success', $job->getStatus());
     // test if external account was deleted
     $accounts = $this->configuration->getAccounts();
     /** @var Account $account */
     foreach ($accounts as $account) {
         $this->assertNotContains('external', $account->getAccountId());
     }
 }
 public function execute(Job $job)
 {
     $this->configuration->setStorageApi($this->storageApi);
     $accounts = $this->configuration->getAccounts();
     $options = $job->getParams();
     $status = [];
     if (isset($options['external'])) {
         // load files by tag from SAPI
         if (!isset($options['external']['account'])) {
             throw new UserException("Missing field 'account'");
         }
         try {
             $this->configuration->create();
         } catch (\Exception $e) {
             // create configuration if not exists
         }
         $account = new Account($this->configuration, uniqid('external'));
         $account->fromArray($options['external']['account']);
         $writer = $this->writerFactory->create($account);
         if (!isset($options['external']['query'])) {
             throw new UserException("Missing field 'query'");
         }
         $queryString = $options['external']['query'];
         $queryString .= ' -tags:wr-google-drive-processed';
         if (isset($options['external']['filterByRunId']) && $options['external']['filterByRunId']) {
             $parentRunId = $this->getParentRunId($job->getRunId());
             if ($parentRunId) {
                 $queryString .= ' +tags:runId-' . $parentRunId;
             }
         }
         $uploadedFiles = $this->storageApi->listFiles((new ListFilesOptions())->setQuery($queryString));
         if (empty($uploadedFiles)) {
             throw new UserException("No file matches your query '" . $queryString . "'");
         }
         foreach ($uploadedFiles as $uploadedFile) {
             $tmpFile = $this->temp->createTmpFile('wr-gd');
             file_put_contents($tmpFile->getPathname(), fopen($uploadedFile['url'], 'r'));
             $file = new File(['id' => $uploadedFile['id'], 'title' => $uploadedFile['name'], 'targetFolder' => isset($options['external']['targetFolder']) ? $options['external']['targetFolder'] : null, 'type' => File::TYPE_FILE, 'pathname' => $tmpFile, 'size' => $uploadedFile['sizeBytes']]);
             $gdFiles = $writer->listFiles(['q' => "trashed=false and name='" . $uploadedFile['name'] . "'"]);
             if (!empty($gdFiles['files'])) {
                 $lastGdFile = array_shift($gdFiles['files']);
                 $file->setGoogleId($lastGdFile['id']);
             }
             $file = $writer->process($file);
             // tag file 'wr-google-drive-processed'
             $this->storageApi->addFileTag($uploadedFile['id'], 'wr-google-drive-processed');
         }
         // delete temporary account
         $this->configuration->removeAccount($account->getAccountId());
     } else {
         $fileFilter = null;
         if (isset($options['config'])) {
             if (!isset($accounts[$options['config']])) {
                 throw new UserException("Config '" . $options['config'] . "' does not exist.");
             }
             $accounts = [$options['config'] => $accounts[$options['config']]];
             if (isset($options['file'])) {
                 /** @var Account $account */
                 $account = $accounts[$options['config']];
                 if (null == $account->getFile($options['file'])) {
                     throw new UserException("File '" . $options['file'] . "' not found");
                 }
                 $fileFilter = $options['file'];
             }
         }
         /** @var Account $account */
         foreach ($accounts as $accountId => $account) {
             $writer = $this->writerFactory->create($account);
             $files = $account->getFiles();
             /** @var File $file */
             foreach ($files as $file) {
                 if ($fileFilter != null && $file->getId() != $fileFilter) {
                     continue;
                 }
                 $file->setPathname($this->temp->createTmpFile()->getPathname());
                 try {
                     $tableExporter = new TableExporter($this->storageApi);
                     $tableExporter->exportTable($file->getTableId(), $file->getPathname(), []);
                 } catch (ClientException $e) {
                     throw new UserException($e->getMessage(), $e, ['file' => $file->toArray()]);
                 }
                 $file = $writer->process($file);
                 $status[$account->getAccountName()][$file->getTitle()] = 'ok';
             }
             // updated changes to files
             $account->save();
         }
     }
     return $status;
 }
 /**
  * @param $accountId
  * @param $fileId
  * @return JsonResponse
  */
 public function deleteFileAction($accountId, $fileId)
 {
     $this->configuration->deleteFile($accountId, $fileId);
     return $this->createJsonResponse([], 204);
 }