Gitlab Community Edition Instance

Commit 73e50818 authored by mhellka's avatar mhellka
Browse files

API: Vault scroll API cleanup and new strict mode.

Make clear that deleted archive IDs are part of a vault scroll listing per default.
Added a `strict` mode to actually check load-ability by the current user.
parent 8e43d6f4
......@@ -113,20 +113,23 @@ endpoints:
help: |
List IDs of archives stored in this vault.
Up to `limit` IDs are returned per request.
IDs are ordered in a stable but otherwise implemention specifc way (usually lexographical).
If the `scroll` parameter is a non-empty string, then only IDs ordered after the given string are returned.
This can be used to scroll through all IDs of a vault in an efficient manner.
This API requires the `list` vault permission or the vault to be public,
but does NOT check archive-level permissions. As a consequence, the returned list
may include IDs the current user session is not allowed to `load`.
This API is also NOT transaction-bound and may return outdated results.
Archives created or removed recently may or may not be included in the listing,
depending on internal caching behavior. In particular, removed archives may be
listed up until they are fully garbage collected. To check if an archive really
exists and is read-able, issue a HEAD request to the <<getArchiveInfo>> endpoint.
Up to `limit` IDs are returned per request. IDs are ordered in a stable but
otherwise implemention specifc way (usually lexographical). If the `scroll`
parameter is a non-empty string, then only IDs ordered after the given string
are returned. This can be used to scroll through all IDs of a vault in an
efficient manner.
By default, this API will return all IDs that were ever created in this vault,
including IDs of archives that were removed or are not load-able by the current
user. This mode requires `list` vault permission or the vault to be public.
In `strict` mode, archive manifests are actually loaded from storage and only IDs
of archives that are load-able by the current user are returned. This mode is less
efficient, but does not require `scroll` permissions on the vault. Use with caution.
This API is NOT transaction-bound or isolated and may reflect changes recently
committed by other transactions.
method: GET
path: /{vault}?scroll
params:
......@@ -142,6 +145,11 @@ endpoints:
default: 25
help: |
Limit the number of results. Values are automatically capped to an allowed maximum.
strict:
type: boolean
default: false
help: |
If true, only IDs for archives that are actually load-able by the current user are returned.
results:
- code: 200
type: <<ScrollResults>>
......
......@@ -44,14 +44,13 @@ public class VaultEndpoint implements RestBlueprint {
private ScrollResult handleScroll(RestContext ctx) throws VaultNotFound {
final QueryHelper qh = new QueryHelper(ctx);
qh.setDefault("limit", "25");
qh.setDefault("_strict", "false");
qh.setDefault("strict", "false");
final String scanOffset = qh.get(PARAM_SCROLL); // may be empty
final int limit = Utils.gate(0, qh.getInt("limit", 0, Integer.MAX_VALUE), SCROLL_LIMIT);
final boolean strict = qh.getBoolean("_strict");
final boolean strict = qh.getBoolean("strict");
qh.ensureNoUnusedParameters();
final CDStarVault vault = SessionHelper.getCDStarSession(ctx, true).getVault(ctx.getPathParam("vault"));
final List<String> result = new ArrayList<>(limit);
......
......@@ -5,6 +5,8 @@ import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.Response.Status;
import org.junit.Test;
......@@ -41,4 +43,26 @@ public class ScrollVaultTest extends BaseRestTest {
assertEquals(allIDs.subList(5, 10), getJsonStrings("results"));
}
@Test
public void testScrollStrict() {
final List<String> allIDs = makeArchives(3);
allIDs.sort(null);
String deleted = allIDs.get(0);
target("/v3/test/", deleted).request().delete();
String noAccess = allIDs.get(1);
target("/v3/test/", noAccess).request().post(Entity.form(new Form("acl:$owner", "")));
// In default mode, these are still visible
target("/v3/test").queryParam("scroll", "").request().get();
assertEquals(allIDs, getJsonStrings("results"));
// In strict mode, these should disappear
allIDs.remove(deleted);
allIDs.remove(noAccess);
target("/v3/test").queryParam("scroll", "").queryParam("strict", "true").request().get();
assertEquals(allIDs, getJsonStrings("results"));
}
}
......@@ -131,7 +131,7 @@ class VaultImpl implements CDStarVault {
@Override
public Iterable<String> getArchiveIterable(String scanOffset, boolean strict) {
if (!isPublic())
if (!(isPublic() || strict))
checkPermission(VaultPermission.LIST);
final Iterable<String> idIterator = pool.getObjectIDs(scanOffset);
if (!strict)
......@@ -141,6 +141,8 @@ class VaultImpl implements CDStarVault {
return () -> StreamSupport.stream(idIterator.spliterator(), false).filter(id -> {
try {
final StorageObject obj = poolSess.getPool().loadObjectDirect(id, null);
if(obj.isRemoved())
return false;
final AclChecker access = new AclChecker(getName(), id, subject,
PropertyHelper.getOwner(obj), PropertyHelper.getAclMap(obj));
return access.isPermitted(ArchivePermission.LOAD)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment