/**
  * @param Request $request
  * @param Closure $next
  *
  * @return array|mixed|string
  */
 public function handle($request, Closure $next)
 {
     //  Allow console requests through
     if (env('DF_IS_VALID_CONSOLE_REQUEST', false)) {
         return $next($request);
     }
     try {
         static::setExceptions();
         if (static::isAccessAllowed()) {
             return $next($request);
         } elseif (static::isException($request)) {
             //API key and/or (non-admin) user logged in, but if access is still not allowed then check for exception case.
             return $next($request);
         } else {
             $apiKey = Session::getApiKey();
             $token = Session::getSessionToken();
             if (empty($apiKey) && empty($token)) {
                 throw new BadRequestException('Bad request. No token or api key provided.');
             } elseif (true === Session::get('token_expired')) {
                 throw new UnauthorizedException(Session::get('token_expired_msg'));
             } elseif (!Session::isAuthenticated()) {
                 throw new UnauthorizedException('Unauthorized.');
             } else {
                 throw new ForbiddenException('Access Forbidden.');
             }
         }
     } catch (\Exception $e) {
         return ResponseFactory::getException($e, $request);
     }
 }
 public function index()
 {
     $uri = static::getURI($_SERVER);
     $dist = env('DF_INSTALL', '');
     if (empty($dist) && false !== stripos(env('DB_DATABASE', ''), 'bitnami')) {
         $dist = 'Bitnami';
     }
     $appCount = App::all()->count();
     $adminCount = User::whereIsSysAdmin(1)->count();
     $userCount = User::whereIsSysAdmin(0)->count();
     $serviceCount = Service::all()->count();
     $roleCount = Role::all()->count();
     $status = ["uri" => $uri, "managed" => env('DF_MANAGED', false), "dist" => $dist, "demo" => Environment::isDemoApplication(), "version" => \Config::get('df.version'), "host_os" => PHP_OS, "resources" => ["app" => $appCount, "admin" => $adminCount, "user" => $userCount, "service" => $serviceCount, "role" => $roleCount]];
     return ResponseFactory::sendResponse(ResponseFactory::create($status));
 }
Example #3
0
 /**
  * Handles GET action
  *
  * @return array
  * @throws NotFoundException
  */
 protected function handleGET()
 {
     if (empty($this->resource)) {
         $service = $this->request->getParameter('service');
         $type = $this->request->getParameter('type');
         $onlyScripted = $this->request->getParameterAsBool('only_scripted');
         if ($onlyScripted) {
             switch ($type) {
                 case 'process':
                     $scripts = EventScript::where('affects_process', 1)->lists('name')->all();
                     break;
                 case 'broadcast':
                     $scripts = EventScript::where('affects_process', 0)->lists('name')->all();
                     break;
                 default:
                     $scripts = EventScript::lists('name')->all();
                     break;
             }
             return ResourcesWrapper::cleanResources(array_values(array_unique($scripts)));
         }
         $results = $this->getEventMap();
         $allEvents = [];
         switch ($type) {
             case 'process':
                 $results = ArrayUtils::get($results, 'process', []);
                 foreach ($results as $serviceKey => $apis) {
                     if (!empty($service) && 0 !== strcasecmp($service, $serviceKey)) {
                         unset($results[$serviceKey]);
                     } else {
                         foreach ($apis as $path => $operations) {
                             foreach ($operations['verb'] as $method => $events) {
                                 $allEvents = array_merge($allEvents, $events);
                             }
                         }
                     }
                 }
                 break;
             case 'broadcast':
                 $results = ArrayUtils::get($results, 'broadcast', []);
                 foreach ($results as $serviceKey => $apis) {
                     if (!empty($service) && 0 !== strcasecmp($service, $serviceKey)) {
                         unset($results[$serviceKey]);
                     } else {
                         foreach ($apis as $path => $operations) {
                             foreach ($operations['verb'] as $method => $events) {
                                 $allEvents = array_merge($allEvents, $events);
                             }
                         }
                     }
                 }
                 break;
             default:
                 foreach ($results as $type => $services) {
                     foreach ($services as $serviceKey => $apis) {
                         if (!empty($service) && 0 !== strcasecmp($service, $serviceKey)) {
                             unset($results[$type][$serviceKey]);
                         } else {
                             foreach ($apis as $path => $operations) {
                                 foreach ($operations['verb'] as $method => $events) {
                                     $allEvents = array_merge($allEvents, $events);
                                 }
                             }
                         }
                     }
                 }
                 break;
         }
         if (!$this->request->getParameterAsBool(ApiOptions::AS_LIST)) {
             return $results;
         }
         return ResourcesWrapper::cleanResources(array_values(array_unique($allEvents)));
     }
     $related = $this->request->getParameter(ApiOptions::RELATED);
     if (!empty($related)) {
         $related = explode(',', $related);
     } else {
         $related = [];
     }
     //	Single script by name
     $fields = [ApiOptions::FIELDS_ALL];
     if (null !== ($value = $this->request->getParameter(ApiOptions::FIELDS))) {
         $fields = explode(',', $value);
     }
     if (null === ($foundModel = EventScript::with($related)->find($this->resource, $fields))) {
         throw new NotFoundException("Script not found.");
     }
     return ResponseFactory::create($foundModel->toArray(), $this->nativeFormat);
 }
