Skip to content

Commit 6acc630

Browse files
committed
Extracted common utility functions from AuthorizationFilter and the Access endpoint
1 parent a87ebae commit 6acc630

File tree

8 files changed

+181
-148
lines changed

8 files changed

+181
-148
lines changed

platform/datasets/admin.trig

-19
Original file line numberDiff line numberDiff line change
@@ -794,25 +794,6 @@ WHERE
794794

795795
}
796796

797-
# creator access
798-
799-
<acl/authorizations/creator/>
800-
{
801-
802-
<acl/authorizations/creator/> a dh:Item ;
803-
sioc:has_container <acl/authorizations/> ;
804-
dct:title "Creator access" ;
805-
foaf:primaryTopic <acl/authorizations/creator/#this> .
806-
807-
<acl/authorizations/creator/#this> a lacl:CreatorAuthorization ;
808-
rdfs:label "Creator access" ;
809-
rdfs:comment "Creators have full control of their created resources" ;
810-
lacl:accessProperty foaf:maker ;
811-
acl:accessToClass dh:Item, dh:Container, def:Root ;
812-
acl:agentClass acl:AuthenticatedAgent .
813-
814-
}
815-
816797
# GROUPS
817798

818799
# owners

src/main/java/com/atomgraph/linkeddatahub/resource/acl/Access.java

+4-57
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@
2626
import com.atomgraph.linkeddatahub.model.Service;
2727
import com.atomgraph.linkeddatahub.model.auth.Agent;
2828
import com.atomgraph.linkeddatahub.server.security.AgentContext;
29-
import com.atomgraph.linkeddatahub.vocabulary.ACL;
30-
import com.atomgraph.linkeddatahub.vocabulary.SIOC;
31-
import com.atomgraph.server.vocabulary.LDT;
29+
import com.atomgraph.linkeddatahub.server.util.AuthorizationParams;
30+
import com.atomgraph.linkeddatahub.server.util.SetResultSetValues;
3231
import com.atomgraph.spinrdf.vocabulary.SPIN;
3332
import jakarta.inject.Inject;
3433
import jakarta.ws.rs.BadRequestException;
@@ -41,7 +40,6 @@
4140
import jakarta.ws.rs.core.UriInfo;
4241
import java.net.URI;
4342
import java.net.URISyntaxException;
44-
import java.util.ArrayList;
4543
import java.util.List;
4644
import java.util.Optional;
4745
import org.apache.jena.ontology.Ontology;
@@ -52,9 +50,6 @@
5250
import org.apache.jena.query.ResultSetRewindable;
5351
import org.apache.jena.rdf.model.Resource;
5452
import org.apache.jena.rdf.model.ResourceFactory;
55-
import org.apache.jena.sparql.core.Var;
56-
import org.apache.jena.sparql.engine.binding.Binding;
57-
import org.apache.jena.vocabulary.RDFS;
5853
import org.slf4j.Logger;
5954
import org.slf4j.LoggerFactory;
6055

@@ -124,8 +119,8 @@ public Response get(@QueryParam(QUERY) Query query,
124119
ResultSet docTypes = loadResultSet(getEndUserService(), getDocumentTypeQuery(), docTypeQsm);
125120
try
126121
{
127-
authPss.setParams(getAuthorizationParams(accessTo, agent));
128-
query = setResultSetValues(authPss.asQuery(), docTypes);
122+
authPss.setParams(new AuthorizationParams(getApplication().getBase(), accessTo, agent).get());
123+
query = new SetResultSetValues().apply(authPss.asQuery(), docTypes);
129124

130125
return super.get(query, defaultGraphUris, namedGraphUris);
131126
}
@@ -140,33 +135,6 @@ public Response get(@QueryParam(QUERY) Query query,
140135
}
141136
}
142137

