/** * @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)); }
/** * 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); }
/** * @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); }
/** * 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); } }
/** * @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); }
/** * @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; }
/** * @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); }
/** * 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); }
/** * @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); }
/** * @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; }
/** * 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); }
/** * @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); }
/** * 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); }
/** * @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); }