Example #4
0
 /**
  * @param string $method
  * @param string $path
  * @param array  $payload
  * @param array  $curlOptions Additional CURL options for external requests
  *
  * @return array
  */
 public static function inlineRequest($method, $path, $payload = null, $curlOptions = [])
 {
     if (null === $payload || 'null' == $payload) {
         $payload = [];
     }
     if (!empty($curlOptions)) {
         $options = [];
         foreach ($curlOptions as $key => $value) {
             if (!is_numeric($key)) {
                 if (defined($key)) {
                     $options[constant($key)] = $value;
                 }
             }
         }
         $curlOptions = $options;
         unset($options);
     }
     try {
         if ('https:/' == ($protocol = substr($path, 0, 7)) || 'http://' == $protocol) {
             $result = static::externalRequest($method, $path, $payload, $curlOptions);
         } else {
             $result = null;
             $params = [];
             if (false !== ($pos = strpos($path, '?'))) {
                 $paramString = substr($path, $pos + 1);
                 if (!empty($paramString)) {
                     $pArray = explode('&', $paramString);
                     foreach ($pArray as $k => $p) {
                         if (!empty($p)) {
                             $tmp = explode('=', $p);
                             $name = ArrayUtils::get($tmp, 0, $k);
                             $value = ArrayUtils::get($tmp, 1);
                             $params[$name] = urldecode($value);
                         }
                     }
                 }
                 $path = substr($path, 0, $pos);
             }
             if (false === ($pos = strpos($path, '/'))) {
                 $serviceName = $path;
                 $resource = null;
             } else {
                 $serviceName = substr($path, 0, $pos);
                 $resource = substr($path, $pos + 1);
                 //	Fix removal of trailing slashes from resource
                 if (!empty($resource)) {
                     if (false === strpos($path, '?') && '/' === substr($path, strlen($path) - 1, 1) || '/' === substr($path, strpos($path, '?') - 1, 1)) {
                         $resource .= '/';
                     }
                 }
             }
             if (empty($serviceName)) {
                 return null;
             }
             $format = DataFormats::PHP_ARRAY;
             if (!is_array($payload)) {
                 $format = DataFormats::TEXT;
             }
             Session::checkServicePermission($method, $serviceName, $resource, ServiceRequestorTypes::SCRIPT);
             $request = new ScriptServiceRequest($method, $params);
             $request->setContent($payload, $format);
             //  Now set the request object and go...
             $service = ServiceHandler::getService($serviceName);
             $result = $service->handleRequest($request, $resource);
         }
     } catch (\Exception $ex) {
         $result = ResponseFactory::create($ex);
         Log::error('Exception: ' . $ex->getMessage(), ['response' => $result]);
     }
     return ResponseFactory::sendScriptResponse($result);
 }
