1 package com.atlassian.refapp.applinks;
2
3 import com.atlassian.applinks.api.ApplicationLink;
4 import com.atlassian.applinks.api.ApplicationLinkRequestFactory;
5 import com.atlassian.applinks.api.ApplicationLinkResponseHandler;
6 import com.atlassian.applinks.api.ApplicationLinkService;
7 import com.atlassian.applinks.api.CredentialsRequiredException;
8 import com.atlassian.sal.api.net.Request;
9 import com.atlassian.sal.api.net.Response;
10 import com.atlassian.sal.api.net.ResponseException;
11 import com.atlassian.templaterenderer.TemplateRenderer;
12 import com.atlassian.webresource.api.assembler.PageBuilderService;
13 import com.google.common.collect.ImmutableMap;
14
15 import javax.servlet.ServletException;
16 import javax.servlet.http.HttpServlet;
17 import javax.servlet.http.HttpServletRequest;
18 import javax.servlet.http.HttpServletResponse;
19 import java.io.IOException;
20 import java.net.URI;
21 import java.net.URISyntaxException;
22 import java.util.Map;
23
24 public class WhoamiApplinksServlet extends HttpServlet {
25 private static final String TEMPLATE = "/templates/whoami.vm";
26 private static final String ENDPOINT = "/plugins/servlet/applinks/whoami";
27
28 private final TemplateRenderer templateRenderer;
29 private final ApplicationLinkService applicationLinkService;
30 private final PageBuilderService pageBuilderService;
31
32 public WhoamiApplinksServlet(final ApplicationLinkService applicationLinkService,
33 final TemplateRenderer templateRenderer,
34 final PageBuilderService pageBuilderService) {
35 this.templateRenderer = templateRenderer;
36 this.applicationLinkService = applicationLinkService;
37 this.pageBuilderService = pageBuilderService;
38 }
39
40 @Override
41 protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
42 throws ServletException, IOException {
43 final ImmutableMap.Builder<String, Object> contextBuilder = ImmutableMap.builder();
44 final ImmutableMap.Builder<ApplicationLink, AuthenticationInformation> recordBuilder = ImmutableMap.builder();
45
46 for (ApplicationLink link : applicationLinkService.getApplicationLinks()) {
47 recordBuilder.put(link, getAuthenticationInformation(request, link));
48 }
49
50 contextBuilder.put("records", recordBuilder.build());
51 render(TEMPLATE, contextBuilder.build(), response);
52 }
53
54 private AuthenticationInformation getAuthenticationInformation(final HttpServletRequest request, final ApplicationLink link) {
55 final ApplicationLinkRequestFactory requestFactory = link.createAuthenticatedRequestFactory();
56 final Holder<String> username = new Holder<String>();
57 final Holder<AuthenticationStatus> status = new Holder<AuthenticationStatus>(AuthenticationStatus.COMMUNICATION_ERROR);
58 final Holder<String> errorMessage = new Holder<String>();
59 try {
60 requestFactory
61 .createRequest(Request.MethodType.GET, ENDPOINT)
62 .execute(new ApplicationLinkResponseHandler() {
63 public Void handle(final Response response) throws ResponseException {
64 if (response.isSuccessful()) {
65 final String body = response.getResponseBodyAsString();
66 if (body == null || "".equals(body)) {
67 status.set(AuthenticationStatus.ANONYMOUS);
68 } else {
69 username.set(body);
70 status.set(AuthenticationStatus.ACCEPTED);
71 }
72 } else {
73 status.set(AuthenticationStatus.COMMUNICATION_ERROR);
74 errorMessage.set(String.format("%s: %s", response.getStatusCode(), response.getStatusText()));
75 }
76 return null;
77 }
78
79 public Void credentialsRequired(final Response response) throws ResponseException {
80 status.set(AuthenticationStatus.CREDENTIALS_REQUIRED);
81 return null;
82 }
83 });
84
85 } catch (CredentialsRequiredException cre) {
86 status.set(AuthenticationStatus.CREDENTIALS_REQUIRED);
87 } catch (ResponseException re) {
88 status.set(AuthenticationStatus.COMMUNICATION_ERROR);
89 errorMessage.set(re.getMessage());
90 }
91 final String authorisationURL = requestFactory.getAuthorisationURI() == null ? null :
92 requestFactory.getAuthorisationURI(getCurrentLocation(request)).toString();
93 return new AuthenticationInformation(username.get(), errorMessage.get(), authorisationURL, status.get());
94 }
95
96 private URI getCurrentLocation(final HttpServletRequest request) {
97 try {
98 return new URI(request.getRequestURL().toString());
99 } catch (URISyntaxException e) {
100
101 throw new RuntimeException(e);
102 }
103 }
104
105 private void render(final String template, Map<String, Object> context, final HttpServletResponse response)
106 throws IOException {
107 response.setContentType("text/html; charset=utf-8");
108 pageBuilderService.assembler().resources().requireWebResource("com.atlassian.auiplugin:ajs");
109 templateRenderer.render(template, context, response.getWriter());
110 }
111
112 public static class AuthenticationInformation {
113 private final AuthenticationStatus status;
114 private final String username;
115 private final String errorMessage;
116 private final String authorisationURL;
117
118 public AuthenticationInformation(String username, String errorMessage, String authorisationURL, AuthenticationStatus status) {
119 this.errorMessage = errorMessage;
120 this.authorisationURL = authorisationURL;
121 this.status = status;
122 this.username = username;
123 }
124
125 public String getAuthorisationURL() {
126 return authorisationURL;
127 }
128
129 public String getErrorMessage() {
130 return errorMessage;
131 }
132
133 public String getStatus() {
134 return status.name();
135 }
136
137
138
139
140 public String getUsername() {
141 return username;
142 }
143 }
144
145 public static enum AuthenticationStatus {
146 ACCEPTED,
147 CREDENTIALS_REQUIRED,
148 COMMUNICATION_ERROR,
149 ANONYMOUS
150 }
151
152
153
154
155 private static class Holder<T> {
156 private T value;
157
158 public Holder() {
159 value = null;
160 }
161
162 public void set(final T value) {
163 this.value = value;
164 }
165
166 public T get() {
167 return value;
168 }
169
170 public Holder(final T value) {
171 this.value = value;
172 }
173 }
174 }