bd5c420e15ff8fb1f6504529daef405ce38ffc4e
[ui/dmaapbc.git] /
1 package org.onap.dcae.dmaapbc.dbcapp.controller;
2
3 import java.util.Date;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import javax.servlet.http.HttpServletRequest;
9
10 import org.onap.dcae.dmaapbc.client.DmaapBcRestClient;
11 import org.onap.dcae.dmaapbc.dbcapp.domain.DmaapAccess;
12 import org.onap.dcae.dmaapbc.model.Dmaap;
13 import org.onap.dcae.dmaapbc.model.DmaapObject;
14 import org.onap.dcae.dmaapbc.model.ErrorResponse;
15 import org.openecomp.portalsdk.core.domain.User;
16 import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
17 import org.openecomp.portalsdk.core.util.SystemProperties;
18 import org.openecomp.portalsdk.core.web.support.UserUtils;
19 import org.slf4j.MDC;
20 import org.springframework.stereotype.Controller;
21 import org.springframework.web.bind.annotation.PathVariable;
22 import org.springframework.web.bind.annotation.RequestMapping;
23 import org.springframework.web.bind.annotation.RequestMethod;
24 import org.springframework.web.bind.annotation.ResponseBody;
25
26 import com.fasterxml.jackson.databind.ObjectMapper;
27
28 /**
29  * DMaaP Access controller: serves Ajax requests made by Angular on pages where
30  * the user adds, edits and deletes DMaaP access profiles. This controller must
31  * defend the database against rogue requests including SQL injection attacks.
32  */
33 @Controller
34 @RequestMapping("/")
35 public class DmaapAccessController extends DbcappRestrictedBaseController {
36
37         /**
38          * Logger that conforms with ECOMP guidelines
39          */
40         private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DmaapAccessController.class);
41
42         private static final String DMAAP_ACCESS_PATH = "/dmaap_access";
43         private static final String SELECT_DMAAP_ACCESS_PATH = "/select_dmaap_access";
44
45         /**
46          * For general use in these methods
47          */
48         private final ObjectMapper mapper;
49
50         /**
51          * Never forget that Spring autowires fields AFTER the constructor is
52          * called.
53          */
54         public DmaapAccessController() {
55                 mapper = new ObjectMapper();
56         }
57
58         /**
59          * Gets a list of DMaaP access profiles for this user from the database and
60          * returns them in a JSON array nested within a response object. Traps errors and constructs an appropriate JSON block if an error
61          * happens.
62          * 
63          * See {@link #getOrInitDmaapAccessList(String)}.
64          * 
65          * @param request
66          *            HttpServletRequest
67          * @return JSON with access profiles, or an error JSON if the request fails.
68          */
69         @RequestMapping(value = { DMAAP_ACCESS_PATH }, method = RequestMethod.GET, produces = "application/json")
70         @ResponseBody
71         public String getDmaapAccessList(HttpServletRequest request) {
72                 MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
73                 logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
74                 String outboundJson = null;
75                 try {
76                         User appUser = UserUtils.getUserSession(request);
77                         if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
78                                 throw new Exception("getDmaapAccessList: Failed to get Login ID");
79                         List<DmaapAccess> dbAccessList = getOrInitDmaapAccessList(appUser.getLoginId());
80                         // Wrap the list in the status indicator.
81                         Map<String, Object> model = new HashMap<String, Object>();
82                         model.put(STATUS_RESPONSE_KEY, new Integer(200));
83                         model.put(DATA_RESPONSE_KEY, dbAccessList);
84                         outboundJson = mapper.writeValueAsString(model);
85                 } catch (Exception ex) {
86                         outboundJson = buildJsonError(500, "Failed to get DMaaP access profile list", ex);
87                 }
88                 MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
89                 logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
90                 return outboundJson;
91         }
92
93         /**
94          * Adds a DMaaP access profile for the requesting user ID; ignores any
95          * values for row ID and user ID in the body. Traps errors and
96          * constructs an appropriate JSON block if an error happens.
97          * 
98          * @param request
99          *            HttpServletRequest
100          * @return Trivial JSON object indicating success or failure.
101          */
102         @RequestMapping(value = { DMAAP_ACCESS_PATH }, method = RequestMethod.POST, produces = "application/json")
103         @ResponseBody
104         public String addDmaapAccess(HttpServletRequest request) {
105                 MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
106                 logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
107                 String outboundJson = null;
108                 try {
109                         User appUser = UserUtils.getUserSession(request);
110                         if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
111                                 throw new Exception("addDmaapAccess: Failed to get Login ID");
112
113                         DmaapAccess dmaapAccess = mapper.readValue(request.getReader(), DmaapAccess.class);
114                         logger.debug("addDmaapAccess: received object: {} ", dmaapAccess);
115
116                         // Null out ID to get an auto-generated ID
117                         dmaapAccess.setId(null);
118                         // Overwrite any submitted user id
119                         dmaapAccess.setUserId(appUser.getLoginId());
120                         // Encrypt password
121                         if (dmaapAccess.getPassword() != null)
122                                 dmaapAccess.encryptPassword(dmaapAccess.getPassword());
123
124                         // Create a new row
125                         getDmaapAccessService().saveDmaapAccess(dmaapAccess);
126
127                         // Answer success
128                         outboundJson = buildJsonSuccess(200, null);
129                 } catch (Exception ex) {
130                         outboundJson = buildJsonError(500, "Failed to add DMaaP access profile", ex);
131                 }
132                 MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
133                 logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
134                 return outboundJson;
135         }
136
137         /**
138          * Updates a DMaaP access profile if the row user ID matches the requesting
139          * user ID. Traps errors and
140          * constructs an appropriate JSON block if an error happens. 
141          * 
142          * @param id
143          *            Path parameter with ID of the DMaaP access profile
144          * @param request
145          *            HttpServletRequest
146          * @return Trivial JSON object indicating success or failure.
147          */
148         @RequestMapping(value = { DMAAP_ACCESS_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
149         @ResponseBody
150         public String updateDmaapAccess(@PathVariable("id") long id, HttpServletRequest request) {
151                 MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
152                 logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
153                 String outboundJson = null;
154                 try {
155                         User appUser = UserUtils.getUserSession(request);
156                         if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
157                                 throw new Exception("updateDmaapAccess: Failed to get Login ID");
158
159                         DmaapAccess domainObj = getDmaapAccessService().getDmaapAccess(id);
160                         if (!appUser.getLoginId().equals(domainObj.getUserId()))
161                                 throw new Exception("updateDmaapAccess: mismatch of appUser and row user ID");
162
163                         DmaapAccess dmaapAccess = mapper.readValue(request.getReader(), DmaapAccess.class);
164                         logger.debug("updateDmaapAccess: received object: {} ", dmaapAccess);
165
166                         // Use the path-parameter id; don't trust the one in the object
167                         dmaapAccess.setId(id);
168                         // Encrypt password if present
169                         if (dmaapAccess.getPassword() != null)
170                                 dmaapAccess.encryptPassword(dmaapAccess.getPassword());
171
172                         // Update the existing row
173                         getDmaapAccessService().saveDmaapAccess(dmaapAccess);
174
175                         // Answer "OK"
176                         outboundJson = buildJsonSuccess(200, null);
177                 } catch (Exception ex) {
178                         outboundJson = buildJsonError(500, "Failed to update DMaaP access profile", ex);
179                 }
180                 MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
181                 logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
182                 return outboundJson;
183         }
184
185         /**
186          * Deletes a DMaaP access profile if the row user ID matches the requesting
187          * user ID. Traps errors and
188          * constructs an appropriate JSON block if an error happens. 
189          * 
190          * @param id
191          *            Path parameter with ID of the DMaaP access profile
192          * @param request
193          *            HttpServletRequest
194          * @return Trivial JSON object indicating success or failure (altho this is
195          *         slightly contrary to conventions for a DELETE method)
196          */
197         @RequestMapping(value = {
198                         DMAAP_ACCESS_PATH + "/{id}" }, method = RequestMethod.DELETE, produces = "application/json")
199         @ResponseBody
200         public String deleteDmaapAccess(@PathVariable("id") long id, HttpServletRequest request) {
201                 MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
202                 logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
203                 String outboundJson = null;
204                 try {
205                         User appUser = UserUtils.getUserSession(request);
206                         if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
207                                 throw new Exception("deleteDmaapAccess: Failed to get Login ID");
208                         // Validate that this user owns the row with the specified ID
209                         DmaapAccess domainObj = getDmaapAccessService().getDmaapAccess(id);
210                         if (!appUser.getLoginId().equals(domainObj.getUserId()))
211                                 throw new Exception("deleteDmaapAccess: mismatch of appUser and row user ID");
212
213                         getDmaapAccessService().deleteDmaapAccess(id);
214
215                         // Answer "OK"
216                         outboundJson = buildJsonSuccess(200, null);
217                 } catch (Exception ex) {
218                         outboundJson = buildJsonError(500, "Failed to delete DMaaP access profile", ex);
219                 }
220                 MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
221                 logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
222                 return outboundJson;
223         }
224
225         /**
226          * Gets the selected DMaaP access row for the requesting user.
227          * 
228          * See {@link #getSelectedDmaapAccess(String)}
229          * 
230          * @param request
231          *            HttpServletRequest
232          * @return JSON object with one DmaapAccessProfile, or an error
233          */
234         @RequestMapping(value = { SELECT_DMAAP_ACCESS_PATH }, method = RequestMethod.GET, produces = "application/json")
235         @ResponseBody
236         public String getSelectedDmaapAccessProfile(HttpServletRequest request)  {
237                 MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
238                 logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
239                 String outboundJson = null;
240                 try {
241                         User appUser = UserUtils.getUserSession(request);
242                         if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
243                                 throw new Exception("getSelectedDmaapAccessProfile: Failed to get Login ID");
244                         DmaapAccess selected = super.getSelectedDmaapAccess(appUser.getLoginId());
245                         // clone and decrypt
246                         DmaapAccess clear = new DmaapAccess(selected);
247                         try {
248                                 clear.setPassword(clear.decryptPassword());
249                         } catch (Exception ex) {
250                                 // Should never happen
251                                 throw new RuntimeException("getSelectedDmaapAccessProfile: Failed to decrypt password", ex);
252                         }
253                         outboundJson = buildJsonSuccess(200, clear);
254                 } catch (Exception ex) {
255                         outboundJson = buildJsonError(500, "Failed to get selected DMaaP access profile", ex);
256                 }
257                 MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
258                 logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
259                 return outboundJson;
260         }
261
262         /**
263          * Marks the DMaaP access row as selected (first choice) for the requesting
264          * user if the row user ID matches the requesting user ID. As a side effect,
265          * removes selected marking from all other user rows. Returns status,
266          * additionally an error message on failure. Traps errors and
267          * constructs an appropriate JSON block if an error happens.
268          * 
269          * Choice of PUT is fairly arbitrary - there is no body, but GET is for
270          * actions that do not change data.
271          * 
272          * @param id
273          *            Path parameter with ID of the DMaaP access profile
274          * @param request
275          *            HttpServletRequest
276          * @return Trivial JSON object indicating success or failure.
277          */
278         @RequestMapping(value = {
279                         SELECT_DMAAP_ACCESS_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
280         @ResponseBody
281         public String selectDmaapAccess(@PathVariable("id") long id, HttpServletRequest request) {
282                 MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
283                 logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
284                 String outboundJson = null;
285                 try {
286                         User appUser = UserUtils.getUserSession(request);
287                         if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
288                                 throw new Exception("selectDmaapAccess: Failed to get Login UID");
289                         // A little inefficient in that it requires 3 database accesses;
290                         // probably could be done in 1 with some sophisticated SQL.
291                         List<DmaapAccess> dmaapAccessList = getDmaapAccessService().getDmaapAccessList(appUser.getLoginId());
292                         for (DmaapAccess dmaap : dmaapAccessList) {
293                                 // Only write out the changed rows.
294                                 boolean changed = false;
295                                 if (id == dmaap.getId()) {
296                                         changed = !dmaap.getSelected();
297                                         dmaap.setSelected(true);
298                                 } else {
299                                         changed = dmaap.getSelected();
300                                         dmaap.setSelected(false);
301                                 }
302                                 if (changed)
303                                         getDmaapAccessService().saveDmaapAccess(dmaap);
304                         }
305
306                         // Answer OK
307                         outboundJson = buildJsonSuccess(200, null);
308                 } catch (Exception ex) {
309                         outboundJson = buildJsonError(500, "Failed to select a DMaaP access profile", ex);
310                 }
311                 MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
312                 logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
313                 return outboundJson;
314         }
315
316         /**
317          * Tests the URL in the DMaaP access profile object. Traps errors and
318          * constructs an appropriate JSON block if an error happens.
319          * 
320          * @param request
321          *            HttpServletRequest
322          * @return JSON with a Dmaap object (which has name etc.) on success, error
323          *         on failure.
324          */
325         @RequestMapping(value = { "test_dmaap_access" }, method = RequestMethod.POST, produces = "application/json")
326         @ResponseBody
327         public String testDmaapAccess(HttpServletRequest request)  {
328                 MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
329                 logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
330                 String outboundJson = null;
331                 try {
332                         DmaapAccess dmaapAccess = mapper.readValue(request.getReader(), DmaapAccess.class);
333                         logger.debug("testDmaapAccess: received object: {} ", dmaapAccess);
334                         if (dmaapAccess.getDmaapUrl() == null || dmaapAccess.getDmaapUrl().trim().length() == 0)
335                                 throw new Exception("Null or empty URL");
336
337                         DmaapBcRestClient restClient = getDmaapBcRestClient(dmaapAccess);
338                         // Get the instance so the page can display its name
339                         DmaapObject dmaap = restClient.getDmaap();
340                         if (dmaap instanceof Dmaap) {
341                                 outboundJson = buildJsonSuccess(200, dmaap);
342                         } else {
343                                 // Bad credentials lands here.
344                                 ErrorResponse err = (ErrorResponse) dmaap;
345                                 outboundJson = buildJsonError(500, "Test failed: " + err.getMessage(), null);
346                         }
347                 } catch (Exception ex) {
348                         // This is entirely likely; e.e., unknown host exception on typo.
349                         outboundJson = buildJsonError(500, "Invalid DMaaP URL", ex);
350                 }
351                 MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
352                 logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
353                 return outboundJson;
354         }
355
356 }