Example #5
0
 /**
  * Handle an incoming request.
  *
  * @param  \Illuminate\Http\Request $request
  * @param  \Closure                 $next
  *
  * @return mixed
  */
 public function handle($request, Closure $next)
 {
     //Get the Console API Key
     $consoleApiKey = AccessCheck::getConsoleApiKey($request);
     // Get limits
     if (config('df.standalone') === true || $consoleApiKey === Managed::getConsoleKey()) {
         return $next($request);
     } else {
         $limits = Managed::getLimits();
         // The limits array comes across from the console as a bunch of Std Objects, need to turn it back
         // into an array
         $limits['api'] = (array) $limits['api'];
         foreach (array_keys($limits['api']) as $key) {
             $limits['api'][$key] = (array) $limits['api'][$key];
         }
     }
     if (!empty($limits) && is_null($this->_getServiceName()) === false) {
         $this->_inUnitTest = \Config::get('api_limits_test');
         $userName = $this->_getUser(Session::getCurrentUserId());
         $userRole = $this->_getRole(Session::getRoleId());
         $apiName = $this->_getApiKey(Session::getApiKey());
         $serviceName = $this->_getServiceName();
         $clusterName = Managed::getClusterName();
         // Build the list of API Hits to check
         $apiKeysToCheck = ['cluster.default' => 0, 'instance.default' => 0];
         $serviceKeys[$serviceName] = 0;
         if (is_null($userRole) === false) {
             $serviceKeys[$serviceName . '.' . $userRole] = 0;
         }
         if (is_null($userName) === false) {
             $serviceKeys[$serviceName . '.' . $userName] = 0;
         }
         if (is_null($apiName) === false) {
             $apiKeysToCheck[$apiName] = 0;
             if (is_null($userRole) === false) {
                 $apiKeysToCheck[$apiName . '.' . $userRole] = 0;
             }
             if (is_null($userName) === false) {
                 $apiKeysToCheck[$apiName . '.' . $userName] = 0;
             }
             foreach ($serviceKeys as $key => $value) {
                 $apiKeysToCheck[$apiName . '.' . $key] = $value;
             }
         }
         if (is_null($clusterName) === false) {
             $apiKeysToCheck[$clusterName] = 0;
             if (is_null($userRole) === false) {
                 $apiKeysToCheck[$clusterName . '.' . $userRole] = 0;
             }
             if (is_null($userName) === false) {
                 $apiKeysToCheck[$clusterName . '.' . $userName] = 0;
             }
             foreach ($serviceKeys as $key => $value) {
                 $apiKeysToCheck[$clusterName . '.' . $key] = $value;
             }
         }
         if (is_null($userName) === false) {
             $apiKeysToCheck[$userName] = 0;
         }
         if (is_null($userRole) === false) {
             $apiKeysToCheck[$userRole] = 0;
         }
         $apiKeysToCheck = array_merge($apiKeysToCheck, $serviceKeys);
         $timePeriods = ['minute', 'hour', 'day', '7-day', '30-day'];
         $overLimit = false;
         try {
             foreach (array_keys($apiKeysToCheck) as $key) {
                 foreach ($timePeriods as $period) {
                     $keyToCheck = $key . '.' . $period;
                     if (array_key_exists($keyToCheck, $limits['api']) === true) {
                         $cacheValue = \Cache::get($keyToCheck, 0);
                         $cacheValue++;
                         \Cache::put($keyToCheck, $cacheValue, $limits['api'][$keyToCheck]['period']);
                         if ($cacheValue > $limits['api'][$keyToCheck]['limit']) {
                             $overLimit = true;
                         }
                     }
                 }
             }
         } catch (\Exception $e) {
             return ResponseFactory::getException(new InternalServerErrorException('Unable to update cache'), $request);
         }
         if ($overLimit === true) {
             return ResponseFactory::getException(new TooManyRequestsException('Specified connection limit exceeded'), $request);
         }
     }
     return $next($request);
 }
 /**
  * @param Request $request
  * @param Closure $next
  *
  * @return array|mixed|string
  */
 public function handle($request, Closure $next)
 {
     try {
         static::setExceptions();
         //Get the api key.
         $apiKey = static::getApiKey($request);
         Session::setApiKey($apiKey);
         $appId = App::getAppIdByApiKey($apiKey);
         //Get the JWT.
         $token = static::getJwt($request);
         Session::setSessionToken($token);
         //Get the Console API Key
         $consoleApiKey = static::getConsoleApiKey($request);
         //Check for basic auth attempt.
         $basicAuthUser = $request->getUser();
         $basicAuthPassword = $request->getPassword();
         if (config('df.managed') && !empty($consoleApiKey) && $consoleApiKey === Managed::getConsoleKey()) {
             //DFE Console request
             return $next($request);
         } elseif (!empty($basicAuthUser) && !empty($basicAuthPassword)) {
             //Attempting to login using basic auth.
             Auth::onceBasic();
             /** @var User $authenticatedUser */
             $authenticatedUser = Auth::user();
             if (!empty($authenticatedUser)) {
                 $userId = $authenticatedUser->id;
                 Session::setSessionData($appId, $userId);
             } else {
                 throw new UnauthorizedException('Unauthorized. User credentials did not match.');
             }
         } elseif (!empty($token)) {
             //JWT supplied meaning an authenticated user session/token.
             try {
                 JWTAuth::setToken($token);
                 /** @type Payload $payload */
                 $payload = JWTAuth::getPayload();
                 JWTUtilities::verifyUser($payload);
                 $userId = $payload->get('user_id');
                 Session::setSessionData($appId, $userId);
             } catch (TokenExpiredException $e) {
                 JWTUtilities::clearAllExpiredTokenMaps();
                 if (!static::isException($request)) {
                     throw new UnauthorizedException($e->getMessage());
                 }
             } catch (TokenBlacklistedException $e) {
                 throw new ForbiddenException($e->getMessage());
             } catch (TokenInvalidException $e) {
                 throw new BadRequestException('Invalid token: ' . $e->getMessage(), 401);
             }
         } elseif (!empty($apiKey)) {
             //Just Api Key is supplied. No authenticated session
             Session::setSessionData($appId);
         } elseif (static::isException($request)) {
             //Path exception.
             return $next($request);
         } else {
             throw new BadRequestException('Bad request. No token or api key provided.');
         }
         if (static::isAccessAllowed()) {
             return $next($request);
         } elseif (static::isException($request)) {
             //API key and/or (non-admin) user logged in, but if access is still not allowed then check for exception case.
             return $next($request);
         } else {
             if (!Session::isAuthenticated()) {
                 throw new UnauthorizedException('Unauthorized.');
             } else {
                 throw new ForbiddenException('Access Forbidden.');
             }
         }
     } catch (\Exception $e) {
         return ResponseFactory::getException($e, $request);
     }
 }
