/** * JSON encodes the passed content and returns it. * * @param mixed $content The content to be JSON encoded * * @return \AppserverIo\Apps\Api\TransferObject\EncodedViewData The DTO with the encoded content */ public function encode($content) { // load the application instance $application = RequestHandler::getApplicationContext(); // this is necessary to load the PSR-4 compatible Swagger library \Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(function ($className) use($application) { // load the application directory $webappPath = $application->getWebappPath(); $shortName = str_replace("Swagger\\Annotations\\", DIRECTORY_SEPARATOR, $className); // prepare the annotation filename for the Swagger annotations $file = sprintf('%s/vendor/zircote/swagger-php/src/Annotations/%s.php', $webappPath, $shortName); // query whether the file exists or not if (file_exists($file)) { require $file; return class_exists($className); } // return FALSE if the class can't be loaded return false; }); // serialize the passed content return new EncodedViewData($this->getContentType(), SerializerBuilder::create()->build()->serialize($content, 'json')); }
/** * Execute the rolesQuery against the dsJndiName to obtain the roles for the authenticated user. * * @param \AppserverIo\Lang\String $username The username to load the roles for * @param \AppserverIo\Lang\String $lookupName The lookup name for the datasource * @param \AppserverIo\Lang\String $rolesQuery The query to load the roles * @param \AppserverIo\Psr\Spi\LoginModuleInterface $aslm The login module to add the roles to * * @return array An array of groups containing the sets of roles * @throws \AppserverIo\Appserver\ServletEngine\Security\Logi\LoginException Is thrown if an error during login occured */ public static function getRoleSets(string $username, string $lookupName, string $rolesQuery, LoginModuleInterface $aslm) { try { // initialize the map for the groups $setsMap = new HashMap(); // load the application context $application = RequestHandler::getApplicationContext(); /** @var \AppserverIo\Appserver\Core\Api\Node\DatabaseNode $databaseNode */ $databaseNode = $application->getNamingDirectory()->search($lookupName)->getDatabase(); // prepare the connection parameters and create the DBAL connection $connection = DriverManager::getConnection(ConnectionUtil::get($application)->fromDatabaseNode($databaseNode)); // try to load the principal's roles from the database $statement = $connection->prepare($rolesQuery); $statement->bindParam(1, $username); $statement->execute(); // query whether or not we've a password found or not $row = $statement->fetch(\PDO::FETCH_NUM); // query whether or not we've found at least one role if ($row == false) { // try load the unauthenticated identity if ($aslm->getUnauthenticatedIdentity() == null) { throw new FailedLoginException('No matching username found in Roles'); } // we're running with an unauthenticatedIdentity so create an empty roles set and return return array(new SimpleGroup(Util::DEFAULT_GROUP_NAME)); } do { // load the found name and initialize the group name with a default value $name = $row[0]; $groupName = Util::DEFAULT_GROUP_NAME; // query whether or not we've to initialize a default group if (isset($row[1])) { $groupName = $row[1]; } // query whether or not the group already exists in the set if ($setsMap->exists($groupName) === false) { $group = new SimpleGroup(new String($groupName)); $setsMap->add($groupName, $group); } else { $group = $setsMap->get($groupName); } try { // add the user to the group $group->addMember($aslm->createIdentity(new String($name))); // log a message $application->getNamingDirectory()->search(NamingDirectoryKeys::SYSTEM_LOGGER)->debug(sprintf('Assign user to role: %s', $name)); } catch (\Exception $e) { $application->getNamingDirectory()->search(NamingDirectoryKeys::SYSTEM_LOGGER)->error(sprintf('Failed to create principal: %s', $name)); } // load one group after another } while ($row = $statement->fetch(\PDO::FETCH_OBJ)); } catch (NamingException $ne) { throw new LoginException($ne->__toString()); } catch (\PDOException $pdoe) { throw new LoginException($pdoe->__toString()); } // close the prepared statement if ($statement != null) { try { $statement->closeCursor(); } catch (\Exception $e) { $application->getNamingDirectory()->search(NamingDirectoryKeys::SYSTEM_LOGGER)->error($e->__toString()); } } // close the DBAL connection if ($connection != null) { try { $connection->close(); } catch (\Exception $e) { $application->getNamingDirectory()->search(NamingDirectoryKeys::SYSTEM_LOGGER)->error($e->__toString()); } } // return the prepared groups return $setsMap->toArray(); }
/** * The main method that handles the thread in a separate context. * * @return void */ public function run() { try { // register the default autoloader require SERVER_AUTOLOADER; // register shutdown handler set_error_handler(array(&$this, 'errorHandler')); register_shutdown_function(array(&$this, 'shutdown')); // initialize the array for the errors $this->errors = array(); // synchronize the application instance and register the class loaders $application = $this->application; $application->registerClassLoaders(); // synchronize the valves, servlet request/response $valves = $this->valves; $servletRequest = $this->servletRequest; $servletResponse = $this->servletResponse; // load the session and the authentication manager $sessionManager = $application->search(SessionManagerInterface::IDENTIFIER); $authenticationManager = $application->search(AuthenticationManagerInterface::IDENTIFIER); // inject the sapplication and servlet response $servletRequest->injectContext($application); $servletRequest->injectResponse($servletResponse); $servletRequest->injectSessionManager($sessionManager); $servletRequest->injectAuthenticationManager($authenticationManager); // prepare the request instance $servletRequest->prepare(); // initialize static request and application context RequestHandler::$requestContext = $servletRequest; RequestHandler::$applicationContext = $application; // process the valves foreach ($valves as $valve) { $valve->invoke($servletRequest, $servletResponse); if ($servletRequest->isDispatched() === true) { break; } } // profile the request if the profile logger is available if ($profileLogger = $application->getInitialContext()->getLogger(LoggerUtils::PROFILE)) { $profileLogger->appendThreadContext('request-handler'); $profileLogger->debug($servletRequest->getUri()); } } catch (\Exception $e) { $this->addError(ErrorUtil::singleton()->fromException($e)); } // re-attach request and response instances $this->servletRequest = $servletRequest; $this->servletResponse = $servletResponse; }
/** * This method finally handles all PHP and user errors as well as the exceptions that * have been thrown through the servlet processing. * * @param \AppserverIo\Appserver\ServletEngine\RequestHandler $requestHandler The request handler instance * @param \AppserverIo\Psr\Servlet\Http\HttpServletRequestInterface $servletRequest The actual request instance * @param \AppserverIo\Psr\Servlet\Http\HttpServletResponseInterface $servletResponse The actual request instance * * @return void */ public function handleErrors(RequestHandler $requestHandler, HttpServletRequestInterface $servletRequest, HttpServletResponseInterface $servletResponse) { // return immediately if we don't have any errors if (sizeof($errors = $requestHandler->getErrors()) === 0) { return; } // iterate over the errors to process each of them foreach ($errors as $error) { // prepare the error message $message = $this->prepareMessage($error); // query whether or not we have to log the error if (Boolean::valueOf(new String(ini_get('log_errors')))->booleanValue()) { // create a local copy of the application if ($application = $servletRequest->getContext()) { // try to load the system logger from the application if ($systemLogger = $application->getLogger(LoggerUtils::SYSTEM)) { $systemLogger->log($this->mapLogLevel($error), $message); } } } // query whether or not, the error has an status code if ($statusCode = $error->getStatusCode()) { $servletResponse->setStatusCode($statusCode); } } // we add the error to the servlet request $servletRequest->setAttribute(RequestHandlerKeys::ERROR_MESSAGES, $errors); // we append the the errors to the body stream if display_errors is on if (Boolean::valueOf(new String(ini_get('display_errors')))->booleanValue()) { $servletResponse->appendBodyStream(implode('<br/>', $errors)); } // query whether or not we've a client or an server error if ($servletResponse->getStatusCode() > 399) { try { // create a local copy of the application $application = $servletRequest->getContext(); // inject the application and servlet response $servletRequest->injectResponse($servletResponse); $servletRequest->injectContext($application); // load the servlet context instance $servletManager = $application->search(ServletContextInterface::IDENTIFIER); // initialize the request URI for the error page to be rendered $requestUri = null; // iterate over the configured error pages to find a matching one foreach ($servletManager->getErrorPages() as $errorCodePattern => $errorPage) { // query whether or not we found an error page configured for the actual status code if (fnmatch($errorCodePattern, $servletResponse->getStatusCode())) { $requestUri = $errorPage; break; } } // query whether or not we've an found a configured error page if ($requestUri == null) { throw new ServletException(sprintf('Please configure an error page for status code %s', $servletResponse->getStatusCode())); } // initialize the request URI $servletRequest->setRequestUri($requestUri); // prepare the request with the new data $servletRequest->prepare(); // reset the body stream to remove content, that has already been appended $servletResponse->resetBodyStream(); // load the servlet path and session-ID $servletPath = $servletRequest->getServletPath(); $sessionId = $servletRequest->getProposedSessionId(); // load and process the servlet $servlet = $servletManager->lookup($servletPath, $sessionId); $servlet->service($servletRequest, $servletResponse); } catch (\Exception $e) { // finally log the exception $application->getInitialContext()->getSystemLogger()->critical($e->__toString()); // append the exception message to the body stream $servletResponse->appendBodyStream($e->__toString()); } } }
/** * This returns a proxy to the requested session bean. * * @param string $lookupName The lookup name for the requested session bean * @param string $sessionId The session-ID if available * * @return \AppserverIo\RemoteMethodInvocation\RemoteObjectInterface The proxy instance */ public function lookupProxy($lookupName, $sessionId = null) { // load the initial context instance $initialContext = $this->getInitialContext(); // query whether a request context is available if ($servletRequest = RequestHandler::getRequestContext()) { // inject the servlet request to handle SFSBs correctly $initialContext->injectServletRequest($servletRequest); } // lookup the proxy by the name and session ID if available return $initialContext->lookup($lookupName, $sessionId); }
/** * Process servlet request. * * @param \AppserverIo\Psr\HttpMessage\RequestInterface $request A request object * @param \AppserverIo\Psr\HttpMessage\ResponseInterface $response A response object * @param \AppserverIo\Server\Interfaces\RequestContextInterface $requestContext A requests context instance * @param integer $hook The current hook to process logic for * * @return boolean * * @throws \AppserverIo\Server\Exceptions\ModuleException */ public function process(RequestInterface $request, ResponseInterface $response, RequestContextInterface $requestContext, $hook) { // if false hook is coming do nothing if (ModuleHooks::REQUEST_POST !== $hook) { return; } // check if we are the handler that has to process this request if ($requestContext->getServerVar(ServerVars::SERVER_HANDLER) !== $this->getModuleName()) { return; } // load the application associated with this request $application = $this->findRequestedApplication($requestContext); // check if the application has already been connected if ($application->isConnected() === false) { throw new \Exception(sprintf('Application %s has not connected yet', $application->getName()), 503); } // create a copy of the valve instances $valves = $this->valves; $handlers = $this->handlers; // create a new request instance from the HTTP request $servletRequest = new Request(); $servletRequest->injectHandlers($handlers); $servletRequest->injectHttpRequest($request); $servletRequest->injectServerVars($requestContext->getServerVars()); $servletRequest->init(); // initialize the request handler instance $requestHandler = new RequestHandler(); $requestHandler->injectValves($valves); $requestHandler->injectApplication($application); $requestHandler->injectRequest($servletRequest); $requestHandler->start(PTHREADS_INHERIT_NONE | PTHREADS_INHERIT_CONSTANTS); $requestHandler->join(); // copy values to the HTTP response $requestHandler->copyToHttpResponse($response); // set response state to be dispatched after this without calling other modules process $response->setState(HttpResponseStates::DISPATCH); }
/** * The main method that handles the thread in a separate context. * * @return void */ public function run() { try { // register the default autoloader require SERVER_AUTOLOADER; // register shutdown handler register_shutdown_function(array(&$this, "shutdown")); // synchronize the application instance and register the class loaders $application = $this->application; $application->registerClassLoaders(); // synchronize the valves, servlet request/response $valves = $this->valves; $servletRequest = $this->servletRequest; // initialize servlet session, request + response $servletResponse = new Response(); $servletResponse->init(); // we initialize this with a 500 to handle 'Fatal Error' case $this->statusCode = 500; // initialize arrays for header and cookies $this->state = $servletResponse->getState(); $this->version = $servletResponse->getVersion(); $this->headers = $servletResponse->getHeaders(); $this->cookies = $servletResponse->getCookies(); // inject the sapplication and servlet response $servletRequest->injectResponse($servletResponse); $servletRequest->injectContext($application); // prepare the request instance $servletRequest->prepare(); // initialize static request and application context RequestHandler::$requestContext = $servletRequest; RequestHandler::$applicationContext = $application; // process the valves foreach ($valves as $valve) { $valve->invoke($servletRequest, $servletResponse); if ($servletRequest->isDispatched() === true) { break; } } // profile the request if the profile logger is available if ($profileLogger = $application->getInitialContext()->getLogger(LoggerUtils::PROFILE)) { $profileLogger->appendThreadContext('request-handler'); $profileLogger->debug($servletRequest->getUri()); } } catch (\Exception $e) { // log the exception $application->getInitialContext()->getSystemLogger()->error($e->__toString()); // ATTENTION: We MUST wrap the exception, because it's possible that // the exception contains not serializable data that will // lead to a white page!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! $this->exception = new ServletException($e, $e->getCode()); } // copy the the response values $this->statusCode = $servletResponse->getStatusCode(); $this->statusReasonPhrase = $servletResponse->getStatusReasonPhrase(); $this->version = $servletResponse->getVersion(); $this->state = $servletResponse->getState(); // copy the content of the body stream $this->bodyStream = $servletResponse->getBodyStream(); // copy headers and cookies $this->headers = $servletResponse->getHeaders(); $this->cookies = $servletResponse->getCookies(); }
/** * Returns the password for the user from the naming directory. * * @return \AppserverIo\Lang\String The user's password * @throws \AppserverIo\Appserver\Psr\Security\Auth\Login\LoginException Is thrown if password can't be loaded */ protected function getUsersPassword() { try { // load the application context $application = RequestHandler::getApplicationContext(); // load and return the user's password or throw an exception return new String($application->search(sprintf('%s/%s', $this->userPathPrefix, $this->getUsername()))); } catch (\Exception $e) { throw new LoginException('No matching username found in naming directory'); } }
/** * Process servlet request. * * @param \AppserverIo\Psr\HttpMessage\RequestInterface $request A request object * @param \AppserverIo\Psr\HttpMessage\ResponseInterface $response A response object * @param \AppserverIo\Server\Interfaces\RequestContextInterface $requestContext A requests context instance * @param integer $hook The current hook to process logic for * * @return boolean * * @throws \AppserverIo\Server\Exceptions\ModuleException */ public function process(RequestInterface $request, ResponseInterface $response, RequestContextInterface $requestContext, $hook) { // if false hook is coming do nothing if (ModuleHooks::REQUEST_POST !== $hook) { return; } // check if we are the handler that has to process this request if ($requestContext->getServerVar(ServerVars::SERVER_HANDLER) !== $this->getModuleName()) { return; } // load the application associated with this request $application = $this->findRequestedApplication($requestContext); $application->registerClassLoaders(); // check if the application has already been connected if ($application->isConnected() === false) { throw new \Exception(sprintf('Application %s has not connected yet', $application->getName()), 503); } // create a copy of the valve instances $valves = $this->valves; $handlers = $this->handlers; // create a new request instance from the HTTP request $servletRequest = new Request(); $servletRequest->injectHandlers($handlers); $servletRequest->injectHttpRequest($request); $servletRequest->injectServerVars($requestContext->getServerVars()); $servletRequest->init(); // initialize servlet response $servletResponse = new Response(); $servletResponse->init(); // load the session and the authentication manager $sessionManager = $application->search(SessionManagerInterface::IDENTIFIER); $authenticationManager = $application->search(AuthenticationManagerInterface::IDENTIFIER); // inject the sapplication and servlet response $servletRequest->injectContext($application); $servletRequest->injectResponse($servletResponse); $servletRequest->injectSessionManager($sessionManager); $servletRequest->injectAuthenticationManager($authenticationManager); // prepare the request instance $servletRequest->prepare(); // initialize static request and application context RequestHandler::$requestContext = $servletRequest; RequestHandler::$applicationContext = $application; // process the valves foreach ($valves as $valve) { $valve->invoke($servletRequest, $servletResponse); if ($servletRequest->isDispatched() === true) { break; } } // copy response values to the HTTP response $response->setState($servletResponse->getState()); $response->setVersion($servletResponse->getVersion()); $response->setStatusCode($servletResponse->getStatusCode()); $response->setStatusReasonPhrase($servletResponse->getStatusReasonPhrase()); // copy the body content to the HTTP response $response->appendBodyStream($servletResponse->getBodyStream()); // copy headers to the HTTP response foreach ($servletResponse->getHeaders() as $headerName => $headerValue) { $response->addHeader($headerName, $headerValue); } // copy cookies to the HTTP response $response->setCookies($servletResponse->getCookies()); // append the servlet engine's signature $response->addHeader(Protocol::HEADER_X_POWERED_BY, get_class($this), true); // set response state to be dispatched after this without calling other modules process $response->setState(HttpResponseStates::DISPATCH); }
/** * Returns the password for the user from the sharedMap data. * * @return \AppserverIo\Lang\String The user's password * @throws \AppserverIo\Psr\Security\Auth\Login\LoginException Is thrown if password can't be loaded */ protected function getUsersPassword() { // load the application context $application = RequestHandler::getApplicationContext(); /** @var \AppserverIo\Appserver\Core\Api\Node\DatabaseNode $databaseNode */ $databaseNode = $application->getNamingDirectory()->search($this->lookupName)->getDatabase(); // prepare the connection parameters and create the DBAL connection $connection = DriverManager::getConnection(ConnectionUtil::get($application)->fromDatabaseNode($databaseNode)); // try to load the principal's credential from the database $statement = $connection->prepare($this->principalsQuery); $statement->bindParam(1, $this->getUsername()); $statement->execute(); // close the PDO connection if ($connection != null) { try { $connection->close(); } catch (\Exception $e) { $application->getNamingDirectory()->search(NamingDirectoryKeys::SYSTEM_LOGGER)->error($e->__toString()); } } // query whether or not we've a password found or not if ($row = $statement->fetch(\PDO::FETCH_NUM)) { return new String($row[0]); } else { throw new LoginException('No matching username found in principals'); } }