aboutsummaryrefslogtreecommitdiffstats
path: root/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/openecomp/dcae/dmaapbc/dbcapp/controller/DmaapAccessController.java
blob: 5f81a7494780498e4cf2b73cdb3d99b133b80ed5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
package org.openecomp.dcae.dmaapbc.dbcapp.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.openecomp.dcae.dmaapbc.client.DmaapBcRestClient;
import org.openecomp.dcae.dmaapbc.dbcapp.domain.DmaapAccess;
import org.openecomp.dcae.dmaapbc.model.Dmaap;
import org.openecomp.dcae.dmaapbc.model.DmaapObject;
import org.openecomp.dcae.dmaapbc.model.ErrorResponse;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.util.SystemProperties;
import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.slf4j.MDC;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * DMaaP Access controller: serves Ajax requests made by Angular on pages where
 * the user adds, edits and deletes DMaaP access profiles. This controller must
 * defend the database against rogue requests including SQL injection attacks.
 */
@Controller
@RequestMapping("/")
public class DmaapAccessController extends DbcappRestrictedBaseController {

	/**
	 * Logger that conforms with ECOMP guidelines
	 */
	private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DmaapAccessController.class);

	private static final String DMAAP_ACCESS_PATH = "/dmaap_access";
	private static final String SELECT_DMAAP_ACCESS_PATH = "/select_dmaap_access";

	/**
	 * For general use in these methods
	 */
	private final ObjectMapper mapper;

	/**
	 * Never forget that Spring autowires fields AFTER the constructor is
	 * called.
	 */
	public DmaapAccessController() {
		mapper = new ObjectMapper();
	}

	/**
	 * Gets a list of DMaaP access profiles for this user from the database and
	 * returns them in a JSON array nested within a response object. Traps errors and constructs an appropriate JSON block if an error
	 * happens.
	 * 
	 * See {@link #getOrInitDmaapAccessList(String)}.
	 * 
	 * @param request
	 *            HttpServletRequest
	 * @return JSON with access profiles, or an error JSON if the request fails.
	 */
	@RequestMapping(value = { DMAAP_ACCESS_PATH }, method = RequestMethod.GET, produces = "application/json")
	@ResponseBody
	public String getDmaapAccessList(HttpServletRequest request) {
		MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
		String outboundJson = null;
		try {
			User appUser = UserUtils.getUserSession(request);
			if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
				throw new Exception("getDmaapAccessList: Failed to get Login ID");
			List<DmaapAccess> dbAccessList = getOrInitDmaapAccessList(appUser.getLoginId());
			// Wrap the list in the status indicator.
			Map<String, Object> model = new HashMap<String, Object>();
			model.put(STATUS_RESPONSE_KEY, new Integer(200));
			model.put(DATA_RESPONSE_KEY, dbAccessList);
			outboundJson = mapper.writeValueAsString(model);
		} catch (Exception ex) {
			outboundJson = buildJsonError(500, "Failed to get DMaaP access profile list", ex);
		}
		MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
		return outboundJson;
	}

	/**
	 * Adds a DMaaP access profile for the requesting user ID; ignores any
	 * values for row ID and user ID in the body. Traps errors and
	 * constructs an appropriate JSON block if an error happens.
	 * 
	 * @param request
	 *            HttpServletRequest
	 * @return Trivial JSON object indicating success or failure.
	 */
	@RequestMapping(value = { DMAAP_ACCESS_PATH }, method = RequestMethod.POST, produces = "application/json")
	@ResponseBody
	public String addDmaapAccess(HttpServletRequest request) {
		MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
		String outboundJson = null;
		try {
			User appUser = UserUtils.getUserSession(request);
			if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
				throw new Exception("addDmaapAccess: Failed to get Login ID");

			DmaapAccess dmaapAccess = mapper.readValue(request.getReader(), DmaapAccess.class);
			logger.debug("addDmaapAccess: received object: {} ", dmaapAccess);

			// Null out ID to get an auto-generated ID
			dmaapAccess.setId(null);
			// Overwrite any submitted user id
			dmaapAccess.setUserId(appUser.getLoginId());
			// Encrypt password
			if (dmaapAccess.getPassword() != null)
				dmaapAccess.encryptPassword(dmaapAccess.getPassword());

			// Create a new row
			getDmaapAccessService().saveDmaapAccess(dmaapAccess);

			// Answer success
			outboundJson = buildJsonSuccess(200, null);
		} catch (Exception ex) {
			outboundJson = buildJsonError(500, "Failed to add DMaaP access profile", ex);
		}
		MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
		return outboundJson;
	}

	/**
	 * Updates a DMaaP access profile if the row user ID matches the requesting
	 * user ID. Traps errors and
	 * constructs an appropriate JSON block if an error happens. 
	 * 
	 * @param id
	 *            Path parameter with ID of the DMaaP access profile
	 * @param request
	 *            HttpServletRequest
	 * @return Trivial JSON object indicating success or failure.
	 */
	@RequestMapping(value = { DMAAP_ACCESS_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
	@ResponseBody
	public String updateDmaapAccess(@PathVariable("id") long id, HttpServletRequest request) {
		MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
		String outboundJson = null;
		try {
			User appUser = UserUtils.getUserSession(request);
			if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
				throw new Exception("updateDmaapAccess: Failed to get Login ID");

			DmaapAccess domainObj = getDmaapAccessService().getDmaapAccess(id);
			if (!appUser.getLoginId().equals(domainObj.getUserId()))
				throw new Exception("updateDmaapAccess: mismatch of appUser and row user ID");

			DmaapAccess dmaapAccess = mapper.readValue(request.getReader(), DmaapAccess.class);
			logger.debug("updateDmaapAccess: received object: {} ", dmaapAccess);

			// Use the path-parameter id; don't trust the one in the object
			dmaapAccess.setId(id);
			// Encrypt password if present
			if (dmaapAccess.getPassword() != null)
				dmaapAccess.encryptPassword(dmaapAccess.getPassword());

			// Update the existing row
			getDmaapAccessService().saveDmaapAccess(dmaapAccess);

			// Answer "OK"
			outboundJson = buildJsonSuccess(200, null);
		} catch (Exception ex) {
			outboundJson = buildJsonError(500, "Failed to update DMaaP access profile", ex);
		}
		MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
		return outboundJson;
	}

	/**
	 * Deletes a DMaaP access profile if the row user ID matches the requesting
	 * user ID. Traps errors and
	 * constructs an appropriate JSON block if an error happens. 
	 * 
	 * @param id
	 *            Path parameter with ID of the DMaaP access profile
	 * @param request
	 *            HttpServletRequest
	 * @return Trivial JSON object indicating success or failure (altho this is
	 *         slightly contrary to conventions for a DELETE method)
	 */
	@RequestMapping(value = {
			DMAAP_ACCESS_PATH + "/{id}" }, method = RequestMethod.DELETE, produces = "application/json")
	@ResponseBody
	public String deleteDmaapAccess(@PathVariable("id") long id, HttpServletRequest request) {
		MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
		String outboundJson = null;
		try {
			User appUser = UserUtils.getUserSession(request);
			if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
				throw new Exception("deleteDmaapAccess: Failed to get Login ID");
			// Validate that this user owns the row with the specified ID
			DmaapAccess domainObj = getDmaapAccessService().getDmaapAccess(id);
			if (!appUser.getLoginId().equals(domainObj.getUserId()))
				throw new Exception("deleteDmaapAccess: mismatch of appUser and row user ID");

			getDmaapAccessService().deleteDmaapAccess(id);

			// Answer "OK"
			outboundJson = buildJsonSuccess(200, null);
		} catch (Exception ex) {
			outboundJson = buildJsonError(500, "Failed to delete DMaaP access profile", ex);
		}
		MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
		return outboundJson;
	}

	/**
	 * Gets the selected DMaaP access row for the requesting user.
	 * 
	 * See {@link #getSelectedDmaapAccess(String)}
	 * 
	 * @param request
	 *            HttpServletRequest
	 * @return JSON object with one DmaapAccessProfile, or an error
	 */
	@RequestMapping(value = { SELECT_DMAAP_ACCESS_PATH }, method = RequestMethod.GET, produces = "application/json")
	@ResponseBody
	public String getSelectedDmaapAccessProfile(HttpServletRequest request)  {
		MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
		String outboundJson = null;
		try {
			User appUser = UserUtils.getUserSession(request);
			if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
				throw new Exception("getSelectedDmaapAccessProfile: Failed to get Login ID");
			DmaapAccess selected = super.getSelectedDmaapAccess(appUser.getLoginId());
			// clone and decrypt
			DmaapAccess clear = new DmaapAccess(selected);
			try {
				clear.setPassword(clear.decryptPassword());
			} catch (Exception ex) {
				// Should never happen
				throw new RuntimeException("getSelectedDmaapAccessProfile: Failed to decrypt password", ex);
			}
			outboundJson = buildJsonSuccess(200, clear);
		} catch (Exception ex) {
			outboundJson = buildJsonError(500, "Failed to get selected DMaaP access profile", ex);
		}
		MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
		return outboundJson;
	}

	/**
	 * Marks the DMaaP access row as selected (first choice) for the requesting
	 * user if the row user ID matches the requesting user ID. As a side effect,
	 * removes selected marking from all other user rows. Returns status,
	 * additionally an error message on failure. Traps errors and
	 * constructs an appropriate JSON block if an error happens.
	 * 
	 * Choice of PUT is fairly arbitrary - there is no body, but GET is for
	 * actions that do not change data.
	 * 
	 * @param id
	 *            Path parameter with ID of the DMaaP access profile
	 * @param request
	 *            HttpServletRequest
	 * @return Trivial JSON object indicating success or failure.
	 */
	@RequestMapping(value = {
			SELECT_DMAAP_ACCESS_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
	@ResponseBody
	public String selectDmaapAccess(@PathVariable("id") long id, HttpServletRequest request) {
		MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
		String outboundJson = null;
		try {
			User appUser = UserUtils.getUserSession(request);
			if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
				throw new Exception("selectDmaapAccess: Failed to get Login UID");
			// A little inefficient in that it requires 3 database accesses;
			// probably could be done in 1 with some sophisticated SQL.
			List<DmaapAccess> dmaapAccessList = getDmaapAccessService().getDmaapAccessList(appUser.getLoginId());
			for (DmaapAccess dmaap : dmaapAccessList) {
				// Only write out the changed rows.
				boolean changed = false;
				if (id == dmaap.getId()) {
					changed = !dmaap.getSelected();
					dmaap.setSelected(true);
				} else {
					changed = dmaap.getSelected();
					dmaap.setSelected(false);
				}
				if (changed)
					getDmaapAccessService().saveDmaapAccess(dmaap);
			}

			// Answer OK
			outboundJson = buildJsonSuccess(200, null);
		} catch (Exception ex) {
			outboundJson = buildJsonError(500, "Failed to select a DMaaP access profile", ex);
		}
		MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
		return outboundJson;
	}

	/**
	 * Tests the URL in the DMaaP access profile object. Traps errors and
	 * constructs an appropriate JSON block if an error happens.
	 * 
	 * @param request
	 *            HttpServletRequest
	 * @return JSON with a Dmaap object (which has name etc.) on success, error
	 *         on failure.
	 */
	@RequestMapping(value = { "test_dmaap_access" }, method = RequestMethod.POST, produces = "application/json")
	@ResponseBody
	public String testDmaapAccess(HttpServletRequest request)  {
		MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
		String outboundJson = null;
		try {
			DmaapAccess dmaapAccess = mapper.readValue(request.getReader(), DmaapAccess.class);
			logger.debug("testDmaapAccess: received object: {} ", dmaapAccess);
			if (dmaapAccess.getDmaapUrl() == null || dmaapAccess.getDmaapUrl().trim().length() == 0)
				throw new Exception("Null or empty URL");

			DmaapBcRestClient restClient = getDmaapBcRestClient(dmaapAccess);
			// Get the instance so the page can display its name
			DmaapObject dmaap = restClient.getDmaap();
			if (dmaap instanceof Dmaap) {
				outboundJson = buildJsonSuccess(200, dmaap);
			} else {
				// Bad credentials lands here.
				ErrorResponse err = (ErrorResponse) dmaap;
				outboundJson = buildJsonError(500, "Test failed: " + err.getMessage(), null);
			}
		} catch (Exception ex) {
			// This is entirely likely; e.e., unknown host exception on typo.
			outboundJson = buildJsonError(500, "Invalid DMaaP URL", ex);
		}
		MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
		logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
		return outboundJson;
	}

}