Example #7
0
 /**
  * @return ServiceResponseInterface
  */
 protected function respond()
 {
     if ($this->response instanceof ServiceResponseInterface) {
         return $this->response;
     } elseif ($this->response instanceof RedirectResponse) {
         return $this->response;
     }
     return ResponseFactory::create($this->response, $this->nativeFormat);
 }
Example #8
0
 /**
  * @throws \DreamFactory\Core\Exceptions\RestException
  * @return bool
  */
 protected function processRequest()
 {
     $data = $this->request->getContent();
     $resource = !empty($this->resourcePath) ? ltrim($this->resourcePath, '/') : null;
     if ($resource) {
         $this->url = rtrim($this->baseUrl, '/') . '/' . $resource;
     } else {
         $this->url = $this->baseUrl;
     }
     if (!empty($this->query)) {
         $splicer = false === strpos($this->baseUrl, '?') ? '?' : '&';
         $this->url .= $splicer . $this->query;
     }
     $cacheKey = '';
     if ($this->cacheEnabled) {
         switch ($this->action) {
             case Verbs::GET:
                 // build cache_key
                 $cacheKey = $this->action . ':' . $this->name;
                 if ($resource) {
                     $cacheKey .= ':' . $resource;
                 }
                 if (!empty($this->cacheQuery)) {
                     $cacheKey .= ':' . $this->cacheQuery;
                 }
                 $cacheKey = hash('sha256', $cacheKey);
                 if (null !== ($result = $this->getFromCache($cacheKey))) {
                     return $result;
                 }
                 break;
         }
     }
     Log::debug('Outbound HTTP request: ' . $this->action . ': ' . $this->url);
     Curl::setDecodeToArray(true);
     $result = Curl::request($this->action, $this->url, $data, $this->curlOptions);
     if (false === $result) {
         $error = Curl::getError();
         throw new RestException(ArrayUtils::get($error, 'code', 500), ArrayUtils::get($error, 'message'));
     }
     $status = Curl::getLastHttpCode();
     if ($status >= 300) {
         if (!is_string($result)) {
             $result = json_encode($result);
         }
         throw new RestException($status, $result, $status);
     }
     $contentType = Curl::getInfo('content_type');
     $format = DataFormats::fromMimeType($contentType);
     $response = ResponseFactory::create($result, $format, $status, $contentType);
     if ($this->cacheEnabled) {
         switch ($this->action) {
             case Verbs::GET:
                 $this->addToCache($cacheKey, $result);
                 break;
         }
     }
     return $response;
 }
