Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ Dynapi ] Fix dynapi model factory #346

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
813aad9
Renamed SparqlQuery component to SparqlSelectQuery
litvinovg Aug 26, 2022
fb71feb
added SparqlConstructQuery component
litvinovg Aug 26, 2022
7f230d7
added simple sparql query integration tests.
litvinovg Aug 26, 2022
8f83a06
Instead of throwing error on empty sparql request provide default values
litvinovg Aug 29, 2022
7ed9a4c
basic implementation of DynapiJsonObject
litvinovg Sep 14, 2022
442a743
tests improvements
litvinovg Sep 14, 2022
85d3d03
refact: renamed DynapiJsonObject to JsonContainer
litvinovg Sep 27, 2022
d716046
Report Generator component start
litvinovg Sep 27, 2022
1caffa5
improvements for Report Generator
litvinovg Sep 28, 2022
3ecc545
json type added, sparql select produce json, test added
litvinovg Sep 28, 2022
3c2450e
ReportGenerator (supports xslx and docx)
litvinovg Sep 29, 2022
c4d84a8
removed unused imports
litvinovg Sep 30, 2022
d3284c4
added ontology ReportGenerator class and properties
litvinovg Sep 30, 2022
3e1e612
Added integration tests for ReportGenerator. Extended usage of intern…
litvinovg Sep 30, 2022
d87992e
Added language tag filtering in SPARQL Queries
litvinovg Oct 4, 2022
7c8881a
Sparql select language filtering test added
litvinovg Oct 4, 2022
28b2738
I18n regression fix (#289)
litvinovg May 20, 2022
621aad3
Parsing accept-language header in converter
litvinovg Oct 4, 2022
16eb53d
Cleanup, fixed formatting
litvinovg Oct 4, 2022
881a831
fix: missed character
litvinovg Oct 5, 2022
d310556
fix n3 syntax mistake
litvinovg Oct 10, 2022
5f2d386
improved content type detection
litvinovg Oct 21, 2022
835ccfa
Avoid dereferencing internal components
litvinovg Oct 21, 2022
b6f214c
User permissions check
litvinovg Oct 21, 2022
c755c5b
remove unused imports
litvinovg Oct 24, 2022
4ae53d9
removed unsafe method and obsolete commented code
litvinovg Nov 3, 2022
19cd5e6
fix: sparql query validation check
litvinovg Nov 3, 2022
42ed273
Update api/src/test/java/edu/cornell/mannlib/vitro/webapp/dynapi/Vali…
litvinovg Nov 3, 2022
e949bc7
Update api/src/test/java/edu/cornell/mannlib/vitro/webapp/dynapi/data…
litvinovg Nov 3, 2022
f25a2b8
Update api/src/test/java/edu/cornell/mannlib/vitro/webapp/dynapi/Vali…
litvinovg Nov 3, 2022
dd593a9
fixed variable names
litvinovg Nov 3, 2022
1bd0f32
Merge branch 'sparql' of github.com:litvinovg/Vitro into sparql
litvinovg Nov 3, 2022
336a6a4
added manual debugging code for report generator integration test
litvinovg Nov 3, 2022
d066f4c
fix for validators test
litvinovg Nov 3, 2022
824f590
removed comment
litvinovg Nov 3, 2022
96609f5
removed comments, extracted constant in SolrQueryTest
litvinovg Nov 3, 2022
380d14d
review fix for ValidatorsTest
litvinovg Nov 3, 2022
932b4a6
fix for langString literal param rdf type
litvinovg Nov 3, 2022
995079b
fixed GroupAccessWhitelist debug logging according to initial idea
litvinovg Nov 3, 2022
c10b096
fix for ReportGeneratorTest
litvinovg Nov 4, 2022
6875a6e
LangStringLiteralParam review fixes
litvinovg Nov 4, 2022
cd07cd7
get graph uri by name to pass it to provide to model access
litvinovg Nov 7, 2022
1cfc1c5
removed duplicate
litvinovg Nov 9, 2022
262a253
Revert "get graph uri by name to pass it to provide to model access"
litvinovg Nov 10, 2022
2a4efa6
substituted graph names with uri to access all graphs by uri
litvinovg Nov 10, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -26,7 +26,7 @@
import edu.cornell.mannlib.vitro.webapp.dynapi.components.ResourceAPIKey;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.Version;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.serialization.ArraySerializationType;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.serialization.JsonObjectSerializationType;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.serialization.JsonContainerSerializationType;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.serialization.PrimitiveSerializationType;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.serialization.SerializationType;
import edu.cornell.mannlib.vitro.webapp.dynapi.request.ApiRequestPath;
Expand Down Expand Up @@ -644,15 +644,15 @@ private void buildObjectSchema(ObjectSchema objectSchema, Parameters parameters)

objectSchema.addProperties(parameterName, primitiveParameter);

} else if (serializationType instanceof JsonObjectSerializationType) {
} else if (serializationType instanceof JsonContainerSerializationType) {

ObjectSchema objectParameter = new ObjectSchema();

objectParameter.setDescription(parameter.getDescription());

objectSchema.addProperties(parameterName, objectParameter);

buildObjectSchema(objectParameter, ((JsonObjectSerializationType) serializationType).getInternalElements());
buildObjectSchema(objectParameter, ((JsonContainerSerializationType) serializationType).getInternalElements());

} else if (serializationType instanceof ArraySerializationType) {

Expand All @@ -676,14 +676,14 @@ private void buildArraySchema(ArraySchema arraySchema, Parameter parameter) {

if (arrayParameterType instanceof PrimitiveSerializationType) {
primitiveParameter = toPrimativeSchema(arrayParameterType);
} else if (arrayParameterType instanceof JsonObjectSerializationType) {
} else if (arrayParameterType instanceof JsonContainerSerializationType) {

primitiveParameter = new ObjectSchema();

primitiveParameter.setDescription(parameter.getDescription());

buildObjectSchema((ObjectSchema) primitiveParameter,
((JsonObjectSerializationType) arrayParameterType).getInternalElements());
((JsonContainerSerializationType) arrayParameterType).getInternalElements());

} else if (parameterType instanceof ArraySerializationType) {

Expand Down
Expand Up @@ -13,6 +13,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.Action;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.DefaultResourceAPI;
Expand Down Expand Up @@ -141,6 +142,11 @@ private void process(HttpServletRequest request, HttpServletResponse response) {
actionPool.printKeys();
}
Action action = actionPool.get(actionName);
UserAccount user = (UserAccount) request.getSession(false).getAttribute("user");
if (!action.hasPermissions(user)) {
OperationResult.notAuthorized().prepareResponse(response);
return;
}
DataStore dataStore = new DataStore();
if (requestPath.isResourceRequest()) {
dataStore.setResourceID(requestPath.getResourceId());
Expand Down
Expand Up @@ -9,6 +9,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.Action;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.OperationResult;
Expand All @@ -20,7 +21,7 @@
@WebServlet(name = "RPCEndpoint", urlPatterns = { RPC_SERVLET_PATH + "/*" })
public class RPCEndpoint extends VitroHttpServlet {

private static final Log log = LogFactory.getLog(RESTEndpoint.class);
private static final Log log = LogFactory.getLog(RPCEndpoint.class);

private ActionPool actionPool = ActionPool.getInstance();

Expand All @@ -37,13 +38,18 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) {
actionPool.printKeys();
}
Action action = actionPool.get(requestPath.getActionName());
UserAccount user = (UserAccount) request.getSession(false).getAttribute("user");
if (!action.hasPermissions(user)) {
OperationResult.notAuthorized().prepareResponse(response);
return;
}
DataStore dataStore = new DataStore();
if (requestPath.isResourceRequest()) {
dataStore.setResourceID(requestPath.getResourceId());
}
try {
Converter.convert(request, action, dataStore);
} catch (ConversionException e) {
} catch (Exception e) {
log.error(e,e);
response.setStatus(500);
return;
Expand Down
@@ -0,0 +1,11 @@
package edu.cornell.mannlib.vitro.webapp.dynapi.access;

import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;

public interface AccessWhitelist {

public boolean isAuthorized(UserAccount user);

public void setActionName(String name);

}
@@ -0,0 +1,44 @@
package edu.cornell.mannlib.vitro.webapp.dynapi.access;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.Property;

public class GroupAccessWhitelist implements AccessWhitelist {

private static final Log log = LogFactory.getLog(GroupAccessWhitelist.class);
private Map<String, UserGroup> groups = new HashMap<String, UserGroup>();
private String actionName = "action name not provided";

@Property(uri = "https://vivoweb.org/ontology/vitro-dynamic-api#userGroup")
public void addAccessFilter(UserGroup userGroup) {
groups.put(userGroup.getName(), userGroup);
}

@Override
public boolean isAuthorized(UserAccount user) {
Set<String> uris = user.getPermissionSetUris();
for (String uri : uris) {
UserGroup userGroup = groups.get(uri);
if (groups.containsKey(uri)) {
log.debug("Group '" + userGroup.getLabel() + "' membership allows '" + user.getEmailAddress() + "' to access action '" + actionName + "'");
return true;
}
log.debug("Group '" + userGroup.getLabel() + "' membership doesn't allow '" + user.getEmailAddress() + "' to access action '" + actionName + "'");
}
log.debug("Whitelist is doesn't allow user '" + user.getEmailAddress() + "' to access action '" + actionName + "'");
return false;
}

@Override
public void setActionName(String name) {
this.actionName = name;
}

}
@@ -0,0 +1,31 @@
package edu.cornell.mannlib.vitro.webapp.dynapi.access;

import edu.cornell.mannlib.vitro.webapp.utils.configuration.Property;

public class UserGroup {

private String name;
private String label;


@Property(uri = "http://www.w3.org/2000/01/rdf-schema#label")
public void setLabel(String label) {
this.label = label;
}

public String getLabel() {
if (label != null) {
return label;
}
return name;
}

@Property(uri = "https://vivoweb.org/ontology/vitro-dynamic-api#name", minOccurs = 1, maxOccurs = 1)
public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}
Expand Up @@ -58,7 +58,7 @@ private void process(HttpServletRequest request, HttpServletResponse response) {
return;
}

request.getSession().setAttribute("logged_in_user", user);
request.getSession().setAttribute("user", user);
response.setStatus(200);
}

Expand Down
Expand Up @@ -2,6 +2,8 @@

import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
Expand All @@ -10,6 +12,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.dynapi.access.AccessWhitelist;
import edu.cornell.mannlib.vitro.webapp.dynapi.computation.AutoConfiguration;
import edu.cornell.mannlib.vitro.webapp.dynapi.computation.StepInfo;
import edu.cornell.mannlib.vitro.webapp.dynapi.data.DataStore;
Expand All @@ -28,20 +32,23 @@ public class Action extends Operation implements Poolable<String>, StepInfo {
private Parameters outputParams = new Parameters();
private Parameters inputParams = new Parameters();
private Parameters internalParams = new Parameters();
private List<AccessWhitelist> accessWhitelists = new LinkedList<AccessWhitelist>();

@Override
public void dereference() {
firstStep.dereference();
firstStep = null;
rpc.dereference();
rpc = null;
}

@Override
public OperationResult run(DataStore dataStore) {
return firstStep.run(dataStore);
}

@Property(uri = "https://vivoweb.org/ontology/vitro-dynamic-api#accessWhiteList")
public void addAccessFilter(AccessWhitelist whiteList) {
accessWhitelists.add(whiteList);
whiteList.setActionName(rpc.getName());
}

@Property(uri = "https://vivoweb.org/ontology/vitro-dynamic-api#hasFirstStep", minOccurs = 1, maxOccurs = 1)
public void setStep(Step step) {
this.firstStep = step;
Expand Down Expand Up @@ -177,4 +184,26 @@ public String getOutputPath() {
return "";
}

public boolean hasPermissions(UserAccount user) {
if (isPublicAccessible()) {
return true;
}
if (user == null) {
return false;
}
if (user.isRootUser()) {
return true;
}
for (AccessWhitelist filter : accessWhitelists) {
if (filter.isAuthorized(user)) {
return true;
}
}
return false;
}

private boolean isPublicAccessible() {
return false;
}

}
Expand Up @@ -56,8 +56,8 @@ public OperationResult run(DataStore dataStore) {
return OperationResult.internalServerError();
}

List<Model> additions = ModelView.getModels(additionModelParams, dataStore);
List<Model> retractions = ModelView.getModels(retractionModelParams, dataStore);
List<Model> additions = ModelView.getExistingModels(additionModelParams, dataStore);
List<Model> retractions = ModelView.getExistingModels(retractionModelParams, dataStore);
Model target = ModelView.getModel(dataStore, targetModelParam);
AdditionsAndRetractions changes = new AdditionsAndRetractions(additions, retractions);
//TODO: set editor uri instead of ""
Expand Down
Expand Up @@ -11,6 +11,7 @@ public class OperationResult {
private static final OperationResult OK = new OperationResult(HttpServletResponse.SC_OK);
private static final OperationResult INTERNAL_SERVER_ERROR = new OperationResult(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
private static final OperationResult METHOD_NOT_ALLOWED = new OperationResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
private static final OperationResult NOT_AUTHORIZED = new OperationResult(HttpServletResponse.SC_UNAUTHORIZED);
private static final OperationResult NOT_FOUND = new OperationResult(HttpServletResponse.SC_NOT_FOUND);
private static final OperationResult BAD_REQUEST = new OperationResult(HttpServletResponse.SC_BAD_REQUEST);
private int responseCode;
Expand Down Expand Up @@ -51,6 +52,10 @@ public static OperationResult internalServerError() {
return INTERNAL_SERVER_ERROR;
}

public static OperationResult notAuthorized() {
return NOT_AUTHORIZED;
}

public static OperationResult ok() {
return OK;
}
Expand Down
Expand Up @@ -12,8 +12,10 @@ public class Parameter implements Removable {
private String description;
private Validators validators = new Validators();
private ParameterType type;
private String defaultValue;
private Boolean internal;

public String getName() {
public String getName() {
return name;
}

Expand All @@ -27,6 +29,16 @@ public ParameterType getType() {
return type;
}

@Property(uri = "https://vivoweb.org/ontology/vitro-dynamic-api#defaultValue", minOccurs = 0, maxOccurs = 1)
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}

@Property(uri = "https://vivoweb.org/ontology/vitro-dynamic-api#isInternal", minOccurs = 0, maxOccurs = 1)
public void setInternal(boolean internal) {
this.internal = internal;
}

@Property(uri = "https://vivoweb.org/ontology/vitro-dynamic-api#name", minOccurs = 1, maxOccurs = 1)
public void setName(String name) {
this.name = name;
Expand Down Expand Up @@ -56,6 +68,9 @@ public void dereference() {
}

public boolean isInternal() {
if (internal != null) {
return internal;
}
return type.isInternal();
}

Expand All @@ -75,7 +90,14 @@ public boolean isOptional() {
return false;
}

public boolean isJsonObject() {
return type.isJsonObject();
public boolean isJsonContainer() {
return type.isJsonContainer();
}

public String getDefaultValue() {
if (defaultValue != null) {
return defaultValue;
}
return type.getImplementationType().getDefaultValue();
}
}
Expand Up @@ -46,22 +46,6 @@ public boolean contains(String name) {
return params.containsKey(name);
}

/*
* // Substitute IRI parameters with their values in specific request public
* Map<String, List<String>> substituteIRIVariables(DataStore input) { return
* params.values().stream() .filter(value -> value.getType().isUri()).collect(
* Collectors.toMap(param -> param.getName(), param ->
* Arrays.asList(input.get(param.getName())))); }
*
* // Substitute parameters that represent RDF literals with their values in //
* specific request public Map<String, List<Literal>>
* substituteLiteralVariables(DataStore input) { return params.values().stream()
* .filter(value -> value.getType().isLiteral()) .collect(Collectors.toMap(param
* -> param.getName(), param ->
* Arrays.asList(ResourceFactory.createTypedLiteral(input.get(param.getName())[0
* ], param.getType().getRdfType().getRDFDataType())))); }
*/

@Override
public void dereference() {
for (String name : params.keySet()) {
Expand Down