package com.perforce.workshop.tjuricek.p4oauth.controllers; import com.github.jknack.handlebars.Handlebars; import com.github.jknack.handlebars.Template; import com.github.jknack.handlebars.io.FileTemplateLoader; import com.github.jknack.handlebars.io.TemplateLoader; import com.perforce.workshop.tjuricek.p4oauth.config.P4OAuthConfig; import com.perforce.workshop.tjuricek.p4oauth.util.HttpServletRequestHelper; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.function.Function; /** * The authorization mechanism will pretty much always go to this method to * present a login page to collect the p4d login and password. * * URL format for this page is: * * <pre>[server root]/login?client_id=[P4 Login]&request_uri=[uri]</pre> */ public class LoginGet implements ControllerMethod { public static final String LOGIN_PATH = "/login"; private P4OAuthConfig config; private Function<HttpServletRequest, HttpServletRequestHelper> requestWrapper; private Handlebars handlebars; private Template cachedTemplate = null; public LoginGet(P4OAuthConfig config, Function<HttpServletRequest, HttpServletRequestHelper> requestWrapper) { this.config = config; this.requestWrapper = requestWrapper; if (!config.isCacheTemplates() && config.getTemplateDirectory() != null) { TemplateLoader loader = new FileTemplateLoader(config.getTemplateDirectory(), ".hbs"); handlebars = new Handlebars(loader); } else { // By default, just uses the classpath loader with the ".hbs" extension handlebars = new Handlebars(); } } @Override public boolean matches(HttpServletRequest baseRequest) { HttpServletRequestHelper request = requestWrapper.apply(baseRequest); return request.pathStartsWith(LOGIN_PATH) && request.hasMethod("GET"); } @Override public void handle(HttpServletRequest baseRequest, HttpServletResponse response) throws IOException, ServletException { HttpServletRequestHelper request = requestWrapper.apply(baseRequest); String login; if (request.getParam("client_id").isPresent()) { login = request.getParam("client_id").get(); } else { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing required parameter client_id"); return; } String redirectUri; if (request.getParam("redirect_uri").isPresent()) { redirectUri = request.getParam("redirect_uri").get(); } else { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing required parameter redirect_uri"); return; } String state = request.getParam("state").orElse(null); response.setContentType("text/html"); LoginTemplateContext context = new LoginTemplateContext(login, redirectUri, state); Template template = getLoginTemplate(); template.apply(context, response.getWriter()); } /** * We allow development environments to set up the "cacheTemplates" boolean * to false in order to make edits on the fly. Otherwise, we generally * just load up the template file once. * * @return */ private Template getLoginTemplate() throws IOException { if (config.isCacheTemplates()) { if (cachedTemplate != null) { return cachedTemplate; } } Template template = handlebars.compile("templates/login.html"); if (config.isCacheTemplates()){ cachedTemplate = template; } return template; } /** * Context used for rendering the template page */ static class LoginTemplateContext { private String login; private String redirectUri; private String state; LoginTemplateContext(String login, String redirectUri, String state) { this.login = login; this.redirectUri = redirectUri; this.state = state; } public String getLogin() { return login; } public String getRedirectUri() { return redirectUri; } public String getState() { return state; } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 9095 | tjuricek | Added some basic test data and renamed "workspace" to "workshop" in package name | ||
//guest/tjuricek/p4oauth/src/main/java/com/perforce/workspace/tjuricek/p4oauth/controllers/LoginGet.java | |||||
#1 | 9089 | tjuricek |
Moving some code that worked via some manual validation to the workshop. This just implements a basic code authorization grant scheme. Automated tests are forthcoming, awating some gradle plugin work that should sit outside of this project. |