Example #9
0
 /**
  * @param Request  $request
  * @param \Closure $next
  *
  * @return array|mixed|string
  */
 public function handle(Request $request, \Closure $next)
 {
     if (!in_array($route = $request->getPathInfo(), ['/setup', '/setup_db'])) {
         try {
             $apiKey = static::getApiKey($request);
             Session::setApiKey($apiKey);
             $appId = App::getAppIdByApiKey($apiKey);
             //Get the JWT.
             $token = static::getJwt($request);
             Session::setSessionToken($token);
             //Check for basic auth attempt.
             $basicAuthUser = $request->getUser();
             $basicAuthPassword = $request->getPassword();
             if (!empty($basicAuthUser) && !empty($basicAuthPassword)) {
                 //Attempting to login using basic auth.
                 Auth::onceBasic();
                 /** @var User $authenticatedUser */
                 $authenticatedUser = Auth::user();
                 if (!empty($authenticatedUser)) {
                     $userId = $authenticatedUser->id;
                     Session::setSessionData($appId, $userId);
                 } else {
                     throw new UnauthorizedException('Unauthorized. User credentials did not match.');
                 }
             } elseif (!empty($token)) {
                 //JWT supplied meaning an authenticated user session/token.
                 /**
                  * Note: All caught exception from JWT are stored in session variables.
                  * These are later checked and handled appropriately in the AccessCheck middleware.
                  *
                  * This is to allow processing API calls that do not require any valid
                  * authenticated session. For example POST user/session to login,
                  * PUT user/session to refresh old JWT, GET system/environment etc.
                  *
                  * This also allows for auditing API calls that are called by not permitted/processed.
                  * It also allows counting unauthorized API calls against Enterprise Console limits.
                  */
                 try {
                     JWTAuth::setToken($token);
                     /** @type Payload $payload */
                     $payload = JWTAuth::getPayload();
                     JWTUtilities::verifyUser($payload);
                     $userId = $payload->get('user_id');
                     Session::setSessionData($appId, $userId);
                 } catch (TokenExpiredException $e) {
                     JWTUtilities::clearAllExpiredTokenMaps();
                     Session::set('token_expired', true);
                     Session::set('token_expired_msg', $e->getMessage());
                 } catch (TokenBlacklistedException $e) {
                     Session::set('token_blacklisted', true);
                     Session::set('token_blacklisted_msg', $e->getMessage());
                 } catch (TokenInvalidException $e) {
                     Session::set('token_invalid', true);
                     Session::set('token_invalid_msg', 'Invalid token: ' . $e->getMessage());
                 }
             } elseif (!empty($apiKey)) {
                 //Just Api Key is supplied. No authenticated session
                 Session::setSessionData($appId);
             }
             return $next($request);
         } catch (\Exception $e) {
             return ResponseFactory::getException($e, $request);
         }
     }
     return $next($request);
 }
Example #10
0
 /**
  * Handles POST actions.
  *
  * @return \DreamFactory\Core\Utility\ServiceResponse
  * @throws BadRequestException
  * @throws InternalServerErrorException
  * @throws \Exception
  */
 protected function handlePOST()
 {
     if (empty($this->filePath)) {
         // create folders and files
         // possible file handling parameters
         $extract = $this->request->getParameterAsBool('extract', false);
         $clean = $this->request->getParameterAsBool('clean', false);
         $checkExist = $this->request->getParameterAsBool('check_exist', false);
         $fileNameHeader = $this->request->getHeader('X-File-Name');
         $folderNameHeader = $this->request->getHeader('X-Folder-Name');
         $fileUrl = filter_var($this->request->getParameter('url', ''), FILTER_SANITIZE_URL);
         if (!empty($fileNameHeader)) {
             // html5 single posting for file create
             $result = $this->handleFileContent($this->folderPath, $fileNameHeader, $this->request->getContent(), $this->request->getContentType(), $extract, $clean, $checkExist);
         } elseif (!empty($folderNameHeader)) {
             // html5 single posting for folder create
             $fullPathName = $this->folderPath . $folderNameHeader;
             $content = $this->request->getPayloadData();
             $this->driver->createFolder($this->container, $fullPathName, $content);
             $result = ['name' => $folderNameHeader, 'path' => $fullPathName];
         } elseif (!empty($fileUrl)) {
             // upload a file from a url, could be expandable zip
             $tmpName = null;
             try {
                 $tmpName = FileUtilities::importUrlFileToTemp($fileUrl);
                 $result = $this->handleFile($this->folderPath, '', $tmpName, '', $extract, $clean, $checkExist);
                 @unlink($tmpName);
             } catch (\Exception $ex) {
                 if (!empty($tmpName)) {
                     @unlink($tmpName);
                 }
                 throw $ex;
             }
         } elseif (null !== ($uploadedFiles = $this->request->getFile('files'))) {
             // older html multi-part/form-data post, single or multiple files
             $files = FileUtilities::rearrangePostedFiles($uploadedFiles);
             $result = $this->handleFolderContentFromFiles($files, $extract, $clean, $checkExist);
             $result = ResourcesWrapper::cleanResources($result);
         } else {
             // possibly xml or json post either of files or folders to create, copy or move
             if (!empty($data = ResourcesWrapper::unwrapResources($this->getPayloadData()))) {
                 $result = $this->handleFolderContentFromData($data, $extract, $clean, $checkExist);
                 $result = ResourcesWrapper::cleanResources($result);
             } else {
                 // create folder from resource path
                 $this->driver->createFolder($this->container, $this->folderPath);
                 $result = ['name' => basename($this->folderPath), 'path' => $this->folderPath];
             }
         }
     } else {
         // create the file
         // possible file handling parameters
         $extract = $this->request->getParameterAsBool('extract', false);
         $clean = $this->request->getParameterAsBool('clean', false);
         $checkExist = $this->request->getParameterAsBool('check_exist', false);
         $name = basename($this->filePath);
         $path = dirname($this->filePath);
         $files = $this->request->getFile('files');
         if (empty($files)) {
             // direct load from posted data as content
             // or possibly xml or json post of file properties create, copy or move
             $result = $this->handleFileContent($path, $name, $this->request->getContent(), $this->request->getContentType(), $extract, $clean, $checkExist);
         } else {
             // older html multipart/form-data post, should be single file
             $files = FileUtilities::rearrangePostedFiles($files);
             if (1 < count($files)) {
                 throw new BadRequestException("Multiple files uploaded to a single REST resource '{$name}'.");
             }
             $file = ArrayUtils::get($files, 0);
             if (empty($file)) {
                 throw new BadRequestException("No file uploaded to REST resource '{$name}'.");
             }
             $error = $file['error'];
             if (UPLOAD_ERR_OK == $error) {
                 $result = $this->handleFile($path, $name, $file["tmp_name"], $file['type'], $extract, $clean, $checkExist);
             } else {
                 throw new InternalServerErrorException("Failed to upload file {$name}.\n{$error}");
             }
         }
     }
     return ResponseFactory::create($result, $this->nativeFormat, ServiceResponseInterface::HTTP_CREATED);
 }
