DB Fix bug#67471678. Include ACLs in the db.singleDocContentSql#110
DB Fix bug#67471678. Include ACLs in the db.singleDocContentSql#110srinicodebytes wants to merge 11 commits intomasterfrom
Conversation
|
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed, please reply here (e.g.
|
| aclPrincipalDelimiter = cfg.getValue("db.aclPrincipalDelimiter"); | ||
| log.config("aclPrincipalDelimiter: '" + aclPrincipalDelimiter + "'"); | ||
| } | ||
| aclPrincipalDelimiter = cfg.getValue("db.aclPrincipalDelimiter"); |
There was a problem hiding this comment.
add comment
// we might have delimiter and no aclSql as ACLs might come from singleDocContentSql rather than aclSql
| if (aclSql != null) { | ||
| resp.setAcl(getAcl(conn, id.getUniqueId())); | ||
| } else { | ||
| resp.setAcl(buildAcl(rs, aclPrincipalDelimiter, aclNamespace, |
There was a problem hiding this comment.
add comment
// see if ACL came as part of result to singleDocContentSql query
| denyGroups.addAll(getGroupPrincipalsFromResultSet(rs, | ||
| GsaSpecialColumns.GSA_DENY_GROUPS, delim, namespace)); | ||
| } | ||
| if (rsNext == ResultSetNext.STOP_NEXT) { |
There was a problem hiding this comment.
Please help me understand the constraint that ACL coming from singleDocContentSql imposes that requires this statement.
There was a problem hiding this comment.
We shouldn't be calling rs.next() when processing ACLs from singleDocContentSql, or else we would be moving to next or end of result set and wouldn't be able to get content from result set.
| String uniqueId) throws SQLException { | ||
| PreparedStatement st = conn.prepareStatement(singleDocContentSql); | ||
| uniqueKey.setContentSqlValues(st, uniqueId); | ||
| uniqueKey.setContentSqlValues(st, uniqueId); |
There was a problem hiding this comment.
has something changed on this line? github shows it as changed.
There was a problem hiding this comment.
Looks like I removed the whitespace at the end. Restored it.
| st = conn.prepareStatement(singleDocContentSql); | ||
| } else { | ||
| st = conn.prepareStatement(aclSql); | ||
| } |
There was a problem hiding this comment.
Thx, fixed it.
| CONTINUE_NEXT, | ||
| STOP_NEXT, | ||
| } | ||
|
|
There was a problem hiding this comment.
How about
PROCESS_ALL_RESULTS
PROCESS_ONE_RESULT
Am I understanding the semantics?
There was a problem hiding this comment.
Thx, modified these.
| } | ||
|
|
||
| @VisibleForTesting | ||
| static Acl buildAcl(ResultSet rs, String delim, String namespace) |
There was a problem hiding this comment.
Only tests currently. Moved this to tests.
| if (aclSql != null) { | ||
| resp.setAcl(getAcl(conn, id.getUniqueId())); | ||
| } else { | ||
| resp.setAcl(buildAcl(rs, aclPrincipalDelimiter, aclNamespace, |
There was a problem hiding this comment.
This seems like it's going to set the empty ACL (an explicitly constructed one, rather than Acl.EMPTY) on a document that should be public.
There was a problem hiding this comment.
Thx, fixed it by returning Acl.EMPTY when no acl info in the result
| String uniqueId) throws SQLException { | ||
| PreparedStatement st = conn.prepareStatement(singleDocContentSql); | ||
| uniqueKey.setContentSqlValues(st, uniqueId); | ||
| uniqueKey.setContentSqlValues(st, uniqueId); |
There was a problem hiding this comment.
Restore trailing whitespace on this unmodified line.
| PreparedStatement st = conn.prepareStatement(aclSql); | ||
| PreparedStatement st; | ||
| if (aclSql == null) { | ||
| st = conn.prepareStatement(singleDocContentSql); |
There was a problem hiding this comment.
It seems worth a comment here that this only happens when called from isUserAuthorized. Also, we will execute db.singleDocContentSql twice in that case. I suppose that's inevitable, but did you think about trying to avoid that?
| } | ||
|
|
||
| enum ResultSetNext { | ||
| CONTINUE_NEXT, |
There was a problem hiding this comment.
What do you think about ALL_ROWS, ONE_ROW?
There was a problem hiding this comment.
Combining your and PJ's suggestion, modified to PROCESS_ALL_ROWS , PROCESS_ONE_ROW.
| + GsaSpecialColumns.GSA_PERMIT_USERS + " varchar(20)," | ||
| + GsaSpecialColumns.GSA_DENY_GROUPS + " varchar(20)," | ||
| + GsaSpecialColumns.GSA_DENY_USERS + " varchar(20))"); | ||
| executeUpdate("insert into data(" |
There was a problem hiding this comment.
This test should minimally have 2 rows as a test of STOP_NEXT.
There was a problem hiding this comment.
Thx, added another row
| .build(); | ||
| ResultSet rs = executeQuery("select * from data"); | ||
| rs.next(); | ||
| Acl acl = DatabaseAdaptor.buildAcl(rs, ",", DEFAULT_NAMESPACE, |
There was a problem hiding this comment.
There are only six tests that use buildAcl instead of getDocContent. I think we should convert all of them, perhaps in a separate CL. Perhaps minimally we could use getDocContent for this new test. We have more logic around db.aclSql now, and I don't like bypassing that in the tests.
There was a problem hiding this comment.
Agree. Modified this test to call getDocContent instead of buildAcl.
|
|
||
| if (!hasPermitUsers && !hasDenyUsers | ||
| && !hasPermitGroups && !hasDenyGroups) { | ||
| return Acl.EMPTY; |
There was a problem hiding this comment.
Whether implicit or explicit, the empty ACL is wrong in the case of getting ACLs from db.singleDocContentSql. I think we could just add another argument for the default ACL to use here, either null or Acl.EMPTY. These values are paired with the ResultSetNext enum, so we could conceivably collapse them into a single argument, but that feels a little obfuscated.
Since this is a bug, albeit newly introduced, you should add a test for it.
There was a problem hiding this comment.
Done. Added test for it.
| GsaSpecialColumns.GSA_TIMESTAMP)); | ||
| } | ||
|
|
||
| private Acl buildAcl(ResultSet rs, String delim, String namespace) |
There was a problem hiding this comment.
I would have left this alone with a TODO, since we're planning to replace it entirely, or you could have used executeQueryAndNext instead of executeQuery. Just mentioning other ideas for posterity, since we're planning to sweep this away anyway.
There was a problem hiding this comment.
Agree. Keeping as is for now.
|
|
||
| Map<String, String> configEntries = new HashMap<String, String>(); | ||
| configEntries.put("db.uniqueKey", "id:int"); | ||
| configEntries.put("db.everyDocIdSql", "select id from data"); |
There was a problem hiding this comment.
Follow the boilerplate and put db.everyDocIdSql after the "Required for validation, ..." comment.
| RecordingResponse response = new RecordingResponse(); | ||
| adaptor.getDocContent(request, response); | ||
|
|
||
| Acl acl = response.getAcl(); |
There was a problem hiding this comment.
It's more consistent now, but if we're planning to use this as an exemplar, I think it's nicer to just inline this value in the assert.
| PreparedStatement st = conn.prepareStatement(aclSql); | ||
| PreparedStatement st; | ||
| if (aclSql == null) { | ||
| st = conn.prepareStatement(singleDocContentSql); |
There was a problem hiding this comment.
Added comment. Done.
| PreparedStatement st = conn.prepareStatement(singleDocContentSql); | ||
| uniqueKey.setContentSqlValues(st, uniqueId); | ||
| if (aclSql == null) { | ||
| uniqueKey.setAclSqlValues(st, uniqueId); |
There was a problem hiding this comment.
This seems wrong. The db.aclSqlParameters columns are specific to db.aclSql, and may not be the same in db.singleDocContentSql. Did something fail without this?
There was a problem hiding this comment.
Since this is wrong, too, maybe add a test where doing this would fail, too.
There was a problem hiding this comment.
Deleted the newly added lines, as these are not required. And no test required.
| private PreparedStatement getAclFromDb(Connection conn, | ||
| String uniqueId) throws SQLException { | ||
| PreparedStatement st = conn.prepareStatement(aclSql); | ||
| PreparedStatement st; |
There was a problem hiding this comment.
Maybe simpler:
String sql = (aclSql == null) ? singleDocContentSql : aclSql;
PreparedStatement st = conn.prepareStatement(sql);
There was a problem hiding this comment.
It seems a little redundant that we run this check before calling this function on line 681. I don't, at this time, have a better suggestion. Let's keep an eye out to see if there is a better way to keep the functions orthogonality composable. The current way is fine, but I will keep an eye out to see if there is something better. It is also possible that you are planning to revisit/refactor in follow up. Thank you
There was a problem hiding this comment.
Yes, thx. Done.
| denyGroups.addAll(getGroupPrincipalsFromResultSet(rs, | ||
| GsaSpecialColumns.GSA_DENY_GROUPS, delim, namespace)); | ||
| } | ||
| if (rsNext == ResultSetNext.PROCESS_ONE_ROW) { |
There was a problem hiding this comment.
Or maybe just:
} while (rsNext == ResultSetNext.PROCESS_ALL_ROWS && rs.next());
| RecordingResponse response = new RecordingResponse(); | ||
| adaptor.getDocContent(request, response); | ||
|
|
||
| assertEquals(golden, response.getAcl()); |
There was a problem hiding this comment.
The use of golden here seems silly. assertNull(response.getAcl()) is more clear.
|
|
||
| Map<String, String> configEntries = new HashMap<String, String>(); | ||
| configEntries.put("db.uniqueKey", "id:int"); | ||
| configEntries.put("db.everyDocIdSql", "select id from data"); |
There was a problem hiding this comment.
Missed comment here: put this at the end of the configEntries, after a comment:
// Required for validation, but not specific to this test.
| private PreparedStatement getAclFromDb(Connection conn, | ||
| String uniqueId) throws SQLException { | ||
| PreparedStatement st = conn.prepareStatement(aclSql); | ||
| // aclSql will be null when called from isUserAuthorized. |
| private PreparedStatement getAclFromDb(Connection conn, | ||
| String uniqueId) throws SQLException { | ||
| PreparedStatement st = conn.prepareStatement(aclSql); | ||
| PreparedStatement st; |
There was a problem hiding this comment.
It seems a little redundant that we run this check before calling this function on line 681. I don't, at this time, have a better suggestion. Let's keep an eye out to see if there is a better way to keep the functions orthogonality composable. The current way is fine, but I will keep an eye out to see if there is something better. It is also possible that you are planning to revisit/refactor in follow up. Thank you
| boolean hasResult = rs.next(); | ||
| if (!hasResult) { | ||
| // empty Acl ensures adaptor will mark this document as secure | ||
| return Acl.EMPTY; |
There was a problem hiding this comment.
Why move this code from buildAcl?
There was a problem hiding this comment.
Because the other call to buildAcl from getDocContent using the content SQL doesn't ever want to call rs.next(). We could check rsNext at the top and bottom of the loop in buildAcl, which is messier and another double-check, but it's in one method.
| @@ -697,18 +703,20 @@ private Acl getAcl(Connection conn, String uniqueId) throws SQLException { | |||
| try (PreparedStatement stmt = getAclFromDb(conn, uniqueId); | |||
There was a problem hiding this comment.
Perhaps rename getAclFromDb to runAclSqlStatement (to disambiguate that it is not running content sql)?
There was a problem hiding this comment.
As I mentioned, I didn't entirely like the structure of getAclFromDb, but it has parallel methods for getDocFromDb and getStreamFromDb. All three methods just create a PreparedStatement, so a basic rename to prepare{Acl,Doc,Stream}Statement seems reasonable, but feels like a separate CL. Maybe we can finish this one and start a new pull request to massage the structure?
Also, these methods have functional utility for try-with-resources: we want to call prepareStatement and executeQuery but do something in between. So we either need these helper methods, or we need two nested try-with-resources.
There was a problem hiding this comment.
Ah, yes, that changed here afe59e4#diff-dd03438283161f00e652d4769de767bf
I agree that some structure/renaming changes are fitting.
I have made a client and am reading DatabaseAdaptor.java file to re-acquaint myself with it. I plan to read it on Monday and make some suggestions then.
Thank you
| @@ -678,6 +680,10 @@ public void getDocContent(Request req, Response resp) throws IOException { | |||
| // Generate Acl if aclSql is provided. | |||
| if (aclSql != null) { | |||
| resp.setAcl(getAcl(conn, id.getUniqueId())); | |||
There was a problem hiding this comment.
Perhaps rename getAcl to getAclFromAclSql (to disambiguate that it is not running the content sql)?
There was a problem hiding this comment.
This call site for getAcl isn't running the content SQL, but when called from isUserAuthorized it is. I don't think that exposing the conditional from getAclFromDb in isUserAuthorized feels right. Perhaps better would be to bury this check for aclSql != null in getAcl as well, so that both call sites just always call getAcl, which figures out how to do the work.
|
|
||
| if (!hasPermitUsers && !hasDenyUsers | ||
| && !hasPermitGroups && !hasDenyGroups) { | ||
| return defaultAcl; |
There was a problem hiding this comment.
why do we need default acl parameter?
There was a problem hiding this comment.
If we have aclSql but no ACL entries, we want an empty ACL to mark the document secure. But if we have no aclSql and no ACL entries, then we want a null ACL to mark the document public.
| @@ -678,6 +680,10 @@ public void getDocContent(Request req, Response resp) throws IOException { | |||
| // Generate Acl if aclSql is provided. | |||
| if (aclSql != null) { | |||
| resp.setAcl(getAcl(conn, id.getUniqueId())); | |||
There was a problem hiding this comment.
This call site for getAcl isn't running the content SQL, but when called from isUserAuthorized it is. I don't think that exposing the conditional from getAclFromDb in isUserAuthorized feels right. Perhaps better would be to bury this check for aclSql != null in getAcl as well, so that both call sites just always call getAcl, which figures out how to do the work.
| @@ -697,18 +703,20 @@ private Acl getAcl(Connection conn, String uniqueId) throws SQLException { | |||
| try (PreparedStatement stmt = getAclFromDb(conn, uniqueId); | |||
There was a problem hiding this comment.
As I mentioned, I didn't entirely like the structure of getAclFromDb, but it has parallel methods for getDocFromDb and getStreamFromDb. All three methods just create a PreparedStatement, so a basic rename to prepare{Acl,Doc,Stream}Statement seems reasonable, but feels like a separate CL. Maybe we can finish this one and start a new pull request to massage the structure?
Also, these methods have functional utility for try-with-resources: we want to call prepareStatement and executeQuery but do something in between. So we either need these helper methods, or we need two nested try-with-resources.
| boolean hasResult = rs.next(); | ||
| if (!hasResult) { | ||
| // empty Acl ensures adaptor will mark this document as secure | ||
| return Acl.EMPTY; |
There was a problem hiding this comment.
Because the other call to buildAcl from getDocContent using the content SQL doesn't ever want to call rs.next(). We could check rsNext at the top and bottom of the loop in buildAcl, which is messier and another double-check, but it's in one method.
|
|
||
| if (!hasPermitUsers && !hasDenyUsers | ||
| && !hasPermitGroups && !hasDenyGroups) { | ||
| return defaultAcl; |
There was a problem hiding this comment.
If we have aclSql but no ACL entries, we want an empty ACL to mark the document secure. But if we have no aclSql and no ACL entries, then we want a null ACL to mark the document public.
PapaJoltOmega
left a comment
There was a problem hiding this comment.
Thanks for your thoughtful review John.
| @@ -697,18 +703,20 @@ private Acl getAcl(Connection conn, String uniqueId) throws SQLException { | |||
| try (PreparedStatement stmt = getAclFromDb(conn, uniqueId); | |||
There was a problem hiding this comment.
Ah, yes, that changed here afe59e4#diff-dd03438283161f00e652d4769de767bf
I agree that some structure/renaming changes are fitting.
I have made a client and am reading DatabaseAdaptor.java file to re-acquaint myself with it. I plan to read it on Monday and make some suggestions then.
Thank you
| String uniqueId) throws SQLException { | ||
| PreparedStatement st = conn.prepareStatement(aclSql); | ||
| // aclSql will only be null when called from isUserAuthorized. | ||
| String sql = (aclSql == null) ? singleDocContentSql : aclSql; |
There was a problem hiding this comment.
There are two bugs here. We'll have to go back to the if statement, because as I suggested elsewhere, the UniqueKey method depends on the query being executed and not the data being read from the result. So if we use singleDocContentSql here, we need to call setContentSqlValues rather than setAclSqlValues. We could just call getDocFromDb in that case, but the logging would be odd, and I think it's worth being clear that we're executing this statement to fetch the ACL in this case. We need some tests for mismatches in singleDocContentSqlParameters and aclSqlParameters (note that everyDocIdSql must return all the columns needed for both, but it could, for example, return 2 columns, and have each of the other queries use a different column; to check for errors I think something like a varchar and an integer column might do the trick, or one query could use both columns and the other just one).
Second, we're actually using AllPublic rather than AccessChecker when aclSql is null (this is set in init). At the moment, aclSql really can't be null here, but that's a bug. We need to always check for ACLs in the AuthzAuthority, but AccessChecker needs some work. We need to deal with the two TODOs, and the fact that getAcl can return null (I think the latter is the key to the former: a null ACL makes a null identity acceptable, otherwise we need the identity to compare to the ACL). Obviously, we need some tests here as well.
There was a problem hiding this comment.
As discussed, changed the code and added tests.
- added processAclQuery() - removed getAclFromDb() Added tests.
| } | ||
| } | ||
|
|
||
| private Acl processAclQuery(PreparedStatement st, Acl defaultAcl) |
There was a problem hiding this comment.
This was a surprising choice. Why did you extract this method instead of leaving getAclFromDb? The latter is a parallel method with two siblings, so instead of that consistency, you added this one-off method, and I don't think it isolates concerns very well, or reads any cleaner (it checks aclSql for null 3 times in getAcl, for example).
There was a problem hiding this comment.
Was trying to make it cleaner. Can't avoid aclSql check multiple times though.
Using getAclFromDb(), the code would be
private Acl getAcl(Connection conn, ResultSet rs, String uniqueId)
throws SQLException {
if (aclSql != null || rs == null) {
try (PreparedStatement stmt = getAclFromDb(conn, uniqueId);
ResultSet resSet = stmt.executeQuery()) {
log.finer("got acl");
boolean hasResult = resSet.next();
if (!hasResult) {
if (aclSql == null) {
return null;
} else {
// empty Acl ensures adaptor will mark this document as secure
return Acl.EMPTY;
}
} else {
return buildAcl(resSet, aclPrincipalDelimiter, aclNamespace,
ResultSetNext.PROCESS_ALL_ROWS, Acl.EMPTY);
}
}
} else {
// Generate ACL if it came as part of result to singleDocContentSql.
return buildAcl(rs, aclPrincipalDelimiter, aclNamespace,
ResultSetNext.PROCESS_ONE_ROW, null);
}
}
Restored it back.
| } | ||
|
|
||
| if (aclSql == null) { | ||
| context.setAuthzAuthority(new AllPublic()); |
There was a problem hiding this comment.
Yes missed it, removed it.
| for (DocId id : ids) { | ||
| log.log(Level.FINE, "about to get acl of doc {0}", id); | ||
| Acl acl = getAcl(conn, id.getUniqueId()); | ||
| Acl acl = getAcl(conn, null, id.getUniqueId()); |
There was a problem hiding this comment.
You missed some changes here. Try running this code live by fetching public docs directly from the adaptor.
| try (ResultSet resSet = st.executeQuery()) { | ||
| log.finer("got acl"); | ||
| boolean hasResult = rs.next(); | ||
| boolean hasResult = resSet.next(); |
There was a problem hiding this comment.
Why s/rs/resSet/? It's a non-standard abbreviation, and rs in a database connector seems perfectly clear.
There was a problem hiding this comment.
Unintended change in this new method, and carried over from trying to make it two nested try-with-resources blocks.
| if (!hasResult) { | ||
| // empty Acl ensures adaptor will mark this document as secure | ||
| return Acl.EMPTY; | ||
| return defaultAcl; |
There was a problem hiding this comment.
This is a behavioral change, albeit a minor one. Why make this change?
There was a problem hiding this comment.
When calling from isUserAuthorized and aclSql is null and has no results this needs to return null. Hence passing the defaultAcl and returning it.
There was a problem hiding this comment.
In fact, it needs to not return null. I thought it was just a nuisance to return null (it will execute the content SQL rather than just skipping this search result), but it's actually a security hole. If the row doesn't exist, then it makes no sense to return a PERMIT for it.
wiarlawd
left a comment
There was a problem hiding this comment.
Partial review. I didn't finish looking at the tests.
| moreEntries.put("db.everyDocIdSql", "select id from data"); | ||
| moreEntries.put("db.singleDocContentSql", | ||
| "select * from data where id = ?"); | ||
| executeUpdate("insert into data(id) values (1),(2)"); |
There was a problem hiding this comment.
This syntax is H2-specific and we eliminated it when porting the unit tests to other databases. What's the point of having two rows here, instead of just one? Also, why separate this from the CREATE TABLE? Next, note that this "public" test specifies a non-null identity. Finally, both the executeUpdate calls and the db.uniqueKey and db.singleDocContentSql properties are now specific to this test. In that case, we put the executeUpdate calls first, then create the moreEntries hash map and put db.singleDocContentSql into it.
There was a problem hiding this comment.
Only inserted data to existing test. Made changes as per comments.
| @Test | ||
| public void testAuthzAuthoritySingleDocContentSql_permit() throws Exception { | ||
| executeUpdate("create table data(id integer, loginid varchar(20), " | ||
| executeUpdate("create table data(id integer, author varchar(20), " |
There was a problem hiding this comment.
What's the s/loginid/author/g for?
There was a problem hiding this comment.
Instead of id and loginid as unique keys, id and author sounds better. Hence changed it.
| ResultSetNext.PROCESS_ALL_ROWS, Acl.EMPTY); | ||
| } else { | ||
| return buildAcl(resSet, aclPrincipalDelimiter, aclNamespace, | ||
| ResultSetNext.PROCESS_ALL_ROWS, null); |
There was a problem hiding this comment.
This should be PROCESS_ONE_ROW. We're back to 3 checks for aclSql == null, which I think suggests we need some refactoring. Maybe some kind of ACL strategy pattern, where we construct an appropriate object once for each scenario?
There was a problem hiding this comment.
Yes, it should be PROCESS_ONE_ROW, thx. Done.
Yes, agree, refactoring to reduce the null check for aclSql will look cleaner.
| throws SQLException { | ||
| if (aclSql != null || rs == null) { | ||
| try (PreparedStatement stmt = getAclFromDb(conn, uniqueId); | ||
| ResultSet resSet = stmt.executeQuery()) { |
There was a problem hiding this comment.
resSet is a terrible name. It gives no indication of how it's different from rs, is uses a short name for a parameter and a longer name for a local variable, and it uses a non-standard abbreviation. Better would be something like s/rs/contentRs/g and then s/resSet/rs/g.
| if (!hasResult) { | ||
| // empty Acl ensures adaptor will mark this document as secure | ||
| return Acl.EMPTY; | ||
| } else { |
| "authorization decision {0} for user {1} and doc {2}", | ||
| new Object[]{decision, user, id}); | ||
| result.put(id, decision); | ||
| if (userIdentity == null) { |
There was a problem hiding this comment.
What did you hope to gain by just moving this check inside the loop? Did you try this live?
There was a problem hiding this comment.
As discussed, changed to get and check Acl first.
| if (acl == null) { | ||
| result.put(id, AuthzStatus.PERMIT); | ||
| } else { | ||
| log.log(Level.INFO, "about to authorize {0} {1}", |
There was a problem hiding this comment.
What this meant to stay here?
There was a problem hiding this comment.
Existing log statement moved.
wiarlawd
left a comment
There was a problem hiding this comment.
This looks right to me. Since we had to work so hard to get the parameters right, let's be sure to capture that in the tests. Some missing tests that I found:
- PROCESS_ONE_ROW for both calls (testSingleDocSqlResultSetHasTwoRecords is not doing the job for the contentRs case because the query only returns one row)
Previously untested behaviors that we changed the code paths for, including:
- PROCESS_ALL_ROWS (there are apparently no tests with multiple rows returned by aclSql, despite the existing code to process such)
- Acl.EMPTY (ditto: the implicit empty ACL the code used to return for what's now the Acl.EMPTY defaultAcl parameter is untested: an aclSql with no ACL columns)
- Combining aclSql with setContentSqlColumns (this was never happening, but I think it's reasonable to augment testAuthzAuthorityAcl_permit with your author field and swizzle things so that this combo would fail there)
I don't think this needs to be 5 new tests, maybe just some config or test data variations in existing tests could cover these.
| } else if (userIdentity == null || userIdentity.getUser() == null) { | ||
| result.put(id, AuthzStatus.DENY); | ||
| } else { | ||
| log.log(Level.INFO, "about to authorize {0} {1}", |
There was a problem hiding this comment.
s/INFO/FINE/, since it's executed now for every document in the authZ request.
| getAuthnIdentity(new UserPrincipal("alice")), | ||
| Arrays.asList(new DocId("1"), new DocId("2"))); | ||
| null, | ||
| Arrays.asList(new DocId("1"))); |
There was a problem hiding this comment.
Oh, I see now, there were two docs in this test. I somehow missed that. I'm OK with restoring that. It seems reasonable to maintain that and test multiple IDs.
There was a problem hiding this comment.
Restored to maintain testing multiple IDs.
* Remove persistent if statements, especially checking whether aclSql is null. * Make it clear that there are two choices, whether aclSql is null, and whether we are coming from getDocContent or isUserAuthorized. * Make most of the config decisions at init-time. Notes: * Indentation is incorrect to reduce diffs. * Additional refactoring can eliminate the additional arguments for buildAcl and getAclFromDb by moving them inside of AclHandler.
- Added test testAuthzAuthoritySingleDocContentSql_muiltiRowAcl to test PROCESS_ONE_ROW - Modified test testAuthzAuthorityAcl_permit to test aclSql with setContentSqlColumns - Other changes as per review
wiarlawd
left a comment
There was a problem hiding this comment.
Just some organizational nits in the tests.
|
|
||
| Map<String, String> moreEntries = new HashMap<String, String>(); | ||
| moreEntries.put("db.aclSql", "select * from acl where id = ?"); | ||
| // Required for validation, but not specific to this test. |
There was a problem hiding this comment.
Why did you remove this, or treat the data table, modeOfOperation, or everyDocIdSql as specific to this test? I can see moving db.uniqueKey and db.everyDocIdSql up (though I probably wouldn't have move the latter, since it's never executed).
There was a problem hiding this comment.
It looked odd to have "create table data.." after "moreEntries.put("db.aclSql"..", hence moved it to top. However, I see that the other tests have this pattern. Restored. it. Thx.
| executeUpdate("create table data(id integer)"); | ||
|
|
||
| Map<String, String> moreEntries = new HashMap<String, String>(); | ||
| moreEntries.put("db.modeOfOperation", "rowToText"); |
There was a problem hiding this comment.
Move to "Required for validation"
| Map<String, String> moreEntries = new HashMap<String, String>(); | ||
| moreEntries.put("db.aclSqlParameters", "author"); | ||
| moreEntries.put("db.singleDocContentSqlParameters", "id, author"); | ||
| moreEntries.put("db.modeOfOperation", "rowToText"); |
There was a problem hiding this comment.
Move to "Required for validation"
| @Test | ||
| public void testAuthzAuthorityAcl_permit() throws Exception { | ||
| executeUpdate("create table acl(id integer, gsa_permit_users varchar(20))"); | ||
| executeUpdate("create table data(id integer, author varchar(20))"); |
There was a problem hiding this comment.
This shouldn't be here at all, but elsewhere the pattern is "create data, insert data, create acl, insert acl".
| executeUpdate("insert into data(id, gsa_permit_users) values (1, 'alice')"); | ||
|
|
||
| Map<String, String> moreEntries = new HashMap<String, String>(); | ||
| moreEntries.put("db.modeOfOperation", "rowToText"); |
There was a problem hiding this comment.
Yes, thx. Moved it in all the new tests.
wiarlawd
left a comment
There was a problem hiding this comment.
Looks good. We're waiting a bit for PJ, and in the meantime, please do a "git merge master" locally and resolve the conflicts and push the commit here.
* Remove persistent if statements, especially checking whether aclSql is null. * Make it clear that there are two choices, whether aclSql is null, and whether we are coming from getDocContent or isUserAuthorized. * Make most of the config decisions at init-time. Notes: * Indentation is incorrect to reduce diffs. * Additional refactoring can eliminate the additional arguments for buildAcl and getAclFromDb by moving them inside of AclHandler.
* Remove persistent if statements, especially checking whether aclSql is null. * Make it clear that there are two choices, whether aclSql is null, and whether we are coming from getDocContent or isUserAuthorized. * Make most of the config decisions at init-time. Notes: * Indentation is incorrect to reduce diffs. * Additional refactoring can eliminate the additional arguments for buildAcl and getAclFromDb by moving them inside of AclHandler.
No description provided.