Add REST proxy for Security API from backend to web

This commit is contained in:
Yi Wang(Data Infrastructure) 2016-09-19 11:19:48 -07:00 committed by Yi Wang
parent 937637c3ea
commit 1171e00097
11 changed files with 148 additions and 63 deletions

View File

@ -13,8 +13,11 @@
*/
package controllers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
@ -26,6 +29,10 @@ import play.libs.Json;
import play.mvc.BodyParser;
import play.mvc.Controller;
import play.mvc.Result;
import wherehows.common.schemas.DatasetGeographicAffinityRecord;
import wherehows.common.schemas.DatasetRetentionRecord;
import wherehows.common.schemas.DatasetSecurityRecord;
import wherehows.common.utils.StringUtil;
public class DatasetInfoController extends Controller {
@ -399,8 +406,10 @@ public class DatasetInfoController extends Controller {
try {
Map<String, Object> security = DatasetInfoDao.getDatasetSecurityByDatasetId(datasetId);
DatasetSecurityRecord record = convertToDatasetSecurityRecord(security);
resultJson.put("return_code", 200);
resultJson.set("dataset_security", Json.toJson(security));
resultJson.put("datasetId", record.getDatasetId());
resultJson.set("securitySpec", Json.toJson(record));
} catch (EmptyResultDataAccessException e) {
Logger.debug("DataAccessException dataset id: " + datasetId, e);
resultJson.put("return_code", 404);
@ -418,8 +427,10 @@ public class DatasetInfoController extends Controller {
}
try {
Map<String, Object> security = DatasetInfoDao.getDatasetSecurityByDatasetUrn(urn);
DatasetSecurityRecord record = convertToDatasetSecurityRecord(security);
resultJson.put("return_code", 200);
resultJson.set("dataset_security", Json.toJson(security));
resultJson.put("datasetId", record.getDatasetId());
resultJson.set("securitySpec", Json.toJson(record));
} catch (EmptyResultDataAccessException e) {
Logger.debug("DataAccessException urn: " + urn, e);
resultJson.put("return_code", 404);
@ -434,6 +445,32 @@ public class DatasetInfoController extends Controller {
return ok(resultJson);
}
private static DatasetSecurityRecord convertToDatasetSecurityRecord(Map<String, Object> map) {
DatasetSecurityRecord record = new DatasetSecurityRecord();
ObjectMapper om = new ObjectMapper();
try {
record.setDatasetId(StringUtil.toInt(map.get("dataset_id")));
record.setDatasetUrn((String) map.get("dataset_urn"));
record.setClassification(
om.readValue((String) map.get("classification"), new TypeReference<Map<String, Integer>>() {
}));
record.setRecordOwnerType((String) map.get("record_owner_type"));
record.setRecordOwner(om.readValue((String) map.get("record_owner"), new TypeReference<List<String>>() {
}));
record.setComplianceType((String) map.get("compliance_type"));
record.setRetentionPolicy(
om.readValue((String) map.get("retention_policy"), new TypeReference<DatasetRetentionRecord>() {
}));
record.setGeographicAffinity(
om.readValue((String) map.get("geographic_affinity"), new TypeReference<DatasetGeographicAffinityRecord>() {
}));
record.setModifiedTime((Long) map.get("modified_time"));
} catch (IOException ex) {
Logger.debug("Can't serialize DB results: security " + map.toString(), ex);
}
return record;
}
@BodyParser.Of(BodyParser.Json.class)
public static Result updateDatasetSecurity() {
JsonNode root = request().body().asJson();

View File

@ -512,31 +512,37 @@ public class DatasetInfoDao {
public static void updateDatasetSecurity(JsonNode root)
throws Exception {
final JsonNode auditHeader = root.path("auditHeader");
final JsonNode urnNode = root.path("urn");
final JsonNode idNode = root.path("datasetId");
final JsonNode security = root.path("securitySpec");
if (auditHeader.isMissingNode() || urnNode.isMissingNode() || security.isMissingNode()) {
if ((idNode.isMissingNode() && urnNode.isMissingNode()) || security.isMissingNode()) {
throw new IllegalArgumentException(
"Dataset security info update fail, " + "Json missing necessary fields: " + root.toString());
}
final String urn = urnNode.asText();
final Long eventTime = auditHeader.path("time").asLong() / 1000; // millisecond to second
final Integer datasetId = Integer.valueOf(DatasetDao.getDatasetByUrn(urn).get("id").toString());
final Integer datasetId;
final String urn;
if (!idNode.isMissingNode()) {
datasetId = idNode.asInt();
urn = DatasetDao.getDatasetById(datasetId).get("urn").toString();
} else {
urn = urnNode.asText();
datasetId = Integer.valueOf(DatasetDao.getDatasetByUrn(urn).get("id").toString());
}
ObjectMapper om = new ObjectMapper();
DatasetSecurityRecord record = om.convertValue(security, DatasetSecurityRecord.class);
record.setDataset(datasetId, urn);
record.setModifiedTime(eventTime);
record.setDatasetId(datasetId);
record.setDatasetUrn(urn);
record.setModifiedTime(System.currentTimeMillis() / 1000);
try {
Map<String, Object> result = getDatasetSecurityByDatasetUrn(urn);
Map<String, Object> result = getDatasetSecurityByDatasetId(datasetId);
String[] columns = record.getDbColumnNames();
Object[] columnValues = record.getAllValuesToString();
String[] conditions = {"dataset_urn"};
Object[] conditionValues = new Object[]{urn};
String[] conditions = {"dataset_id"};
Object[] conditionValues = new Object[]{datasetId};
SECURITY_WRITER.update(columns, columnValues, conditions, conditionValues);
} catch (EmptyResultDataAccessException ex) {
SECURITY_WRITER.append(record);

View File

@ -20,8 +20,12 @@ import models.DatasetColumn;
import models.DatasetDependency;
import models.DatasetListViewNode;
import models.ImpactDataset;
import play.Play;
import play.api.libs.json.JsValue;
import play.api.mvc.SimpleResult;
import play.libs.F;
import play.libs.Json;
import play.libs.WS;
import play.mvc.BodyParser;
import play.mvc.Controller;
import play.mvc.Result;
@ -32,9 +36,15 @@ import dao.DatasetsDAO;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import scala.concurrent.Future;
public class Dataset extends Controller
{
public static final String BACKEND_SERVICE_URL_KEY = "backend.service.url";
public static final String DATASET_SECURITY_PATH = "/dataset/security";
public static Result getDatasetOwnerTypes()
{
ObjectNode result = Json.newObject();
@ -831,4 +841,49 @@ public class Dataset extends Controller
return ok(result);
}
public static F.Promise<Result> getDatasetSecurity(int datasetId) {
final String backendUrl = Play.application().configuration().getString(BACKEND_SERVICE_URL_KEY);
final String queryUrl = backendUrl + DATASET_SECURITY_PATH;
final F.Promise<Result> resultPromise = WS.url(queryUrl)
.setQueryParameter("datasetId", Integer.toString(datasetId))
.get()
.map(new F.Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok(response.asJson());
}
});
return resultPromise;
}
public static F.Promise<Result> updateDatasetSecurity(int datasetId) {
String username = session("user");
if (StringUtils.isNotBlank(username)) {
final String backendUrl = Play.application().configuration().getString(BACKEND_SERVICE_URL_KEY);
final String queryUrl = backendUrl + DATASET_SECURITY_PATH;
final ObjectNode queryNode = Json.newObject();
queryNode.put("datasetId", datasetId);
queryNode.put("securitySpec", request().body().asJson());
final F.Promise<Result> resultPromise = WS.url(queryUrl)
.post(queryNode)
.map(new F.Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok(response.asJson());
}
});
return resultPromise;
} else {
ObjectNode result = Json.newObject();
result.put("status", "failed");
result.put("error", "true");
result.put("msg", "Unauthorized User.");
return F.Promise.promise(new F.Function0<Result>() {
public Result apply() {
return ok(result);
}
});
}
}
}

View File

@ -79,6 +79,7 @@ search.engine = "default"
elasticsearch.dataset.url = "$YOUR_DATASET_INDEX_URL"
elasticsearch.flow.url = "$YOUR_FLOW_INDEX_URL"
backend.service.url = "$YOUR_BACKEND_SERVICE_URL"
authentication.ldap.url = "$YOUR_LDAP_SERVER"
authentication.ldap.context_factory_class = "com.sun.jndi.ldap.LdapCtxFactory"

View File

@ -109,6 +109,10 @@ POST /api/v1/datasets/:id/watch controllers.api.v1.Dataset.w
DELETE /api/v1/datasets/:id/watch/:watchId controllers.api.v1.Dataset.unwatchDataset(id:Int, watchId:Int)
GET /api/v1/datasets/:id/security controllers.api.v1.Dataset.getDatasetSecurity(id:Int)
POST /api/v1/datasets/:id/security controllers.api.v1.Dataset.updateDatasetSecurity(id:Int)
GET /api/v1/urn/watch controllers.api.v1.Dataset.getWatchedUrnId()
POST /api/v1/urn/watch controllers.api.v1.Dataset.watchURN()

View File

@ -13,6 +13,7 @@
*/
package wherehows.common.schemas;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
@ -56,6 +57,7 @@ public abstract class AbstractRecord implements Record {
* return all declared fields of the class, exclude inherited fields
* @return Field[]
*/
@JsonIgnore
public Field[] getAllFields() {
return this.getClass().getDeclaredFields();
}
@ -65,6 +67,7 @@ public abstract class AbstractRecord implements Record {
* @return Object[]
* @throws IllegalAccessException
*/
@JsonIgnore
public Object[] getAllValues()
throws IllegalAccessException {
final Field[] fields = this.getAllFields();
@ -80,6 +83,7 @@ public abstract class AbstractRecord implements Record {
* return the corresponding database column names to the class fields
* @return
*/
@JsonIgnore
public String[] getDbColumnNames() {
return null;
}
@ -90,11 +94,12 @@ public abstract class AbstractRecord implements Record {
* @return Object[]
* @throws IllegalAccessException
*/
@JsonIgnore
public Object[] getAllValuesToString()
throws IllegalAccessException {
final Object[] values = getAllValues();
for (int i = 0; i < values.length; i++) {
values[i] = StringUtil.objectToString(values[i]);
values[i] = StringUtil.objectToJsonString(values[i]);
}
return values;
}
@ -105,6 +110,7 @@ public abstract class AbstractRecord implements Record {
* @return Map: String-Object
* @throws IllegalAccessException
*/
@JsonIgnore
public Map<String, Object> getFieldValueMap()
throws IllegalAccessException {
String[] columns = this.getDbColumnNames();

View File

@ -13,11 +13,7 @@
*/
package wherehows.common.schemas;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DatasetGeographicAffinityRecord extends AbstractRecord {
@ -25,11 +21,6 @@ public class DatasetGeographicAffinityRecord extends AbstractRecord {
String affinity;
List<DatasetLocaleRecord> locations;
@Override
public String[] getDbColumnNames() {
return new String[]{"affinity", "locations"};
}
@Override
public List<Object> fillAllFields() {
return null;
@ -38,18 +29,6 @@ public class DatasetGeographicAffinityRecord extends AbstractRecord {
public DatasetGeographicAffinityRecord() {
}
@Override
public String toString() {
try {
Map<String, String> valueMap = new HashMap<>();
valueMap.put("affinity", affinity);
valueMap.put("locations", locations.toString());
return new ObjectMapper().writeValueAsString(valueMap);
} catch (JsonProcessingException ex) {
return null;
}
}
public String getAffinity() {
return affinity;
}

View File

@ -13,10 +13,6 @@
*/
package wherehows.common.schemas;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DatasetLocaleRecord {
String language;
@ -26,15 +22,6 @@ public class DatasetLocaleRecord {
public DatasetLocaleRecord() {
}
@Override
public String toString() {
try {
return new ObjectMapper().writeValueAsString(this);
} catch (JsonProcessingException ex) {
return null;
}
}
public String getLanguage() {
return language;
}

View File

@ -22,11 +22,6 @@ public class DatasetRetentionRecord extends AbstractRecord {
Long retentionWindow;
String retentionWindowUnit;
@Override
public String[] getDbColumnNames() {
return new String[]{"retention_type", "retention_window", "retention_window_unit"};
}
@Override
public List<Object> fillAllFields() {
return null;
@ -35,15 +30,6 @@ public class DatasetRetentionRecord extends AbstractRecord {
public DatasetRetentionRecord() {
}
@Override
public String toString() {
try {
return this.getFieldValueMap().toString();
} catch (IllegalAccessException ex) {
return null;
}
}
public String getRetentionType() {
return retentionType;
}

View File

@ -43,8 +43,19 @@ public class DatasetSecurityRecord extends AbstractRecord {
public DatasetSecurityRecord() {
}
public void setDataset(Integer datasetId, String datasetUrn) {
public Integer getDatasetId() {
return datasetId;
}
public void setDatasetId(Integer datasetId) {
this.datasetId = datasetId;
}
public String getDatasetUrn() {
return datasetUrn;
}
public void setDatasetUrn(String datasetUrn) {
this.datasetUrn = datasetUrn;
}

View File

@ -13,6 +13,8 @@
*/
package wherehows.common.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
@ -57,6 +59,17 @@ public class StringUtil {
return obj;
}
public static Object objectToJsonString(Object obj) {
if (obj instanceof Collection || obj instanceof Map || obj instanceof Object[] || obj instanceof Record) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (JsonProcessingException ex) {
return obj;
}
}
return obj;
}
public static String toStr(Object obj) {
return obj != null ? obj.toString() : null;
}