Example #11
0
 /**
  * @param \Exception               $e
  * @param \Illuminate\Http\Request $request
  *
  * @return array|mixed|string
  */
 public static function getException($e, $request)
 {
     $response = ResponseFactory::create($e);
     $accepts = explode(',', $request->header('ACCEPT'));
     return ResponseFactory::sendResponse($response, $accepts);
 }
 /**
  * Handle an incoming request.
  *
  * @param  \Illuminate\Http\Request $request
  * @param  \Closure                 $next
  *
  * @return mixed
  */
 public function handle(Request $request, Closure $next)
 {
     /**
      * It is assumed, if you get this far, that ClusterServiceProvider was registered via
      * the ManagedInstance bootstrapper. If not, you're in a world of shit.
      *
      * We use provider's service() method because Facades are not loaded yet
      */
     $_cluster = ClusterServiceProvider::service();
     //  Get limits or bail
     if (!$_cluster instanceof ProvidesManagedLimits || empty($limits = $_cluster->getLimits())) {
         return $next($request);
     }
     $this->testing = config('api_limits_test', 'testing' == env('APP_ENV'));
     if (!empty($limits)) {
         $userName = $this->getUser(Session::getCurrentUserId());
         $userRole = $this->getRole(Session::getRoleId());
         $apiName = $this->getApiKey(Session::getApiKey());
         $clusterName = $_cluster->getClusterId();
         $instanceName = $_cluster->getInstanceName();
         $serviceName = $this->getServiceName($request);
         $limits = json_encode($limits);
         //TODO: Update dfe-console to properly set this, but right now, we want to touch as few files as possible
         if (!$this->testing) {
             $limits = str_replace(['cluster.default', 'instance.default'], [$clusterName, $clusterName . '.' . $instanceName], $limits);
         }
         //  Convert to an array
         $limits = json_decode($limits, true);
         //  Build the list of API Hits to check
         $apiKeysToCheck = [$clusterName . '.' . $instanceName => 0];
         $serviceKeys = [];
         if ($serviceName) {
             $serviceKeys[$serviceName] = 0;
             $userRole && ($serviceKeys[$serviceName . '.' . $userRole] = 0);
             $userName && ($serviceKeys[$serviceName . '.' . $userName] = 0);
         }
         if ($apiName) {
             $apiKeysToCheck[$clusterName . '.' . $instanceName . '.' . $apiName] = 0;
             $userRole && ($apiKeysToCheck[$clusterName . '.' . $instanceName . '.' . $apiName . '.' . $userRole] = 0);
             $userName && ($apiKeysToCheck[$clusterName . '.' . $instanceName . '.' . $apiName . '.' . $userName] = 0);
             foreach ($serviceKeys as $key => $value) {
                 $apiKeysToCheck[$apiName . '.' . $key] = $value;
             }
         }
         if ($clusterName) {
             $apiKeysToCheck[$clusterName] = 0;
             $userRole && ($apiKeysToCheck[$clusterName . '.' . $instanceName . '.' . $userRole] = 0);
             $userName && ($apiKeysToCheck[$clusterName . '.' . $instanceName . '.' . $userName] = 0);
             foreach ($serviceKeys as $key => $value) {
                 $apiKeysToCheck[$clusterName . '.' . $instanceName . '.' . $key] = $value;
             }
         }
         /* Per Ben, we want to increment every limit they hit, not stop after the first one */
         $overLimit = [];
         try {
             foreach (array_keys($apiKeysToCheck) as $key) {
                 foreach ($this->periods as $period) {
                     $_checkKey = $key . '.' . $period;
                     /** @noinspection PhpUndefinedMethodInspection */
                     if (array_key_exists($_checkKey, $limits['api'])) {
                         $_limit = $limits['api'][$_checkKey];
                         // For any cache drivers that make use of the cache prefix, we need to make sure we use
                         // a prefix that every instance can see.  But first, grab the current value
                         $dfCachePrefix = env('DF_CACHE_PREFIX');
                         putenv('DF_CACHE_PREFIX' . '=' . 'df_limits');
                         $_ENV['DF_CACHE_PREFIX'] = $_SERVER['DF_CACHE_PREFIX'] = 'df_limits';
                         //  Increment counter
                         $cacheValue = $this->cache()->get($_checkKey, 0);
                         $cacheValue++;
                         if ($cacheValue > $_limit['limit']) {
                             // Push the name of the rule onto the over-limit array so we can give the name in the 429 error message
                             $overLimit[] = array_get($_limit, 'name', $_checkKey);
                         } else {
                             // Only increment the counter if we are not over the limit.  Fixes DFE-205
                             $this->cache()->put($_checkKey, $cacheValue, $_limit['period']);
                         }
                         // And now set it back
                         putenv('DF_CACHE_PREFIX' . '=' . $dfCachePrefix);
                         $_ENV['DF_CACHE_PREFIX'] = $_SERVER['DF_CACHE_PREFIX'] = $dfCachePrefix;
                     }
                 }
             }
         } catch (\Exception $_ex) {
             return ResponseFactory::getException(new InternalServerErrorException('Unable to update cache: ' . $_ex->getMessage()), $request);
         }
         if ($overLimit) {
             /* Per Ben, we want to increment every limit they hit, not stop after the first one */
             return ResponseFactory::getException(new TooManyRequestsException('API limit(s) exceeded: ' . implode(', ', $overLimit)), $request);
         }
     }
     return $next($request);
 }
