2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * ============LICENSE_END=============================================
20 * ====================================================================
22 package org.onap.music.rest;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
29 import java.util.UUID;
30 import javax.ws.rs.Consumes;
31 import javax.ws.rs.DELETE;
32 import javax.ws.rs.GET;
33 import javax.ws.rs.POST;
34 import javax.ws.rs.PUT;
35 import javax.ws.rs.Path;
36 import javax.ws.rs.Produces;
37 import javax.ws.rs.core.HttpHeaders;
38 import javax.ws.rs.core.MediaType;
39 import javax.ws.rs.core.Response;
40 import javax.ws.rs.core.Response.ResponseBuilder;
41 import javax.ws.rs.core.Response.Status;
43 import org.mindrot.jbcrypt.BCrypt;
44 import org.onap.music.datastore.PreparedQueryObject;
45 import org.onap.music.datastore.jsonobjects.JSONObject;
46 import org.onap.music.datastore.jsonobjects.JsonCallback;
47 import org.onap.music.datastore.jsonobjects.JsonOnboard;
48 import org.onap.music.eelf.logging.EELFLoggerDelegate;
49 import org.onap.music.eelf.logging.format.AppMessages;
50 import org.onap.music.eelf.logging.format.ErrorSeverity;
51 import org.onap.music.eelf.logging.format.ErrorTypes;
52 //import org.onap.music.main.CacheAccess;
53 import org.onap.music.main.CachingUtil;
54 import org.onap.music.main.MusicCore;
55 import org.onap.music.main.MusicUtil;
56 import org.onap.music.main.ResultType;
57 import org.onap.music.response.jsonobjects.JsonResponse;
59 import com.datastax.driver.core.DataType;
60 import com.datastax.driver.core.ResultSet;
61 import com.datastax.driver.core.Row;
62 import com.datastax.driver.core.exceptions.InvalidQueryException;
63 import com.sun.jersey.api.client.Client;
64 import com.sun.jersey.api.client.ClientResponse;
65 import com.sun.jersey.api.client.WebResource;
66 import com.sun.jersey.core.util.Base64;
68 import io.swagger.annotations.Api;
69 import io.swagger.annotations.ApiOperation;
70 import org.apache.commons.jcs.JCS;
71 import org.apache.commons.jcs.access.CacheAccess;
74 // @Path("/v{version: [0-9]+}/admin")
76 @Api(value = "Admin Api", hidden = true)
77 public class RestMusicAdminAPI {
78 private static EELFLoggerDelegate logger =
79 EELFLoggerDelegate.getLogger(RestMusicAdminAPI.class);
81 * API to onboard an application with MUSIC. This is the mandatory first step.
85 @Path("/onboardAppWithMusic")
86 @ApiOperation(value = "Onboard application", response = String.class)
87 @Consumes(MediaType.APPLICATION_JSON)
88 @Produces(MediaType.APPLICATION_JSON)
89 public Response onboardAppWithMusic(JsonOnboard jsonObj) throws Exception {
90 ResponseBuilder response =
91 Response.noContent().header("X-latestVersion", MusicUtil.getVersion());
92 Map<String, Object> resultMap = new HashMap<>();
93 String appName = jsonObj.getAppname();
94 String userId = jsonObj.getUserId();
95 String isAAF = jsonObj.getIsAAF();
96 String password = jsonObj.getPassword();
97 if (appName == null || userId == null || isAAF == null || password == null) {
98 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO,
99 ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
100 resultMap.put("Exception",
101 "Unauthorized: Please check the request parameters. Some of the required values appName(ns), userId, password, isAAF are missing.");
102 return Response.status(Status.UNAUTHORIZED).entity(resultMap).build();
105 PreparedQueryObject pQuery = new PreparedQueryObject();
106 pQuery.appendQueryString(
107 "select uuid from admin.keyspace_master where application_name = ? allow filtering");
108 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
109 ResultSet rs = MusicCore.get(pQuery);
110 if (!rs.all().isEmpty()) {
111 resultMap.put("Exception", "Application " + appName
112 + " has already been onboarded. Please contact admin.");
113 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
116 pQuery = new PreparedQueryObject();
117 String uuid = CachingUtil.generateUUID();
118 pQuery.appendQueryString(
119 "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, "
120 + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)");
121 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
122 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
123 MusicUtil.DEFAULTKEYSPACENAME));
124 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
125 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True"));
126 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt())));
127 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
128 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF));
130 String returnStr = MusicCore.eventualPut(pQuery).toString();
131 if (returnStr.contains("Failure")) {
132 resultMap.put("Exception",
133 "Oops. Something wrong with onboarding process. Please retry later or contact admin.");
134 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
136 CachingUtil.updateisAAFCache(appName, isAAF);
137 resultMap.put("Success", "Your application " + appName + " has been onboarded with MUSIC.");
138 resultMap.put("Generated AID", uuid);
139 return Response.status(Status.OK).entity(resultMap).build();
145 @ApiOperation(value = "Search Onboard application", response = String.class)
146 @Consumes(MediaType.APPLICATION_JSON)
147 @Produces(MediaType.APPLICATION_JSON)
148 public Response getOnboardedInfoSearch(JsonOnboard jsonObj) throws Exception {
149 Map<String, Object> resultMap = new HashMap<>();
150 ResponseBuilder response =
151 Response.noContent().header("X-latestVersion", MusicUtil.getVersion());
152 String appName = jsonObj.getAppname();
153 String uuid = jsonObj.getAid();
154 String isAAF = jsonObj.getIsAAF();
156 if (appName == null && uuid == null && isAAF == null) {
157 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO,
158 ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
159 resultMap.put("Exception",
160 "Unauthorized: Please check the request parameters. Enter atleast one of the following parameters: appName(ns), aid, isAAF.");
161 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
164 PreparedQueryObject pQuery = new PreparedQueryObject();
165 String cql = "select uuid, keyspace_name from admin.keyspace_master where ";
167 cql = cql + "application_name = ? AND ";
169 cql = cql + "uuid = ? AND ";
171 cql = cql + "is_aaf = ?";
173 if (cql.endsWith("AND "))
174 cql = cql.trim().substring(0, cql.length() - 4);
175 System.out.println("Query is: " + cql);
176 cql = cql + " allow filtering";
177 System.out.println("Get OnboardingInfo CQL: " + cql);
178 pQuery.appendQueryString(cql);
180 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
182 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
184 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(),
185 Boolean.parseBoolean(isAAF)));
186 ResultSet rs = MusicCore.get(pQuery);
187 Iterator<Row> it = rs.iterator();
188 while (it.hasNext()) {
189 Row row = (Row) it.next();
190 resultMap.put(row.getUUID("uuid").toString(), row.getString("keyspace_name"));
192 if (resultMap.isEmpty()) {
194 resultMap.put("Exception",
195 "Please make sure Aid is correct and application is onboarded.");
196 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
198 resultMap.put("Exception",
199 "Application is not onboarded. Please make sure all the information is correct.");
200 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
203 return Response.status(Status.OK).entity(resultMap).build();
208 @Path("/onboardAppWithMusic")
209 @ApiOperation(value = "Delete Onboard application", response = String.class)
210 @Consumes(MediaType.APPLICATION_JSON)
211 @Produces(MediaType.APPLICATION_JSON)
212 public Response deleteOnboardApp(JsonOnboard jsonObj) throws Exception {
213 Map<String, Object> resultMap = new HashMap<>();
214 ResponseBuilder response =
215 Response.noContent().header("X-latestVersion", MusicUtil.getVersion());
216 String appName = jsonObj.getAppname();
217 String aid = jsonObj.getAid();
218 PreparedQueryObject pQuery = new PreparedQueryObject();
219 String consistency = MusicUtil.EVENTUAL;;
220 if (appName == null && aid == null) {
221 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO,
222 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
223 resultMap.put("Exception", "Please make sure either appName(ns) or Aid is present");
224 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
227 pQuery.appendQueryString(
228 "SELECT keyspace_name FROM admin.keyspace_master WHERE uuid = ?");
229 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(),
230 UUID.fromString(aid)));
231 Row row = MusicCore.get(pQuery).one();
233 String ks = row.getString("keyspace_name");
234 if (!ks.equals(MusicUtil.DEFAULTKEYSPACENAME)) {
235 PreparedQueryObject queryObject = new PreparedQueryObject();
236 queryObject.appendQueryString("DROP KEYSPACE IF EXISTS " + ks + ";");
237 MusicCore.nonKeyRelatedPut(queryObject, consistency);
240 pQuery = new PreparedQueryObject();
241 pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ? IF EXISTS");
242 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(),
243 UUID.fromString(aid)));
244 ResultType result = MusicCore.nonKeyRelatedPut(pQuery, consistency);
245 if (result == ResultType.SUCCESS) {
246 resultMap.put("Success", "Your application has been deleted successfully");
248 resultMap.put("Exception",
249 "Oops. Something went wrong. Please make sure Aid is correct or Application is onboarded");
250 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA,
251 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
252 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
255 return Response.status(Status.OK).entity(resultMap).build();
258 pQuery.appendQueryString(
259 "select uuid from admin.keyspace_master where application_name = ? allow filtering");
260 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
261 ResultSet rs = MusicCore.get(pQuery);
262 List<Row> rows = rs.all();
264 if (rows.size() == 0) {
265 resultMap.put("Exception",
266 "Application not found. Please make sure Application exists.");
267 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA,
268 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
269 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
270 } else if (rows.size() == 1) {
271 uuid = rows.get(0).getUUID("uuid").toString();
272 pQuery = new PreparedQueryObject();
273 pQuery.appendQueryString(
274 "SELECT keyspace_name FROM admin.keyspace_master WHERE uuid = ?");
275 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(),
276 UUID.fromString(uuid)));
277 Row row = MusicCore.get(pQuery).one();
278 String ks = row.getString("keyspace_name");
279 if (!ks.equals(MusicUtil.DEFAULTKEYSPACENAME)) {
280 PreparedQueryObject queryObject = new PreparedQueryObject();
281 queryObject.appendQueryString("DROP KEYSPACE " + ks + ";");
282 MusicCore.nonKeyRelatedPut(queryObject, consistency);
285 pQuery = new PreparedQueryObject();
286 pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?");
287 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(),
288 UUID.fromString(uuid)));
289 MusicCore.eventualPut(pQuery);
290 resultMap.put("Success", "Your application " + appName + " has been deleted.");
291 return Response.status(Status.OK).entity(resultMap).build();
293 resultMap.put("Failure",
294 "More than one Aid exists for this application, so please provide Aid.");
295 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MULTIPLERECORDS,
296 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
297 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
303 @Path("/onboardAppWithMusic")
304 @ApiOperation(value = "Update Onboard application", response = String.class)
305 @Consumes(MediaType.APPLICATION_JSON)
306 @Produces(MediaType.APPLICATION_JSON)
307 public Response updateOnboardApp(JsonOnboard jsonObj) throws Exception {
308 Map<String, Object> resultMap = new HashMap<>();
309 ResponseBuilder response =
310 Response.noContent().header("X-latestVersion", MusicUtil.getVersion());
311 String aid = jsonObj.getAid();
312 String appName = jsonObj.getAppname();
313 String userId = jsonObj.getUserId();
314 String isAAF = jsonObj.getIsAAF();
315 String password = jsonObj.getPassword();
316 String consistency = "eventual";
317 PreparedQueryObject pQuery;
320 resultMap.put("Exception", "Please make sure Aid is present");
321 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
322 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
323 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
326 if (appName == null && userId == null && password == null && isAAF == null) {
327 resultMap.put("Exception",
328 "No parameters found to update. Please update atleast one parameter.");
329 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
330 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
331 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
334 if (appName != null) {
335 pQuery = new PreparedQueryObject();
336 pQuery.appendQueryString(
337 "select uuid from admin.keyspace_master where application_name = ? allow filtering");
338 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
339 ResultSet rs = MusicCore.get(pQuery);
340 if (!rs.all().isEmpty()) {
341 resultMap.put("Exception", "Application " + appName
342 + " has already been onboarded. Please contact admin.");
343 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.ALREADYEXIST,
344 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
345 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
349 pQuery = new PreparedQueryObject();
350 StringBuilder preCql = new StringBuilder("UPDATE admin.keyspace_master SET ");
352 preCql.append(" application_name = ?,");
354 preCql.append(" username = ?,");
355 if (password != null)
356 preCql.append(" password = ?,");
358 preCql.append(" is_aaf = ?,");
359 preCql.deleteCharAt(preCql.length() - 1);
360 preCql.append(" WHERE uuid = ? IF EXISTS");
361 pQuery.appendQueryString(preCql.toString());
363 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
365 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
366 if (password != null)
367 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt())));
369 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF));
371 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), UUID.fromString(aid)));
372 ResultType result = MusicCore.nonKeyRelatedPut(pQuery, consistency);
374 if (result == ResultType.SUCCESS) {
375 resultMap.put("Success", "Your application has been updated successfully");
377 resultMap.put("Exception",
378 "Oops. Something went wrong. Please make sure Aid is correct and application is onboarded");
379 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA,
380 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
381 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
384 return Response.status(Status.OK).entity(resultMap).build();
387 Client client = Client.create();
390 @Path("/callbackOps")
391 @Produces(MediaType.APPLICATION_JSON)
392 @Consumes(MediaType.APPLICATION_JSON)
393 public String callbackOps(JSONObject inputJsonObj) {
394 // trigger response {"full_table":"admin.race_winners","keyspace":"admin","name":"Siri","operation":"update","table_name":"race_winner","primary_key":"1"}
396 logger.info("Got notification: " + inputJsonObj.getData());
397 String dataStr = inputJsonObj.getData();
398 String[] dataStrArr = dataStr.substring(1, dataStr.length() - 1).split(",");
400 for (String key : dataStrArr) {
401 if (key.contains("full_table")) {
402 String tableName = key.split(":")[1].substring(1, key.split(":")[1].length() - 1);
403 PreparedQueryObject pQuery = new PreparedQueryObject();
404 pQuery.appendQueryString(
405 "select endpoint, username, password from admin.callback_api where changes = ? allow filtering");
406 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), tableName));
407 ResultSet rs = MusicCore.get(pQuery);
408 Row row = rs.all().get(0);
410 String endpoint = row.getString("endpoint");
411 String username = row.getString("username");
412 String password = row.getString("password");
413 logger.info("Notifying the changes to endpoint: "+endpoint);
414 WebResource webResource = client.resource(endpoint);
415 String authData = username+":"+password;
416 byte[] plainCredsBytes = authData.getBytes();
417 byte[] base64CredsBytes = Base64.encode(plainCredsBytes);
418 String base64Creds = new String(base64CredsBytes);
419 ClientResponse response = webResource.header("Authorization", "Basic " + base64Creds).accept("application/json")
420 .post(ClientResponse.class, inputJsonObj);
421 if(response.getStatus() != 200){
422 logger.error("Exception while notifying");
428 } catch(Exception e) {
430 logger.info("Exception...");
436 @Path("/addCallback")
437 @Produces(MediaType.APPLICATION_JSON)
438 @Consumes(MediaType.APPLICATION_JSON)
439 public Response addCallback(JsonCallback jsonCallback) throws Exception {
440 Map<String, Object> resultMap = new HashMap<>();
441 ResponseBuilder response =
442 Response.noContent().header("X-latestVersion", MusicUtil.getVersion());
443 String username = jsonCallback.getApplicationUsername();
444 String password = jsonCallback.getApplicationPassword();
445 String endpoint = jsonCallback.getApplicationNotificationEndpoint();
446 String changes = jsonCallback.getNotifyWhenChangeIn();
447 String inserts = jsonCallback.getNotifyWhenInsertsIn();
448 String deletes = jsonCallback.getNotifyWhenDeletesIn();
449 PreparedQueryObject pQuery = new PreparedQueryObject();
450 if (username == null || password == null || endpoint == null || changes == null || inserts == null || deletes == null) {
451 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO,
452 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
453 resultMap.put("Exception",
454 "Please check the request parameters. Some of the required values are missing.");
455 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
457 String uuid = CachingUtil.generateUUID();
459 pQuery.appendQueryString(
460 "INSERT INTO admin.callback_api (uuid, username, password, endpoint, "
461 + "changes, inserts, deletes) VALUES (?,?,?,?,?,?,?)");
462 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
463 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), username));
464 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), password));
465 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), endpoint));
466 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), changes));
467 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), inserts));
468 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), deletes));
469 MusicCore.eventualPut(pQuery);
471 Map<String, String> jsonMap = new HashMap<>();
472 jsonMap.put("username", username);
473 jsonMap.put("password", password);
474 jsonMap.put("endpoint", endpoint);
475 jsonMap.put("changes", changes);
476 jsonMap.put("inserts", inserts);
477 jsonMap.put("deletes", deletes);
479 //callBackCache.put(jsonCallback.getApplicationName(), jsonMap);
480 } catch (InvalidQueryException e) {
481 logger.error(EELFLoggerDelegate.errorLogger,"Exception callback_api table not configured."+e.getMessage());
482 resultMap.put("Exception", "Please make sure admin.callback_api table is configured.");
483 return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
485 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Callback api successfully registered").toMap()).build();