Author: Tim Wagner (tw@appserver.io)
Inheritance: extends Thread
 /**
  * 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'));
 }
Esempio n. 2
0
 /**
  * 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();
 }
Esempio n. 3
0
 /**
  * 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;
 }
Esempio n. 4
0
 /**
  * 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());
         }
     }
 }
Esempio n. 5
0
 /**
  * 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);
 }
Esempio n. 6
0
 /**
  * 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);
 }
Esempio n. 7
0
 /**
  * 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');
     }
 }