Example #13
0
 /**
  * @return bool|mixed
  * @throws \DreamFactory\Core\Events\Exceptions\ScriptException
  * @throws \DreamFactory\Core\Exceptions\BadRequestException
  * @throws \DreamFactory\Core\Exceptions\InternalServerErrorException
  */
 protected function processRequest()
 {
     //	Now all actions must be HTTP verbs
     if (!Verbs::contains($this->action)) {
         throw new BadRequestException('The action "' . $this->action . '" is not supported.');
     }
     $logOutput = $this->request->getParameterAsBool('log_output', true);
     $data = ['request' => $this->request->toArray()];
     $data['resource'] = $this->resourcePath;
     $output = null;
     $result = ScriptEngineManager::runScript($this->content, 'script.' . $this->name, $this->engineConfig, $this->scriptConfig, $data, $output);
     if (!empty($output) && $logOutput) {
         \Log::info("Script '{$this->name}' output:" . PHP_EOL . $output . PHP_EOL);
     }
     //  Bail on errors...
     if (is_array($result) && isset($result['script_result'], $result['script_result']['error'])) {
         throw new InternalServerErrorException($result['script_result']['error']);
     }
     if (is_array($result) && isset($result['exception'])) {
         throw new InternalServerErrorException(ArrayUtils::get($result, 'exception', ''));
     }
     //  The script runner should return an array
     if (is_array($result) && isset($result['__tag__'])) {
         $scriptResult = ArrayUtils::get($result, 'script_result', []);
         if (!empty($response = ArrayUtils::get($result, 'response', []))) {
             $content = ArrayUtils::get($response, 'content');
             $status = ArrayUtils::get($response, 'status', ServiceResponseInterface::HTTP_OK);
             $format = ArrayUtils::get($response, 'format', DataFormats::PHP_ARRAY);
             return ResponseFactory::create($content, $format, $status);
         }
         return $scriptResult;
     } else {
         Log::error('  * Script did not return an array: ' . print_r($result, true));
     }
     return $output;
 }
