Skip to content

Commit 61b2bdb

Browse files
authored
Fix ACL modes (#242)
* Streamlined `AuthorizationFilter` * Attempt to fix
1 parent 416c942 commit 61b2bdb

2 files changed

Lines changed: 28 additions & 20 deletions

File tree

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

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,14 @@ public void filter(ContainerRequestContext request) throws IOException
136136
if (request.getSecurityContext().getUserPrincipal() instanceof Agent) agent = ((Agent)(request.getSecurityContext().getUserPrincipal()));
137137
else agent = null; // public access
138138

139-
Resource authorization = authorize(request, agent, accessMode);
140-
if (authorization == null)
139+
Model authorizations = authorize(request, agent, accessMode);
140+
if (authorizations == null)
141141
{
142142
if (log.isTraceEnabled()) log.trace("Access not authorized for request URI: {} and access mode: {}", request.getUriInfo().getAbsolutePath(), accessMode);
143143
throw new AuthorizationException("Access not authorized for request URI", request.getUriInfo().getAbsolutePath(), accessMode);
144144
}
145145
else // authorization successful
146-
request.setProperty(AuthorizationContext.class.getCanonicalName(), new AuthorizationContext(authorization.getModel()));
146+
request.setProperty(AuthorizationContext.class.getCanonicalName(), new AuthorizationContext(authorizations));
147147
}
148148

149149
/**
@@ -152,21 +152,22 @@ public void filter(ContainerRequestContext request) throws IOException
152152
* @param request current request
153153
* @param agent agent resource or null
154154
* @param accessMode ACL access mode
155-
* @return authorization resource or null
155+
* @return authorizations model or null if access denied
156156
*/
157-
public Resource authorize(ContainerRequestContext request, Resource agent, Resource accessMode)
157+
public Model authorize(ContainerRequestContext request, Resource agent, Resource accessMode)
158158
{
159159
Resource accessTo = ResourceFactory.createResource(request.getUriInfo().getAbsolutePath().toString());
160-
161-
// special case where the agent is the owner of the requested document - automatically grant acl:Read/acl:Append/acl:Write access
160+
QuerySolutionMap thisQsm = new QuerySolutionMap();
161+
thisQsm.add(SPIN.THIS_VAR_NAME, accessTo);
162+
Model authorizations = ModelFactory.createDefaultModel();
163+
164+
// the agent is the owner of the requested document - automatically grant acl:Read/acl:Append/acl:Write access.
165+
// Note: the document does not even need to have a type at this point.
162166
if (agent != null && isOwner(accessTo, agent))
163167
{
164168
log.debug("Agent <{}> is the owner of <{}>, granting acl:Read/acl:Append/acl:Write access", agent, accessTo);
165-
return createOwnerAuthorization(accessTo, agent);
169+
createOwnerAuthorization(authorizations, accessTo, agent);
166170
}
167-
168-
QuerySolutionMap thisQsm = new QuerySolutionMap();
169-
thisQsm.add(SPIN.THIS_VAR_NAME, accessTo);
170171

171172
ResultSetRewindable docTypesResult = loadResultSet(getApplication().getService(), getDocumentTypeQuery(), thisQsm);
172173
try
@@ -192,24 +193,30 @@ public Resource authorize(ContainerRequestContext request, Resource agent, Resou
192193
// only root and containers allow child documents. This needs to be checked before checking ownership
193194
if (Collections.disjoint(parentTypes, Set.of(Default.Root, DH.Container))) return null;
194195
docTypesResult.reset(); // rewind result set to the beginning - it's used again later on
195-
196-
// special case where the agent is the owner of the requested document - automatically grant acl:Read/acl:Append/acl:Write access
196+
197+
// the agent is the owner of the requested document - automatically grant acl:Read/acl:Append/acl:Write access
197198
if (agent != null && isOwner(accessTo, agent))
198199
{
199200
log.debug("Agent <{}> is the owner of <{}>, granting acl:Read/acl:Append/acl:Write access", agent, accessTo);
200-
return createOwnerAuthorization(accessTo, agent);
201+
createOwnerAuthorization(authorizations, accessTo, agent);
201202
}
202203
}
204+
// access to non-existing documents is denied if the request method is not PUT *and* the agent has no Write access
203205
else return null;
204206
}
205-
207+
206208
ParameterizedSparqlString pss = getApplication().canAs(EndUserApplication.class) ? getACLQuery() : getOwnerACLQuery();
207209
Query query = new SetResultSetValues().apply(pss.asQuery(), docTypesResult);
208210
pss = new ParameterizedSparqlString(query.toString()); // make sure VALUES are now part of the query string
209211
assert pss.toString().contains("VALUES");
210212

211-
Model authModel = loadModel(getAdminService(), pss, new AuthorizationParams(getApplication().getBase(), accessTo, agent).get());
212-
return getAuthorizationByMode(authModel, accessMode);
213+
// note we're not setting the $mode value on the ACL queries as we want to provide the AuthorizationContext with all of the agent's authorizations
214+
authorizations.add(loadModel(getAdminService(), pss, new AuthorizationParams(getApplication().getBase(), accessTo, agent).get()));
215+
216+
// access denied if the agent has no authorization to the requested document with the requested ACL mode
217+
if (getAuthorizationByMode(authorizations, accessMode) == null) return null;
218+
219+
return authorizations;
213220
}
214221
finally
215222
{
@@ -326,17 +333,17 @@ protected ResultSetRewindable loadResultSet(com.atomgraph.linkeddatahub.model.Se
326333

327334
/**
328335
* Creates a special <code>acl:Authorization</code> resource for an owner.
336+
* @param model RDF model
329337
* @param accessTo requested URI
330338
* @param agent authenticated agent
331339
* @return authorization resource
332340
*/
333-
public Resource createOwnerAuthorization(Resource accessTo, Resource agent)
341+
public Resource createOwnerAuthorization(Model model, Resource accessTo, Resource agent)
334342
{
335343
if (accessTo == null) throw new IllegalArgumentException("Document resource cannot be null");
336344
if (agent == null) throw new IllegalArgumentException("Agent resource cannot be null");
337345

338-
return ModelFactory.createDefaultModel().
339-
createResource().
346+
return model.createResource().
340347
addProperty(RDF.type, ACL.Authorization).
341348
addProperty(RDF.type, LACL.OwnerAuthorization).
342349
addProperty(ACL.accessTo, accessTo).

src/main/java/com/atomgraph/linkeddatahub/server/util/AuthorizationParams.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class AuthorizationParams implements Supplier<QuerySolutionMap>
3636

3737
/**
3838
* Constructs authorization query solution supplier.
39+
* <em>Does not set <samp>$mode</samp> value intentionally as we want to provide the {@link com.atomgraph.linkeddatahub.server.security.AuthorizationContext} with all of the agent's authorizations.</em>
3940
*
4041
* @param base application's base URI
4142
* @param absolutePath request URL without query string

0 commit comments

Comments
 (0)