Repository: incubator-blur Updated Branches: refs/heads/master 8b7eb8f09 -> e5a828dce
Fixing some issues with the read mask. Project: http://git-wip-us.apache.org/repos/asf/incubator-blur/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-blur/commit/e5a828dc Tree: http://git-wip-us.apache.org/repos/asf/incubator-blur/tree/e5a828dc Diff: http://git-wip-us.apache.org/repos/asf/incubator-blur/diff/e5a828dc Branch: refs/heads/master Commit: e5a828dce2c86478f2a91f358c638110bed691df Parents: 8b7eb8f Author: Aaron McCurry <amccu...@gmail.com> Authored: Mon Nov 16 15:58:28 2015 -0500 Committer: Aaron McCurry <amccu...@gmail.com> Committed: Mon Nov 16 15:58:28 2015 -0500 ---------------------------------------------------------------------- .../blur/thrift/BlurClusterTestSecurity.java | 50 ++++++++++++++++++++ .../security/index/SecureAtomicReader.java | 47 ++++++++++++++++++ .../index/SecureAtomicReaderTestBase.java | 32 ++++++++----- .../apache/blur/analysis/BaseFieldManager.java | 9 +++- .../type/ReadMaskFieldTypeDefinition.java | 7 ++- 5 files changed, 127 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/e5a828dc/blur-core/src/test/java/org/apache/blur/thrift/BlurClusterTestSecurity.java ---------------------------------------------------------------------- diff --git a/blur-core/src/test/java/org/apache/blur/thrift/BlurClusterTestSecurity.java b/blur-core/src/test/java/org/apache/blur/thrift/BlurClusterTestSecurity.java index f3e01bf..9131f72 100644 --- a/blur-core/src/test/java/org/apache/blur/thrift/BlurClusterTestSecurity.java +++ b/blur-core/src/test/java/org/apache/blur/thrift/BlurClusterTestSecurity.java @@ -104,6 +104,56 @@ public class BlurClusterTestSecurity extends BlurClusterTestBase { } @Test + public void testSecurityMaskReadRowQuery() throws BlurException, TException, IOException { + String tableName = "testSecurity2"; + createTable(tableName); + Iface client = getClient(); + { + ColumnDefinition columnDefinition = new ColumnDefinition(TEST, "read_mask", null, false, "read-mask", null, false); + columnDefinition.setMultiValueField(false); + client.addColumnDefinition(tableName, columnDefinition); + } + List<RowMutation> batch = new ArrayList<RowMutation>(); + for (int i = 0; i < 50; i++) { + List<RecordMutation> recordMutations = getRecordMutations("a"); + RowMutation mutation1 = new RowMutation(tableName, getRowId(), RowMutationType.REPLACE_ROW, recordMutations); + addReadMaskColumn(mutation1); + batch.add(mutation1); + } + client.mutateBatch(batch); + + Map<String, String> attributes = new HashMap<String, String>(); + attributes.put(BlurConstants.ACL_READ, "a"); + User user = new User("testuser", attributes); + UserContext.setUser(user); + + BlurQuery blurQuery = new BlurQuery(); + blurQuery.setSelector(new Selector()); + Query query = new Query(); + query.setRowQuery(true); + query.setQuery("*"); + blurQuery.setQuery(query); + blurQuery.setFetch(100); + + BlurResults results = client.query(tableName, blurQuery); + for (BlurResult result : results.getResults()) { + System.out.println(result.getFetchResult().getRowResult().getRow()); + } + List<String> terms = client.terms(tableName, TEST, "test2", "", (short) 1000); + assertTrue(terms.isEmpty()); + UserContext.reset(); + } + + private void addReadMaskColumn(RowMutation mutation) { + List<RecordMutation> recordMutations = mutation.getRecordMutations(); + for (RecordMutation recordMutation : recordMutations) { + Record record = recordMutation.getRecord(); + record.addToColumns(new Column("test2", UUID.randomUUID().toString())); + record.addToColumns(new Column("read_mask", "test2|MASK")); + } + } + + @Test public void testSecurityReadOnlyRowQuery() throws BlurException, TException, IOException { String tableName = "testSecurity1"; createTable(tableName); http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/e5a828dc/blur-document-security/src/main/java/org/apache/blur/lucene/security/index/SecureAtomicReader.java ---------------------------------------------------------------------- diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/index/SecureAtomicReader.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/index/SecureAtomicReader.java index c9a2bfb..4e31a65 100644 --- a/blur-document-security/src/main/java/org/apache/blur/lucene/security/index/SecureAtomicReader.java +++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/index/SecureAtomicReader.java @@ -513,6 +513,36 @@ public class SecureAtomicReader extends FilterAtomicReader { } @Override + public SeekStatus seekCeil(BytesRef text, boolean useCache) throws IOException { + SeekStatus seekStatus = in.seekCeil(text, useCache); + if (seekStatus == SeekStatus.END) { + return SeekStatus.END; + } + BytesRef term = in.term(); + BytesRef bytesRef = new BytesRef(); + bytesRef.copyBytes(term); + // If not in mask then return. + if (!_maskTermsEnum.seekExact(bytesRef, true)) { + return seekStatus; + } else { + if (checkDocs()) { + return seekStatus; + } + // check if any docs for given term are not present in mask terms enums + if (next() == null) { + return SeekStatus.END; + } else { + return SeekStatus.NOT_FOUND; + } + } + } + + @Override + public void seekExact(long ord) throws IOException { + throw new IOException("Not supported"); + } + + @Override public BytesRef next() throws IOException { while (true) { BytesRef ref = in.next(); @@ -553,6 +583,23 @@ public class SecureAtomicReader extends FilterAtomicReader { } @Override + public SeekStatus seekCeil(BytesRef text, boolean useCache) throws IOException { + SeekStatus seekStatus = in.seekCeil(text, useCache); + if (seekStatus == SeekStatus.END) { + return SeekStatus.END; + } + BytesRef term = in.term(); + if (hasAccess(term)) { + return seekStatus; + } + if (next() == null) { + return SeekStatus.END; + } else { + return SeekStatus.NOT_FOUND; + } + } + + @Override public BytesRef next() throws IOException { BytesRef t; while ((t = in.next()) != null) { http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/e5a828dc/blur-document-security/src/test/java/org/apache/blur/lucene/security/index/SecureAtomicReaderTestBase.java ---------------------------------------------------------------------- diff --git a/blur-document-security/src/test/java/org/apache/blur/lucene/security/index/SecureAtomicReaderTestBase.java b/blur-document-security/src/test/java/org/apache/blur/lucene/security/index/SecureAtomicReaderTestBase.java index 375d0e6..fced55d 100644 --- a/blur-document-security/src/test/java/org/apache/blur/lucene/security/index/SecureAtomicReaderTestBase.java +++ b/blur-document-security/src/test/java/org/apache/blur/lucene/security/index/SecureAtomicReaderTestBase.java @@ -50,6 +50,7 @@ import org.apache.lucene.index.SortedDocValues; import org.apache.lucene.index.SortedSetDocValues; import org.apache.lucene.index.Terms; import org.apache.lucene.index.TermsEnum; +import org.apache.lucene.index.TermsEnum.SeekStatus; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.Query; @@ -232,27 +233,32 @@ public abstract class SecureAtomicReaderTestBase { public void testTermWalk() throws IOException, ParseException { SecureAtomicReader secureReader = getSecureReader(); Fields fields = secureReader.fields(); - // for (String field : fields) { - // Terms terms = fields.terms(field); - // TermsEnum termsEnum = terms.iterator(null); - // BytesRef ref; - // while ((ref = termsEnum.next()) != null) { - // System.out.println(field + " " + ref.utf8ToString()); - // DocsEnum docsEnum = termsEnum.docs(null, null); - // int doc; - // while ((doc = docsEnum.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) { - // System.out.println(field + " " + ref.utf8ToString() + " " + doc); - // } - // } - // } assertEquals(0, getTermCount(fields, "termmask")); // read mask + assertEquals(0, getTermWithSeekCount(fields, "termmask")); // read mask assertEquals(0, getTermCount(fields, "shouldnotsee")); // discover + assertEquals(0, getTermWithSeekCount(fields, "shouldnotsee")); // discover assertEquals(1, getTermCount(fields, "test")); + assertEquals(1, getTermWithSeekCount(fields, "test")); secureReader.close(); } + private int getTermWithSeekCount(Fields fields, String field) throws IOException { + Terms terms = fields.terms(field); + TermsEnum termsEnum = terms.iterator(null); + SeekStatus seekStatus = termsEnum.seekCeil(new BytesRef("")); + if (seekStatus == SeekStatus.END) { + return 0; + } + System.out.println(termsEnum.term().utf8ToString()); + int count = 1; + while (termsEnum.next() != null) { + count++; + } + return count; + } + private int getTermCount(Fields fields, String field) throws IOException { Terms terms = fields.terms(field); TermsEnum termsEnum = terms.iterator(null); http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/e5a828dc/blur-query/src/main/java/org/apache/blur/analysis/BaseFieldManager.java ---------------------------------------------------------------------- diff --git a/blur-query/src/main/java/org/apache/blur/analysis/BaseFieldManager.java b/blur-query/src/main/java/org/apache/blur/analysis/BaseFieldManager.java index 250f33d..1085a13 100644 --- a/blur-query/src/main/java/org/apache/blur/analysis/BaseFieldManager.java +++ b/blur-query/src/main/java/org/apache/blur/analysis/BaseFieldManager.java @@ -166,7 +166,7 @@ public abstract class BaseFieldManager extends FieldManager { protected Analyzer getWrappedAnalyzer(String fieldName) { FieldTypeDefinition fieldTypeDefinition; try { - fieldTypeDefinition = getFieldTypeDefinition(fieldName); + fieldTypeDefinition = getFieldTypeDefinition(getFieldNameRealNameIfReadMask(fieldName)); } catch (IOException e) { throw new RuntimeException(e); } @@ -183,6 +183,13 @@ public abstract class BaseFieldManager extends FieldManager { }; } + protected String getFieldNameRealNameIfReadMask(String fieldName) { + if (fieldName.endsWith("$" + ReadMaskFieldTypeDefinition.INTERNAL_FIELDNAME)) { + return fieldName.substring(0, fieldName.lastIndexOf('$')); + } + return fieldName; + } + protected boolean isBuiltInField(String fieldName) { if (fieldName.equals(BlurConstants.ROW_ID)) { return true; http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/e5a828dc/blur-query/src/main/java/org/apache/blur/analysis/type/ReadMaskFieldTypeDefinition.java ---------------------------------------------------------------------- diff --git a/blur-query/src/main/java/org/apache/blur/analysis/type/ReadMaskFieldTypeDefinition.java b/blur-query/src/main/java/org/apache/blur/analysis/type/ReadMaskFieldTypeDefinition.java index 2e48e43..06e42ca 100644 --- a/blur-query/src/main/java/org/apache/blur/analysis/type/ReadMaskFieldTypeDefinition.java +++ b/blur-query/src/main/java/org/apache/blur/analysis/type/ReadMaskFieldTypeDefinition.java @@ -38,7 +38,7 @@ import org.apache.lucene.util.BytesRef; public class ReadMaskFieldTypeDefinition extends FieldTypeDefinition { - private static final String INTERNAL_FIELDNAME = "_readmask_"; + public static final String INTERNAL_FIELDNAME = "_readmask_"; private static final KeywordAnalyzer KEYWORD_ANALYZER = new KeywordAnalyzer(); private static final String READ_MASK = "read-mask"; private static final Collection<String> ALT_FIELD_NAMES; @@ -73,13 +73,13 @@ public class ReadMaskFieldTypeDefinition extends FieldTypeDefinition { String name = getName(family, column.getName()); List<Field> fields = new ArrayList<Field>(); fields.add(new StoredField(name, column.getValue())); - fields.add(new StringField(INTERNAL_FIELDNAME, column.getValue(), Store.YES)); + fields.add(new StringField(INTERNAL_FIELDNAME, family + "." + column.getValue(), Store.YES)); return fields; } @Override public Iterable<? extends Field> getFieldsForSubColumn(String family, Column column, String subName) { - return makeIterable(new StringField(INTERNAL_FIELDNAME, column.getValue(), Store.YES)); + return makeIterable(new StringField(INTERNAL_FIELDNAME, family + "." + column.getValue(), Store.YES)); } @Override @@ -92,7 +92,6 @@ public class ReadMaskFieldTypeDefinition extends FieldTypeDefinition { return Integer.MAX_VALUE; } - @SuppressWarnings("unchecked") @Override public Iterable<? extends IndexableField> executePostProcessing(Iterable<? extends IndexableField> fields) { return FilterAccessControlWriter.processFieldMasks(fields);