Skip to content

Commit

Permalink
#34 Close to doing everything except roles/users as a non-admin user
Browse files Browse the repository at this point in the history
  • Loading branch information
rjrudin committed Jul 6, 2015
1 parent 11cf423 commit dcbd66a
Show file tree
Hide file tree
Showing 16 changed files with 245 additions and 46 deletions.
45 changes: 18 additions & 27 deletions src/main/java/com/marklogic/appdeployer/AppConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ public class AppConfig {
private String name;
private String host = "localhost";

// User/password for authenticating against the REST API
private String username;
private String password;
// Username/password combo for using the client REST API - e.g. to load modules
private String restAdminUsername;
private String restAdminPassword;
private Authentication authentication = Authentication.DIGEST;

// User/password for making XDBC calls, usually against port 8000
Expand All @@ -30,7 +30,6 @@ public class AppConfig {

private List<String> modulePaths;
private ConfigDir configDir;
private List<ConfigDir> dependencyConfigDirs;

private String groupName = "Default";

Expand All @@ -49,10 +48,10 @@ public AppConfig(String defaultModulePath) {
modulePaths.add(defaultModulePath);
configDir = new ConfigDir();

this.username = "admin";
this.password = "admin";
this.xdbcUsername = username;
this.xdbcPassword = password;
this.restAdminUsername = "admin";
this.restAdminPassword = "admin";
this.xdbcUsername = restAdminUsername;
this.xdbcPassword = restAdminPassword;
}

public boolean isTestPortSet() {
Expand Down Expand Up @@ -104,15 +103,15 @@ public String getSchemasDatabaseName() {
}

public String getContentXccUrl() {
return String.format("xcc://%s:%s@%s:8000/%s", username, password, host, getContentDatabaseName());
return String.format("xcc://%s:%s@%s:8000/%s", xdbcUsername, xdbcPassword, host, getContentDatabaseName());
}

public String getTestContentXccUrl() {
return String.format("xcc://%s:%s@%s:8000/%s", username, password, host, getTestContentDatabaseName());
return String.format("xcc://%s:%s@%s:8000/%s", xdbcUsername, xdbcPassword, host, getTestContentDatabaseName());
}

public String getModulesXccUrl() {
return String.format("xcc://%s:%s@%s:8000/%s", username, password, host, getModulesDatabaseName());
return String.format("xcc://%s:%s@%s:8000/%s", xdbcUsername, xdbcPassword, host, getModulesDatabaseName());
}

public String getName() {
Expand All @@ -131,20 +130,20 @@ public void setHost(String host) {
this.host = host;
}

public String getUsername() {
return username;
public String getRestAdminUsername() {
return restAdminUsername;
}

public void setUsername(String username) {
this.username = username;
public void setRestAdminUsername(String username) {
this.restAdminUsername = username;
}

public String getPassword() {
return password;
public String getRestAdminPassword() {
return restAdminPassword;
}

public void setPassword(String password) {
this.password = password;
public void setRestAdminPassword(String password) {
this.restAdminPassword = password;
}

public Integer getRestPort() {
Expand Down Expand Up @@ -195,14 +194,6 @@ public void setConfigDir(ConfigDir configDir) {
this.configDir = configDir;
}

public List<ConfigDir> getDependencyConfigDirs() {
return dependencyConfigDirs;
}

public void setDependencyConfigDirs(List<ConfigDir> dependencyConfigDirs) {
this.dependencyConfigDirs = dependencyConfigDirs;
}

public String getXdbcUsername() {
return xdbcUsername;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void execute(CommandContext context) {
AppConfig config = context.getAppConfig();

DatabaseClient client = DatabaseClientFactory.newClient(config.getHost(), config.getRestPort(),
config.getUsername(), config.getPassword(), config.getAuthentication());
config.getRestAdminUsername(), config.getRestAdminPassword(), config.getAuthentication());

for (String modulesPath : config.getModulePaths()) {
logger.info("Loading modules from dir: " + modulesPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ public CreateRolesCommand() {
setExecuteSortOrder(SortOrderConstants.CREATE_ROLES);
}

/**
* Roles are usually the very last thing we want to delete, right after deleting users.
*/
@Override
public Integer getUndoSortOrder() {
return Integer.MAX_VALUE;
}

protected File getResourcesDir(CommandContext context) {
return new File(context.getAppConfig().getConfigDir().getSecurityDir(), "roles");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ public CreateUsersCommand() {
setExecuteSortOrder(SortOrderConstants.CREATE_USERS);
}

/**
* We usually want to delete users right before we delete roles, at the end of the deployment process.
*/
@Override
public Integer getUndoSortOrder() {
return Integer.MAX_VALUE - 10;
}

protected File getResourcesDir(CommandContext context) {
return new File(context.getAppConfig().getConfigDir().getSecurityDir(), "users");
}
Expand Down
19 changes: 15 additions & 4 deletions src/main/java/com/marklogic/rest/mgmt/AbstractManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ public class AbstractManager extends LoggingObject {

protected ObjectMapper objectMapper = new ObjectMapper();

/**
* Manager classes that need to connect to ML as a user with the admin role should override this to return true.
*
* @return
*/
protected boolean useAdminUser() {
return false;
}

/**
* Assumes the resource name is based on the class name - e.g. RoleManager would have a resource name of "role".
*
Expand Down Expand Up @@ -68,16 +77,18 @@ protected boolean isJsonPayload(String payload) {
}

protected ResponseEntity<String> putPayload(ManageClient client, String path, String payload) {
boolean useAdmin = useAdminUser();
if (isJsonPayload(payload)) {
return client.putJson(path, payload);
return useAdmin ? client.putJsonAsAdmin(path, payload) : client.putJson(path, payload);
}
return client.putXml(path, payload);
return useAdmin ? client.putXmlAsAdmin(path, payload) : client.putXml(path, payload);
}

protected ResponseEntity<String> postPayload(ManageClient client, String path, String payload) {
boolean useAdmin = useAdminUser();
if (isJsonPayload(payload)) {
return client.postJson(path, payload);
return useAdmin ? client.postJsonAsAdmin(path, payload) : client.postJson(path, payload);
}
return client.postXml(path, payload);
return useAdmin ? client.postXmlAsAdmin(path, payload) : client.postXml(path, payload);
}
}
16 changes: 12 additions & 4 deletions src/main/java/com/marklogic/rest/mgmt/AbstractResourceManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,19 @@ public boolean exists(String resourceNameOrId) {
}

public ResourcesFragment getAsXml() {
return new ResourcesFragment(manageClient.getXml(getResourcesPath()));
Fragment f = useAdminUser() ? manageClient.getXmlAsAdmin(getResourcesPath()) : manageClient
.getXml(getResourcesPath());
return new ResourcesFragment(f);
}

public Fragment getAsXml(String resourceNameOrId) {
return manageClient.getXml(getResourcePath(resourceNameOrId));
return useAdminUser() ? manageClient.getXmlAsAdmin(getResourcePath(resourceNameOrId)) : manageClient
.getXml(getResourcePath(resourceNameOrId));
}

public Fragment getPropertiesAsXml(String resourceNameOrId) {
return manageClient.getXml(getPropertiesPath(resourceNameOrId));
return useAdminUser() ? manageClient.getXmlAsAdmin(getPropertiesPath(resourceNameOrId)) : manageClient
.getXml(getPropertiesPath(resourceNameOrId));
}

public void save(String payload) {
Expand Down Expand Up @@ -74,7 +78,11 @@ public void delete(String payload) {
path = appendParamsAndValuesToPath(path, getDeleteResourceParams(payload));

logger.info(format("Deleting %s at path %s", label, path));
manageClient.delete(path);
if (useAdminUser()) {
manageClient.deleteAsAdmin(path);
} else {
manageClient.delete(path);
}
logger.info(format("Deleted %s at path %s", label, path));
}
}
Expand Down
63 changes: 63 additions & 0 deletions src/main/java/com/marklogic/rest/mgmt/ManageClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
public class ManageClient extends LoggingObject {

private RestTemplate restTemplate;
private RestTemplate adminRestTemplate;
private String baseUrl;

/**
Expand All @@ -42,6 +43,17 @@ public void initialize(ManageConfig config) {
logger.info("Initializing ManageClient with manage config of: " + config);
}
this.restTemplate = RestTemplateUtil.newRestTemplate(config);

if (!config.getUsername().equals(config.getAdminUsername())) {
if (logger.isInfoEnabled()) {
logger.info("Initializing ManageClient with admin config, admin user: " + config.getAdminUsername());
}
this.adminRestTemplate = RestTemplateUtil.newRestTemplate(config.getHost(), config.getPort(),
config.getAdminUsername(), config.getAdminPassword());
} else {
this.adminRestTemplate = restTemplate;
}

this.baseUrl = config.getBaseUrl();
if (logger.isInfoEnabled()) {
logger.info("Initialized ManageClient with base URL of: " + baseUrl);
Expand All @@ -52,18 +64,46 @@ public ResponseEntity<String> putJson(String path, String json) {
return restTemplate.exchange(baseUrl + path, HttpMethod.PUT, buildJsonEntity(json), String.class);
}

public ResponseEntity<String> putJsonAsAdmin(String path, String json) {
if (logger.isDebugEnabled()) {
logger.debug("Sending JSON PUT request as user with MarkLogic admin role");
}
return adminRestTemplate.exchange(baseUrl + path, HttpMethod.PUT, buildJsonEntity(json), String.class);
}

public ResponseEntity<String> putXml(String path, String xml) {
return restTemplate.exchange(baseUrl + path, HttpMethod.PUT, buildXmlEntity(xml), String.class);
}

public ResponseEntity<String> putXmlAsAdmin(String path, String xml) {
if (logger.isDebugEnabled()) {
logger.debug("Sending XML PUT request as user with MarkLogic admin role");
}
return adminRestTemplate.exchange(baseUrl + path, HttpMethod.PUT, buildXmlEntity(xml), String.class);
}

public ResponseEntity<String> postJson(String path, String json) {
return restTemplate.exchange(baseUrl + path, HttpMethod.POST, buildJsonEntity(json), String.class);
}

public ResponseEntity<String> postJsonAsAdmin(String path, String json) {
if (logger.isDebugEnabled()) {
logger.debug("Sending JSON POST request as user with MarkLogic admin role");
}
return adminRestTemplate.exchange(baseUrl + path, HttpMethod.POST, buildJsonEntity(json), String.class);
}

public ResponseEntity<String> postXml(String path, String xml) {
return restTemplate.exchange(baseUrl + path, HttpMethod.POST, buildXmlEntity(xml), String.class);
}

public ResponseEntity<String> postXmlAsAdmin(String path, String xml) {
if (logger.isDebugEnabled()) {
logger.debug("Sending XML POST request as user with MarkLogic admin role");
}
return adminRestTemplate.exchange(baseUrl + path, HttpMethod.POST, buildXmlEntity(xml), String.class);
}

public HttpEntity<String> buildJsonEntity(String json) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
Expand Down Expand Up @@ -96,15 +136,38 @@ public Fragment getXml(String path, String... namespacePrefixesAndUris) {
return new Fragment(xml, list.toArray(new Namespace[] {}));
}

public Fragment getXmlAsAdmin(String path, String... namespacePrefixesAndUris) {
if (logger.isDebugEnabled()) {
logger.debug("Sending GET request as user with MarkLogic admin role");
}
String xml = getAdminRestTemplate().getForObject(getBaseUrl() + path, String.class);
List<Namespace> list = new ArrayList<Namespace>();
for (int i = 0; i < namespacePrefixesAndUris.length; i += 2) {
list.add(Namespace.getNamespace(namespacePrefixesAndUris[i], namespacePrefixesAndUris[i + 1]));
}
return new Fragment(xml, list.toArray(new Namespace[] {}));
}

public void delete(String path) {
restTemplate.delete(baseUrl + path);
}

public void deleteAsAdmin(String path) {
if (logger.isDebugEnabled()) {
logger.debug("Sending DELETE request as user with MarkLogic admin role");
}
adminRestTemplate.delete(baseUrl + path);
}

public RestTemplate getRestTemplate() {
return restTemplate;
}

public String getBaseUrl() {
return baseUrl;
}

public RestTemplate getAdminRestTemplate() {
return adminRestTemplate;
}
}
29 changes: 26 additions & 3 deletions src/main/java/com/marklogic/rest/mgmt/ManageConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,42 @@
import com.marklogic.rest.util.RestConfig;

/**
* Defines the configuration data for talking to the Mgmt REST API.
* Defines the configuration data for talking to the Mgmt REST API. Also includes properties for the admin user, as this
* user is typically needed for managing resources such as roles and users. If adminUsername and adminPassword are not
* set, they default to the username/password attribute values.
*/
public class ManageConfig extends RestConfig {

private String adminUsername;
private String adminPassword;

public ManageConfig() {
super("localhost", 8002, "admin", "admin");
this("localhost", "admin");
}

public ManageConfig(String host, String password) {
super(host, 8002, "admin", password);
this(host, 8002, "admin", password);
}

public ManageConfig(String host, int port, String username, String password) {
super(host, port, username, password);
setAdminUsername(username);
setAdminPassword(password);
}

public String getAdminUsername() {
return adminUsername;
}

public void setAdminUsername(String adminUsername) {
this.adminUsername = adminUsername;
}

public String getAdminPassword() {
return adminPassword;
}

public void setAdminPassword(String adminPassword) {
this.adminPassword = adminPassword;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ public RoleManager(ManageClient client) {
super(client);
}

@Override
protected boolean useAdminUser() {
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@ public class UserManager extends AbstractResourceManager {
public UserManager(ManageClient client) {
super(client);
}

@Override
protected boolean useAdminUser() {
return true;
}

}
Loading

0 comments on commit dcbd66a

Please sign in to comment.