@@ -167,49 +167,51 @@ public Model authorize(ContainerRequestContext request, Resource agent, Resource
167167 createOwnerAuthorization (authorizations , accessTo , agent );
168168 }
169169
170- // special case for PUT requests to non-existing document: allow if the agent has acl:Write acess to the *parent* URI
171- if (request .getMethod ().equals (HttpMethod .PUT ) && accessMode .equals (ACL .Write ))
170+ QuerySolutionMap thisQsm = new QuerySolutionMap ();
171+ thisQsm .add (SPIN .THIS_VAR_NAME , accessTo );
172+ ResultSetRewindable docTypesResult = loadResultSet (getApplication ().get ().getService (), getDocumentTypeQuery (), thisQsm );
173+ try
172174 {
173- // Use Jena's IRIx for RFC 3986-compliant resolution - java.net.URI.resolve("..") is non-compliant
174- // (RFC 3986 section 5.2.4 step 2D requires ".." to be removed, but java.net.URI leaves it literal)
175- IRIx parentURI = IRIx .create (accessTo .getURI ()).resolve (".." );
176- Resource parent = ResourceFactory .createResource (parentURI .toString ());
177- log .debug ("Requested document <{}> not found, falling back to parent URI <{}>" , parent , parentURI );
178-
179- QuerySolutionMap parentQsm = new QuerySolutionMap ();
180- parentQsm .add (SPIN .THIS_VAR_NAME , parent );
181- ResultSetRewindable docTypesResult = loadResultSet (getApplication ().get ().getService (), getDocumentTypeQuery (), parentQsm );
182- try
175+ // special case for PUT requests: if the document does not exist, check acl:Write access on the *parent* URI instead
176+ if (!docTypesResult .hasNext () && request .getMethod ().equals (HttpMethod .PUT ) && accessMode .equals (ACL .Write ))
183177 {
184- Set <Resource > parentTypes = new HashSet <>();
185- docTypesResult .forEachRemaining (qs -> parentTypes .add (qs .getResource ("Type" )));
178+ // Use Jena's IRIx for RFC 3986-compliant resolution - java.net.URI.resolve("..") is non-compliant
179+ // (RFC 3986 section 5.2.4 step 2D requires ".." to be removed, but java.net.URI leaves it literal)
180+ IRIx parentURI = IRIx .create (accessTo .getURI ()).resolve (".." );
181+ Resource parent = ResourceFactory .createResource (parentURI .toString ());
182+ log .debug ("Requested document <{}> not found, falling back to parent URI <{}>" , parent , parentURI );
186183
187- // only root and containers allow child documents. This needs to be checked before checking ownership
188- if (Collections .disjoint (parentTypes , Set .of (Default .Root , DH .Container ))) return null ;
184+ QuerySolutionMap parentQsm = new QuerySolutionMap ();
185+ parentQsm .add (SPIN .THIS_VAR_NAME , parent );
186+ ResultSetRewindable parentTypesResult = loadResultSet (getApplication ().get ().getService (), getDocumentTypeQuery (), parentQsm );
187+ try
188+ {
189+ Set <Resource > parentTypes = new HashSet <>();
190+ parentTypesResult .forEachRemaining (qs -> parentTypes .add (qs .getResource ("Type" )));
191+
192+ // only root and containers allow child documents. This needs to be checked before checking ownership
193+ if (Collections .disjoint (parentTypes , Set .of (Default .Root , DH .Container ))) return null ;
189194
190- // the agent is the owner of the requested document - automatically grant acl:Read/acl:Append/acl:Write access
191- if (agent != null && isOwner (parent , agent ))
195+ // the agent is the owner of the requested document - automatically grant acl:Read/acl:Append/acl:Write access
196+ if (agent != null && isOwner (parent , agent ))
197+ {
198+ log .debug ("Agent <{}> is the owner of <{}>, granting acl:Read/acl:Append/acl:Write access" , agent , parent );
199+ createOwnerAuthorization (authorizations , parent , agent );
200+ }
201+
202+ accessTo = parent ; // redirect ACL query to parent URI since the document does not exist yet
203+ }
204+ finally
192205 {
193- log .debug ("Agent <{}> is the owner of <{}>, granting acl:Read/acl:Append/acl:Write access" , agent , parent );
194- createOwnerAuthorization (authorizations , parent , agent );
206+ parentTypesResult .close ();
195207 }
196208 }
197- finally
198- {
199- docTypesResult .close ();
200- }
201- }
202-
203- QuerySolutionMap thisQsm = new QuerySolutionMap ();
204- thisQsm .add (SPIN .THIS_VAR_NAME , accessTo );
205- ResultSetRewindable docTypesResult = loadResultSet (getApplication ().get ().getService (), getDocumentTypeQuery (), thisQsm );
206- try
207- {
209+
208210 ParameterizedSparqlString pss = getApplication ().get ().canAs (EndUserApplication .class ) ? getACLQuery () : getOwnerACLQuery ();
209211 if (docTypesResult .hasNext ())
210212 {
211213 Query query = new SetResultSetValues ().apply (pss .asQuery (), docTypesResult );
212- pss = new ParameterizedSparqlString (query .toString ()); // make sure VALUES are now part of the query string
214+ pss = new ParameterizedSparqlString (query .toString ()); // make sure type VALUES are now part of the query string
213215 assert pss .toString ().contains ("VALUES" );
214216 }
215217
0 commit comments