143-
/**
144-
* Builds solution map for the authorization query.
145-
*
146-
* @param absolutePath request URL without query string
147-
* @param agent agent resource or null
148-
* @return solution map
149-
*/
150-
public QuerySolutionMap getAuthorizationParams(Resource absolutePath, Resource agent)
151-
{
152-
QuerySolutionMap qsm = new QuerySolutionMap();
153-
qsm.add(SPIN.THIS_VAR_NAME, absolutePath);
154-
qsm.add(LDT.base.getLocalName(), getApplication().getBase());
155-
156-
if (agent != null)
157-
{
158-
qsm.add("AuthenticatedAgentClass", ACL.AuthenticatedAgent); // enable AuthenticatedAgent UNION branch
159-
qsm.add("agent", agent);
160-
}
161-
else
162-
{
163-
qsm.add("AuthenticatedAgentClass", RDFS.Resource); // disable AuthenticatedAgent UNION branch
164-
qsm.add("agent", RDFS.Resource); // disables UNION branch with $agent
165-
}
166-
167-
return qsm;
168-
}
169-
170138
/**
171139
* Loads SPARQL result set from a service.
172140
*
@@ -199,27 +167,6 @@ protected ResultSet loadResultSet(com.atomgraph.linkeddatahub.model.Service serv
199167
}
200168
}
201169

202-
/**
203-
* Converts a SPARQL result set into a <code>VALUES</code> block.
204-
*
205-
* @param query SPARQL query
206-
* @param resultSet result set
207-
* @return query with appended values
208-
*/
209-
public Query setResultSetValues(Query query, ResultSet resultSet)
210-
{
211-
if (query == null) throw new IllegalArgumentException("Query cannot be null");
212-
if (resultSet == null) throw new IllegalArgumentException("ResultSet cannot be null");
213-
214-
List<Var> vars = resultSet.getResultVars().stream().map(Var::alloc).toList();
215-
List<Binding> values = new ArrayList<>();
216-
while (resultSet.hasNext())
217-
values.add(resultSet.nextBinding());
218-
219-
query.setValuesDataBlock(vars, values);
220-
return query;
221-
}
222-
223170
/**
224171
* Returns the SPARQL service for end-user data.
225172
*

src/main/java/com/atomgraph/linkeddatahub/resource/acl/AccessRequest.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.apache.jena.rdf.model.StmtIterator;
5959
import org.apache.jena.vocabulary.DCTerms;
6060
import org.apache.jena.vocabulary.RDF;
61+
import org.apache.jena.vocabulary.RDFS;
6162
import org.slf4j.Logger;
6263
import org.slf4j.LoggerFactory;
6364

@@ -119,6 +120,9 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false")
119120
Resource agent = authorization.getPropertyResourceValue(ACL.agent);
120121
if (!agent.equals(getAgentContext().get().getAgent())) throw new IllegalStateException("Agent requesting access must be authenticated");
121122

123+
String humanReadableName = getAgentsHumanReadableName(getAgentContext().get().getAgent());
124+
String accessRequestLabel = humanReadableName != null ? "Access request by " + humanReadableName : null; // TO-DO: localize the string
125+
122126
Resource agentGroup = authorization.getPropertyResourceValue(ACL.agentGroup);
123127
Resource accessTo = authorization.getPropertyResourceValue(ACL.accessTo);
124128
Resource accessToClass = authorization.getPropertyResourceValue(ACL.accessToClass);
@@ -127,7 +131,8 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false")
127131
addProperty(RDF.type, LACL.AuthorizationRequest).
128132
addProperty(LACL.requestAgent, agent).
129133
addLiteral(DCTerms.created, GregorianCalendar.getInstance());
130-
134+
if (accessRequestLabel != null) accessRequest.addLiteral(RDFS.label, accessRequestLabel);
135+
131136
// add all requested access modes
132137
StmtIterator modeIt = authorization.listProperties(ACL.mode);
133138
try
@@ -144,11 +149,12 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false")
144149
if (accessToClass != null) accessRequest.addProperty(LACL.requestAccessToClass, accessToClass);
145150

146151
// attach document to parent explicitly because this class extends GraphStoreImpl and not Graph (which would handle it implicitly)
147-
requestModel.createResource(graphUri.toString()).
152+
Resource doc = requestModel.createResource(graphUri.toString()).
148153
addProperty(RDF.type, DH.Item).
149154
addProperty(SIOC.HAS_CONTAINER, requestModel.createResource(getAuthRequestContainerUriBuilder().build().toString())).
150155
addProperty(FOAF.primaryTopic, accessRequest);
151-
156+
if (accessRequestLabel != null) doc.addLiteral(DCTerms.title, accessRequestLabel);
157+
152158
// try
153159
// {
154160
// sendEmail(owner, accessRequest);
@@ -175,6 +181,15 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false")
175181
}
176182
}
177183

184+
public String getAgentsHumanReadableName(Agent agent)
185+
{
186+
if (agent.hasProperty(FOAF.givenName) && agent.hasProperty(FOAF.familyName))
187+
return agent.getProperty(FOAF.givenName).getString() + " " + agent.getProperty(FOAF.familyName).getString();
188+
189+
if (agent.hasProperty(FOAF.name)) return agent.getProperty(FOAF.name).getString();
190+
191+
return null;
192+
}
178193

179194
/**
180195
* Returns the URI builder for authorization requests.

src/main/java/com/atomgraph/linkeddatahub/server/filter/request/AuthorizationFilter.java

+6-56
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
import com.atomgraph.linkeddatahub.model.auth.Agent;
2424
import com.atomgraph.linkeddatahub.model.Service;
2525
import com.atomgraph.linkeddatahub.server.security.AuthorizationContext;
26+
import com.atomgraph.linkeddatahub.server.util.AuthorizationParams;
27+
import com.atomgraph.linkeddatahub.server.util.SetResultSetValues;
2628
import com.atomgraph.linkeddatahub.vocabulary.ACL;
2729
import com.atomgraph.linkeddatahub.vocabulary.DH;
2830
import com.atomgraph.linkeddatahub.vocabulary.Default;
29-
import com.atomgraph.server.vocabulary.LDT;
31+
import com.atomgraph.linkeddatahub.vocabulary.LACL;
3032
import com.atomgraph.spinrdf.vocabulary.SPIN;
3133
import java.io.IOException;
3234
import java.util.Collections;
@@ -43,9 +45,7 @@
4345
import jakarta.ws.rs.container.PreMatching;
4446
import jakarta.ws.rs.core.Response;
4547
import java.net.URI;
46-
import java.util.ArrayList;
4748
import java.util.HashSet;
48-
import java.util.List;
4949
import java.util.Set;
5050
import org.apache.jena.query.ParameterizedSparqlString;
5151
import org.apache.jena.query.Query;
@@ -58,10 +58,7 @@
5858
import org.apache.jena.rdf.model.ResIterator;
5959
import org.apache.jena.rdf.model.Resource;
6060
import org.apache.jena.rdf.model.ResourceFactory;
61-
import org.apache.jena.sparql.core.Var;
62-
import org.apache.jena.sparql.engine.binding.Binding;
6361
import org.apache.jena.vocabulary.RDF;
64-
import org.apache.jena.vocabulary.RDFS;
6562
import org.slf4j.Logger;
6663
import org.slf4j.LoggerFactory;
6764

@@ -156,33 +153,6 @@ public void filter(ContainerRequestContext request) throws IOException
156153
request.setProperty(AuthorizationContext.class.getCanonicalName(), new AuthorizationContext(authorization.getModel()));
157154
}
158155

159-
/**
160-
* Builds solution map for the authorization query.
161-
*
162-
* @param absolutePath request URL without query string
163-
* @param agent agent resource or null
164-
* @return solution map
165-
*/
166-
public QuerySolutionMap getAuthorizationParams(Resource absolutePath, Resource agent)
167-
{
168-
QuerySolutionMap qsm = new QuerySolutionMap();
169-
qsm.add(SPIN.THIS_VAR_NAME, absolutePath);
170-
qsm.add(LDT.base.getLocalName(), getApplication().getBase());
171-
172-
if (agent != null)
173-
{
174-
qsm.add("AuthenticatedAgentClass", ACL.AuthenticatedAgent); // enable AuthenticatedAgent UNION branch
175-
qsm.add("agent", agent);
176-
}
177-
else
178-
{
179-
qsm.add("AuthenticatedAgentClass", RDFS.Resource); // disable AuthenticatedAgent UNION branch
180-
qsm.add("agent", RDFS.Resource); // disables UNION branch with $agent
181-
}
182-
183-
return qsm;
184-
}
185-
186156
/**
187157
* Returns authorization for the current request.
188158
*
@@ -241,11 +211,11 @@ public Resource authorize(ContainerRequestContext request, Resource agent, Resou
241211
}
242212

243213
ParameterizedSparqlString pss = getApplication().canAs(EndUserApplication.class) ? getACLQuery() : getOwnerACLQuery();
244-
Query query = setResultSetValues(pss.asQuery(), docTypes);
214+
Query query = new SetResultSetValues().apply(pss.asQuery(), docTypes);
245215
pss = new ParameterizedSparqlString(query.toString()); // make sure VALUES are now part of the query string
246216
assert pss.toString().contains("VALUES");
247217

248-
Model authModel = loadModel(getAdminService(), pss, getAuthorizationParams(accessTo, agent));
218+
Model authModel = loadModel(getAdminService(), pss, new AuthorizationParams(getApplication().getBase(), accessTo, agent).get());
249219
return authorize(authModel, accessMode);
250220
}
251221
finally
@@ -360,27 +330,6 @@ protected ResultSetRewindable loadResultSet(com.atomgraph.linkeddatahub.model.Se
360330
}
361331
}
362332

363-
/**
364-
* Converts a SPARQL result set into a <code>VALUES</code> block.
365-
*
366-
* @param query SPARQL query
367-
* @param resultSet result set
368-
* @return query with appended values
369-
*/
370-
public Query setResultSetValues(Query query, ResultSet resultSet)
371-
{
372-
if (query == null) throw new IllegalArgumentException("Query cannot be null");
373-
if (resultSet == null) throw new IllegalArgumentException("ResultSet cannot be null");
374-
375-
List<Var> vars = resultSet.getResultVars().stream().map(Var::alloc).toList();
376-
List<Binding> values = new ArrayList<>();
377-
while (resultSet.hasNext())
378-
values.add(resultSet.nextBinding());
379-
380-
query.setValuesDataBlock(vars, values);
381-
return query;
382-
}
383-
384333
/**
385334
* Creates a special <code>acl:Authorization</code> resource for an owner.
386335
* @param accessTo requested URI
@@ -395,6 +344,7 @@ public Resource createOwnerAuthorization(Resource accessTo, Resource agent)
395344
return ModelFactory.createDefaultModel().
396345
createResource().
397346
addProperty(RDF.type, ACL.Authorization).
347+
addProperty(RDF.type, LACL.CreatorAuthorization).
398348
addProperty(ACL.accessTo, accessTo).
399349
addProperty(ACL.agent, agent).
400350
addProperty(ACL.mode, ACL.Read).

0 commit comments

Comments
 (0)