Example #14
0
 /**
  * Handles all service requests
  *
  * @param null|string $version
  * @param string      $service
  * @param null|string $resource
  *
  * @return ServiceResponseInterface|null
  */
 public function handleService($version = null, $service, $resource = null)
 {
     try {
         $service = strtolower($service);
         // fix removal of trailing slashes from resource
         if (!empty($resource)) {
             $uri = \Request::getRequestUri();
             if (false === strpos($uri, '?') && '/' === substr($uri, strlen($uri) - 1, 1) || '/' === substr($uri, strpos($uri, '?') - 1, 1)) {
                 $resource .= '/';
             }
         }
         $response = ServiceHandler::processRequest($version, $service, $resource);
     } catch (\Exception $e) {
         $response = ResponseFactory::create($e);
     }
     if ($response instanceof RedirectResponse) {
         return $response;
     }
     return ResponseFactory::sendResponse($response, null, null, $resource);
 }
Example #15
0
 /**
  * @param \Exception               $e
  * @param \Illuminate\Http\Request $request
  *
  * @return array|mixed|string
  */
 public static function getException($e, $request)
 {
     $response = ResponseFactory::create($e);
     return ResponseFactory::sendResponse($response);
 }
Example #16
0
 /**
  * Handles POST action
  *
  * @return \DreamFactory\Core\Utility\ServiceResponse
  * @throws BadRequestException
  * @throws \Exception
  */
 protected function handlePOST()
 {
     if (!empty($this->resource)) {
         throw new BadRequestException('Create record by identifier not currently supported.');
     }
     $records = ResourcesWrapper::unwrapResources($this->getPayloadData());
     if (empty($records)) {
         throw new BadRequestException('No record(s) detected in request.');
     }
     $this->triggerActionEvent($this->response);
     $model = $this->getModel();
     $result = $model::bulkCreate($records, $this->request->getParameters());
     $asList = $this->request->getParameterAsBool(ApiOptions::AS_LIST);
     $id = $this->request->getParameter(ApiOptions::ID_FIELD, $this->getResourceIdentifier());
     $result = ResourcesWrapper::cleanResources($result, $asList, $id, ApiOptions::FIELDS_ALL);
     return ResponseFactory::create($result, $this->nativeFormat, ServiceResponseInterface::HTTP_CREATED);
 }
Example #17
0
 /**
  * @param Request  $request
  * @param \Closure $next
  *
  * @return array|mixed|string
  */
 public function handle(Request $request, \Closure $next)
 {
     if (!in_array($route = $request->getPathInfo(), ['/setup', '/setup_db'])) {
         try {
             $apiKey = static::getApiKey($request);
             Session::setApiKey($apiKey);
             $appId = App::getAppIdByApiKey($apiKey);
             //Get the JWT.
             $token = static::getJwt($request);
             Session::setSessionToken($token);
             //Check for basic auth attempt.
             $basicAuthUser = $request->getUser();
             $basicAuthPassword = $request->getPassword();
             if (!empty($basicAuthUser) && !empty($basicAuthPassword)) {
                 //Attempting to login using basic auth.
                 Auth::onceBasic();
                 /** @var User $authenticatedUser */
                 $authenticatedUser = Auth::user();
                 if (!empty($authenticatedUser)) {
                     $userId = $authenticatedUser->id;
                     Session::setSessionData($appId, $userId);
                 } else {
                     throw new UnauthorizedException('Unauthorized. User credentials did not match.');
                 }
             } elseif (!empty($token)) {
                 //JWT supplied meaning an authenticated user session/token.
                 try {
                     JWTAuth::setToken($token);
                     /** @type Payload $payload */
                     $payload = JWTAuth::getPayload();
                     JWTUtilities::verifyUser($payload);
                     $userId = $payload->get('user_id');
                     Session::setSessionData($appId, $userId);
                 } catch (TokenExpiredException $e) {
                     JWTUtilities::clearAllExpiredTokenMaps();
                     Session::set('token_expired', true);
                     Session::set('token_expired_msg', $e->getMessage());
                 } catch (TokenBlacklistedException $e) {
                     throw new ForbiddenException($e->getMessage());
                 } catch (TokenInvalidException $e) {
                     throw new BadRequestException('Invalid token: ' . $e->getMessage(), 401);
                 }
             } elseif (!empty($apiKey)) {
                 //Just Api Key is supplied. No authenticated session
                 Session::setSessionData($appId);
             }
             return $next($request);
         } catch (\Exception $e) {
             return ResponseFactory::getException($e, $request);
         }
     }
     return $next($request);
 }