 package ibgroup.http;
 
 import ibgroup.Config;
 import ibgroup.core.CookieManager;
 import ibgroup.services.AmService;
 import ibgroup.services.BaseServiceProxy;
 import ibgroup.services.ClientPortalService;
 import ibgroup.services.ServiceEvent;
 import ibgroup.services.SsoService;
 import ibgroup.utils.HttpResponse;
 import ibgroup.utils.IPv4Validator;
 import ibgroup.utils.RequestUtils;
 import io.vertx.core.AsyncResult;
 import io.vertx.core.Handler;
 import io.vertx.core.Vertx;
 import io.vertx.core.http.HttpClient;
 import io.vertx.core.http.HttpClientOptions;
 import io.vertx.core.http.HttpClientResponse;
 import io.vertx.core.http.HttpMethod;
 import io.vertx.core.http.HttpServerRequest;
 import io.vertx.core.json.JsonArray;
 import io.vertx.core.json.JsonObject;
 import io.vertx.core.logging.Logger;
 import io.vertx.core.logging.LoggerFactory;
 import io.vertx.core.net.SocketAddress;
 import io.vertx.ext.web.Router;
 import io.vertx.ext.web.RoutingContext;
 import io.vertx.ext.web.handler.CorsHandler;
 import io.vertx.ext.web.handler.StaticHandler;
 import java.util.Map;
 import java.util.Objects;
 
 public class GatewayHttpProxy {
   private static final Logger logger = LoggerFactory.getLogger(GatewayHttpProxy.class);
   private final AmService amService;
   private Config config;
   private int cpLoginRetry = 0;
   private final ClientPortalService cpService;
   private final HttpProxy httpProxy;
   private final HttpClient ibClient;
   private boolean loggedIn = false;
   private final Router router;
   private final SsoService ssoService;
   private final IPv4Validator validator;
   private final Vertx vertx;
   
   public GatewayHttpProxy(Vertx vertx, Config config) {
     HttpClientOptions options = (new HttpClientOptions()).setSsl(true);
     options.setConnectTimeout(15000);
     this.config = Objects.<Config>requireNonNull(config);
     this.vertx = Objects.<Vertx>requireNonNull(vertx);
     this.ibClient = vertx.createHttpClient(options);
     this.validator = new IPv4Validator(config);
     this.httpProxy = new HttpProxy(config, this.ibClient);
     
     this.amService = new AmService(vertx, this.ibClient, config);
     this.cpService = new ClientPortalService(vertx, this.ibClient, config);
     this.ssoService = new SsoService(vertx, this.ibClient, config);
     this.cpService.listener(event -> onEvent(event));
     this.ssoService.listener(event -> onEvent(event));
     this.amService.listener(event -> onEvent(event));
     
     this.router = Router.router(vertx);
     this.router.route("/*").handler(this::securityCheck);
     if (config.getCors() != null) {
       Map<String, Object> corsConfig = config.getCors();
       
       String corsOrig = (String)corsConfig.getOrDefault("origin.allowed", "*");
       boolean corsCred = ((Boolean)corsConfig.getOrDefault("allowCredentials", Boolean.valueOf(false))).booleanValue();
 
 
 
 
 
 
 
 
 
       
       CorsHandler allowCredentials = CorsHandler.create(corsOrig).allowCredentials(corsCred).allowedMethod(HttpMethod.POST).allowedMethod(HttpMethod.GET).allowedMethod(HttpMethod.POST).allowedMethod(HttpMethod.OPTIONS).allowedMethod(HttpMethod.DELETE).allowedMethod(HttpMethod.PUT).allowedHeader("Content-Type").allowedHeader("portal").allowedHeader("Cookie");
       this.router.route().handler((Handler)allowCredentials);
     } 
     this.router.route("/").handler(this::handleRedirect);
     this.router.route("/status").handler(this::handleStatus);
     this.router.route("/clear").handler(req -> {
           CookieManager.getInstance().clear();
           req.response().end("cleared");
         });
     this.router.routeWithRegex("/" + config.getServiceEnvironment() + "/(portal|api)/iserver/reauthenticate")
       .handler(this::handleReauthenticate);
     for (Config.WebApps app : config.getWebApps()) {
       logger.info(" -> mount {} on {}", new Object[] { app.name, "/" + app.name });
       System.out.println(" -> mount " + app.name + " on /" + app.name);
       this.router.route("/" + app.name + "/*")
         .handler((Handler)StaticHandler.create()
           .setWebRoot("root/webapps/" + app.name)
           .setDirectoryListing(app.listing)
           .setCachingEnabled(app.cache));
     } 
     this.router.routeWithRegex("^/(scripts|stylesheet|images|fonts).*").handler(this::staticFileHandler);
     this.router.routeWithRegex("^/(sso)/.*").handler(this::generalHandler);
     this.router.routeWithRegex("/:version/:service/logout").handler(this::handleLogout);
     this.router.routeWithRegex("^/(v1|qa|ci|alpha|local)/(portal|am|api)/(.*)").handler(this::generalHandler);
     this.router.route("/*").handler(this::handleNotFound);
   }
 
   
   public Router getRouter() {
     return this.router;
   }
   
   private void handleLogout(RoutingContext ctx) {
     HttpServerRequest clientReq = ctx.request();
     this.cpService.onProxyRequest(clientReq, serverRes -> {
           if (serverRes.statusCode() == 200) {
             clientReq.response().setStatusCode(200);
             clientReq.response().write("\nClient logout succeeded\n");
             clientReq.response().end();
             logger.info("Client logout succeeded");
             this.loggedIn = false;
             CookieManager.getInstance().clear();
           } else {
             clientReq.response().end();
           } 
         });
   }
 
   
   private void generalHandler(RoutingContext ctx) {
     HttpServerRequest clientReq = ctx.request();
     String service = clientReq.getParam("param1");
     if (service == null) {
       service = clientReq.getParam("param0");
     }
     if (service == null) {
       HttpResponse.sendNotFound(clientReq, clientReq.uri());
       return;
     } 
     if (service.equals("api")) {
       service = "portal";
     }
     BaseServiceProxy.fwdToSvc(clientReq, service, serverRes -> {
           if (serverRes.statusCode() == 302 && clientReq.uri().startsWith("/sso/Dispatcher")) {
             clientReq.response().setStatusCode(200);
             clientReq.response().write("Client login succeeds");
             clientReq.response().end();
             logger.info("Client login succeeds");
             onLoggedIn();
           } else {
             clientReq.response().end();
           } 
         });
   }
 
   
   private void handleNotFound(RoutingContext ctx) {
     HttpResponse.sendNotFound(ctx.request(), ctx.request().uri());
   }
   
   private void handleReauthenticate(RoutingContext ctx) {
     logger.info("reauthenticate {}", new Object[] { Boolean.valueOf(this.loggedIn) });
     if (!this.loggedIn) {
       HttpResponse.sendResponse(ctx, (new JsonObject()).put("error", "not logged in"));
     } else {
       HttpResponse.sendResponse(ctx, (new JsonObject()).put("message", "triggered"));
       loginToCp();
     } 
   }
   
   private void handleRedirect(RoutingContext ctx) {
     RequestUtils.redirect(ctx, "/sso/Login?forwardTo=22&RL=1&ip2loc=" + this.config.getIp2loc());
   }
 
   
   private void handleStatus(RoutingContext ctx) {}
 
   
   private void loginToCp() {
     this.cpLoginRetry++;
     this.cpService.reset();
     this.cpService.authenticate(res -> {
           if (res.succeeded()) {
             logger.info("authenticated to cp");
             this.cpLoginRetry = 0;
             this.cpService.getUser();
             this.ssoService.ssoDHInit();
           } else {
             logger.error("authentication to cp failed, retry {}", res.cause(), new Object[] { Integer.valueOf(this.cpLoginRetry) });
             if (this.cpLoginRetry < 5) {
               this.vertx.setTimer(3000L, ());
             } else {
               logger.error("giving up ...");
             } 
           } 
         });
   }
   
   private void onEvent(ServiceEvent event) {
     switch (event.type) {
       case ON_SSODH_FAILED:
         logger.error("ssodh failed, retry with /iserver/reauthenticate");
         return;
       case ON_AM_SESSION_ID:
         this.amService.getAccounts();
         return;
       case ON_SSODH_COMPLETED:
         logger.debug("delaying authentication for {}", new Object[] { Integer.valueOf(this.config.getAuthDelay()) });
         this.vertx.setTimer(this.config.getAuthDelay(), run -> this.cpService.setK(this.ssoService.getK()));
         return;
       case ON_AM_ACCOUNTS:
         this.cpService.validateAccounts((JsonArray)event.payload);
         return;
       case ON_CP_TICKLE_FAILED:
         if (this.loggedIn) {
           loginToCp();
         }
         return;
     } 
     logger.info("Unhandled event {}", new Object[] { event.type });
   }
 
 
   
   private void onLoggedIn() {
     this.loggedIn = true;
     this.ssoService.reset();
     this.amService.reset();
     loginToCp();
     this.amService.authenticate();
   }
   
   private void securityCheck(RoutingContext ctx) {
     HttpServerRequest clientReq = ctx.request();
     SocketAddress remoteIp = clientReq.remoteAddress();
     String ip = remoteIp.host();
     if (!this.validator.isAllowedIPAddress(ip)) {
       HttpResponse.sendResponse(clientReq, "Access Denied");
       return;
     } 
     ctx.next();
   }
   
   private void staticFileHandler(RoutingContext ctx) {
     HttpServerRequest request = ctx.request();
     this.httpProxy.internalProxy(request.uri(), request, serverRes -> request.response().end());
   }
 }


/* Location:              C:\Users\iuzeri\AppData\Local\Temp\ibrk_cpwa_gateway\dist\ibgroup.web.core.iblink.router.clientportal.gw.jar!\ibgroup\web\core\clientportal\gw\http\GatewayHttpProxy.class
 * Java compiler version: 8 (52.0)
 * JD-Core Version:       1.1.3
 */