Skip to content

Commit 4938b34

Browse files
committed
DEVEXP-478 New addFromString method for permissions
This logic is from ml-javaclient-util, pretty much copy/pasted it and added tests. Also moved a test to the new "client.test.io" package as I don't like how we have a zillion tests in the "com.marklogic.client.test" package.
1 parent e41aa86 commit 4938b34

File tree

3 files changed

+128
-14
lines changed

3 files changed

+128
-14
lines changed

marklogic-client-api/src/main/java/com/marklogic/client/io/DocumentMetadataHandle.java

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.io.InputStream;
2222
import java.io.InputStreamReader;
2323
import java.io.OutputStream;
24-
import java.io.UnsupportedEncodingException;
2524
import java.math.BigDecimal;
2625
import java.math.BigInteger;
2726
import java.nio.charset.StandardCharsets;
@@ -95,18 +94,33 @@ public void addAll(String... collections) {
9594
}
9695
}
9796

98-
/**
99-
* Represents the permissions for a database document.
100-
*/
101-
public interface DocumentPermissions extends Map<String,Set<Capability>> {
102-
/**
103-
* Adds a role with one or more capabilities to the metadata that can be written
104-
* for the document.
105-
* @param role the role for users permitted to access the document
106-
* @param capabilities the permissions to be granted to users with the role
107-
*/
108-
public void add(String role, Capability... capabilities);
109-
}
97+
/**
98+
* Represents the permissions for a database document.
99+
*/
100+
public interface DocumentPermissions extends Map<String, Set<Capability>> {
101+
/**
102+
* Adds a role with one or more capabilities to the metadata that can be written
103+
* for the document.
104+
*
105+
* @param role the role for users permitted to access the document
106+
* @param capabilities the permissions to be granted to users with the role
107+
*/
108+
void add(String role, Capability... capabilities);
109+
110+
/**
111+
* Adds one or more permissions based on the given comma-delimited string. Each capability value is
112+
* case-insensitive; you do not need to worry about providing the correct case. Similar to {@code add}, this
113+
* method adds permissions and can thus add capabilities to roles already present in this object.
114+
*
115+
* For example, the following string would add two permissions - a "read" permission for "rest-reader" and an
116+
* "update" permission for "rest-writer": rest-reader,read,rest-writer,update.
117+
*
118+
* @param commaSeparatedRolesAndCapabilities comma-delimited string of the pattern: role1,capability1,role2,capability2,etc.
119+
* @since 6.3.0
120+
*/
121+
void addFromString(String commaSeparatedRolesAndCapabilities);
122+
}
123+
110124
@SuppressWarnings("serial")
111125
static private class PermissionsImpl extends HashMap<String,Set<Capability>> implements DocumentPermissions {
112126
@Override
@@ -130,7 +144,42 @@ public void add(String role, Capability capability) {
130144
put(role, caps );
131145
}
132146
}
147+
148+
/**
149+
*
150+
* @param commaSeparatedRolesAndCapabilities comma-delimited string of the pattern: role1,capability1,role2,capability2,etc.
151+
* @since 6.3.0
152+
*/
153+
@Override
154+
public void addFromString(String commaSeparatedRolesAndCapabilities) {
155+
if (commaSeparatedRolesAndCapabilities != null && commaSeparatedRolesAndCapabilities.trim().length() > 0) {
156+
String[] tokens = commaSeparatedRolesAndCapabilities.trim().split(",");
157+
for (int i = 0; i < tokens.length; i += 2) {
158+
String role = tokens[i];
159+
if (i + 1 >= tokens.length) {
160+
throw new IllegalArgumentException(String.format(
161+
"Unable to parse permissions string, which must be a comma-separated " +
162+
"list of role names and capabilities - i.e. role1,read,role2,update,role3,execute; string: %s",
163+
commaSeparatedRolesAndCapabilities));
164+
}
165+
Capability c;
166+
try {
167+
c = Capability.getValueOf(tokens[i + 1]);
168+
} catch (Exception e) {
169+
throw new IllegalArgumentException(String.format(
170+
"Unable to parse permissions string: %s; cause: %s",
171+
commaSeparatedRolesAndCapabilities, e.getMessage()));
172+
}
173+
if (this.containsKey(role)) {
174+
this.get(role).add(c);
175+
} else {
176+
this.add(role, c);
177+
}
178+
}
179+
}
180+
}
133181
}
182+
134183
/**
135184
* A document operation restricted to users with a role.
136185
*/
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.marklogic.client.test.io;
2+
3+
import com.marklogic.client.io.DocumentMetadataHandle;
4+
import org.junit.jupiter.api.BeforeEach;
5+
import org.junit.jupiter.api.Test;
6+
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
import static org.junit.jupiter.api.Assertions.assertThrows;
9+
import static org.junit.jupiter.api.Assertions.assertTrue;
10+
11+
public class AddPermissionsFromStringTest {
12+
13+
private DocumentMetadataHandle.DocumentPermissions permissions;
14+
15+
@BeforeEach
16+
void beforeEach() {
17+
permissions = new DocumentMetadataHandle().getPermissions();
18+
}
19+
20+
@Test
21+
void simpleCase() {
22+
permissions.addFromString("rest-admin,read,rest-admin,update,rest-extension-user,execute,app-user,node-update");
23+
24+
assertEquals(3, permissions.size());
25+
assertEquals(2, permissions.get("rest-admin").size());
26+
assertEquals(1, permissions.get("rest-extension-user").size());
27+
assertEquals(DocumentMetadataHandle.Capability.EXECUTE, permissions.get("rest-extension-user").iterator().next());
28+
assertEquals(1, permissions.get("app-user").size());
29+
assertEquals(DocumentMetadataHandle.Capability.NODE_UPDATE, permissions.get("app-user").iterator().next());
30+
}
31+
32+
@Test
33+
void roleAlreadyExists() {
34+
permissions.addFromString("rest-reader,read");
35+
assertEquals(1, permissions.size());
36+
assertEquals(1, permissions.get("rest-reader").size());
37+
38+
permissions.addFromString("rest-reader,update");
39+
assertEquals(1, permissions.size());
40+
assertEquals(2, permissions.get("rest-reader").size());
41+
42+
permissions.addFromString("rest-reader,read");
43+
assertEquals(1, permissions.size());
44+
assertEquals(2, permissions.get("rest-reader").size(), "A duplicate permission should be ignored since the " +
45+
"set of capabilities is a Set.");
46+
}
47+
48+
@Test
49+
void badInput() {
50+
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
51+
() -> permissions.addFromString("rest-admin,read,rest-admin"));
52+
assertTrue(ex.getMessage().startsWith("Unable to parse permissions string"));
53+
}
54+
55+
@Test
56+
void invalidCapability() {
57+
IllegalArgumentException ex = assertThrows(
58+
IllegalArgumentException.class,
59+
() -> permissions.addFromString("app-user,not-valid"));
60+
assertEquals("Unable to parse permissions string: app-user,not-valid; cause: No enum constant com.marklogic.client.io.DocumentMetadataHandle.Capability.NOT_VALID",
61+
ex.getMessage());
62+
}
63+
64+
}

marklogic-client-api/src/test/java/com/marklogic/client/test/DocumentMetadataHandleTest.java renamed to marklogic-client-api/src/test/java/com/marklogic/client/test/io/DocumentMetadataHandleTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.marklogic.client.test;
16+
package com.marklogic.client.test.io;
1717

1818
import com.marklogic.client.Transaction;
1919
import com.marklogic.client.document.BinaryDocumentManager;
@@ -24,6 +24,7 @@
2424
import com.marklogic.client.io.FileHandle;
2525
import com.marklogic.client.io.InputStreamHandle;
2626
import com.marklogic.client.io.StringHandle;
27+
import com.marklogic.client.test.Common;
2728
import org.custommonkey.xmlunit.exceptions.XpathException;
2829
import org.junit.jupiter.api.AfterAll;
2930
import org.junit.jupiter.api.BeforeAll;

0 commit comments

Comments
 (0)