SOLR-5455: add managed schema name to the files the admin UI cannot edit

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1542859 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Erick Erickson 2013-11-17 22:59:42 +00:00
parent 194238944c
commit 6e78f9a497
2 changed files with 69 additions and 89 deletions

View File

@ -36,6 +36,8 @@ import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.RawResponseWriter;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.ManagedIndexSchema;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -170,13 +172,11 @@ public class ShowFileRequestHandler extends RequestHandlerBase
if (fname == null) {
rsp.setException(new SolrException(ErrorCode.BAD_REQUEST, "No file name specified for write operation."));
} else {
if (coreContainer.isZooKeeperAware()) {
if (isHiddenFile(rsp, fname) == false) {
fname = fname.replace('\\', '/');
if (isHiddenFile(req, rsp, fname, true) == false) {
if (coreContainer.isZooKeeperAware()) {
writeToZooKeeper(req, rsp, coreContainer);
}
} else {
fname = fname.replace('\\', '/'); // normalize slashes. Should be done above too?
if (isHiddenFile(rsp, fname) == false) {
} else {
writeToFileSystem(req, rsp);
}
}
@ -186,21 +186,38 @@ public class ShowFileRequestHandler extends RequestHandlerBase
// See if we should deal with this file
private boolean isHiddenFile(SolrQueryResponse rsp, String fnameIn) {
private boolean isHiddenFile(SolrQueryRequest req, SolrQueryResponse rsp, String fnameIn, boolean reportError) {
String fname = fnameIn.toUpperCase(Locale.ROOT);
if (hiddenFiles.contains(fname) || hiddenFiles.contains("*")) {
log.error("Cannot access " + fname);
rsp.setException(new SolrException(ErrorCode.FORBIDDEN, "Can not access: " + fnameIn));
if (reportError) {
log.error("Cannot access " + fname);
rsp.setException(new SolrException(ErrorCode.FORBIDDEN, "Can not access: " + fnameIn));
}
return true;
}
// This is slightly off, a valid path is something like ./schema.xml. I don't think it's worth the effort though
// to fix it to handle all possibilities though.
if (fname.indexOf("..") >= 0 || fname.startsWith(".")) {
log.error("Invalid path: " + fname);
rsp.setException(new SolrException(ErrorCode.FORBIDDEN, "Invalid path: " + fnameIn));
if (reportError) {
log.error("Invalid path: " + fname);
rsp.setException(new SolrException(ErrorCode.FORBIDDEN, "Invalid path: " + fnameIn));
}
return true;
}
// Make sure that if the schema is managed, we don't allow editing. Don't really want to put
// this in the init since we're not entirely sure when the managed schema will get initialized relative to this
// handler.
SolrCore core = req.getCore();
IndexSchema schema = core.getLatestSchema();
if (schema instanceof ManagedIndexSchema) {
String managed = schema.getResourceName();
if (fname.equalsIgnoreCase(managed)) {
return true;
}
}
return false;
}
@ -223,7 +240,7 @@ public class ShowFileRequestHandler extends RequestHandlerBase
adminFile = confPath;
} else {
fname = fname.replace('\\', '/'); // normalize slashes
if (isHiddenFile(rsp, fname)) {
if (isHiddenFile(req, rsp, fname, true)) {
return null;
}
if (fname.startsWith("/")) { // Only files relative to conf are valid
@ -291,7 +308,7 @@ public class ShowFileRequestHandler extends RequestHandlerBase
NamedList<SimpleOrderedMap<Object>> files = new SimpleOrderedMap<SimpleOrderedMap<Object>>();
for (String f : children) {
if (isHiddenFile(rsp, f)) {
if (isHiddenFile(req, rsp, f, false)) {
continue;
}
@ -452,13 +469,11 @@ public class ShowFileRequestHandler extends RequestHandlerBase
for( File f : adminFile.listFiles() ) {
String path = f.getAbsolutePath().substring( basePath );
path = path.replace( '\\', '/' ); // normalize slashes
if( hiddenFiles.contains( path.toUpperCase(Locale.ROOT) ) ) {
continue; // don't show 'hidden' files
if (isHiddenFile(req, rsp, f.getName().replace('\\', '/'), false)) {
continue;
}
if( f.isHidden() || f.getName().startsWith( "." ) ) {
continue; // skip hidden system files...
}
SimpleOrderedMap<Object> fileInfo = new SimpleOrderedMap<Object>();
files.add( path, fileInfo );
if( f.isDirectory() ) {
@ -480,7 +495,7 @@ public class ShowFileRequestHandler extends RequestHandlerBase
req.setParams(params);
ContentStreamBase content = new ContentStreamBase.FileStream( adminFile );
content.setContentType( req.getParams().get( USE_CONTENT_TYPE ) );
content.setContentType(req.getParams().get(USE_CONTENT_TYPE));
rsp.add(RawResponseWriter.CONTENT, content);
}

View File

@ -16,23 +16,20 @@ package org.apache.solr.schema;
* limitations under the License.
*/
import org.apache.commons.io.IOUtils;
import org.apache.solr.client.solrj.ResponseParser;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.cloud.AbstractFullDistribZkTestBase;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.zookeeper.KeeperException;
import org.junit.BeforeClass;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.regex.Pattern;
import java.util.List;
public class TestCloudManagedSchema extends AbstractFullDistribZkTestBase {
@ -69,72 +66,40 @@ public class TestCloudManagedSchema extends AbstractFullDistribZkTestBase {
String collectionSchema = (String)collectionStatus.get(CoreAdminParams.SCHEMA);
// Make sure the upgrade to managed schema happened
assertEquals("Schema resource name differs from expected name", "managed-schema", collectionSchema);
// Make sure "DO NOT EDIT" is in the content of the managed schema
String fileContent = getFileContentFromZooKeeper("managed-schema");
assertTrue("Managed schema is missing", fileContent.contains("DO NOT EDIT"));
// Make sure the original non-managed schema is no longer in ZooKeeper
assertFileNotInZooKeeper("schema.xml");
// Make sure the renamed non-managed schema is present in ZooKeeper
fileContent = getFileContentFromZooKeeper("schema.xml.bak");
assertTrue("schema file doesn't contain '<schema'", fileContent.contains("<schema"));
}
private String getFileContentFromZooKeeper(String fileName) throws IOException, SolrServerException {
QueryRequest request = new QueryRequest(params("file", fileName));
request.setPath("/admin/file");
RawResponseParser responseParser = new RawResponseParser();
request.setResponseParser(responseParser);
int which = r.nextInt(clients.size());
// For some reason, /admin/file requests work without stripping the /collection1 step from the URL
// (unlike /admin/cores requests - see above)
SolrServer client = clients.get(which);
client.request(request);
return responseParser.getRawFileContent();
}
private class RawResponseParser extends ResponseParser {
// Stolen from ShowFileRequestHandlerTest
private String rawFileContent = null;
String getRawFileContent() { return rawFileContent; }
@Override
public String getWriterType() {
return "mock";//unfortunately this gets put onto params wt=mock but it apparently has no effect
}
@Override
public NamedList<Object> processResponse(InputStream body, String encoding) {
try {
rawFileContent = IOUtils.toString(body, encoding);
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
@Override
public NamedList<Object> processResponse(Reader reader) {
throw new UnsupportedOperationException("TODO unimplemented");//TODO
}
}
protected final void assertFileNotInZooKeeper(String fileName) throws Exception {
// Stolen from AbstractBadConfigTestBase
String errString = "Not Found";
ignoreException(Pattern.quote(errString));
String rawContent = null;
SolrZkClient zkClient = new SolrZkClient(zkServer.getZkHost(), 30000);
try {
rawContent = getFileContentFromZooKeeper(fileName);
} catch (Exception e) {
// short circuit out if we found what we expected
if (-1 != e.getMessage().indexOf(errString)) return;
// otherwise, rethrow it, possibly completely unrelated
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Unexpected error, expected error matching: " + errString, e);
// Make sure "DO NOT EDIT" is in the content of the managed schema
String fileContent = getFileContentFromZooKeeper(zkClient, "/solr/configs/conf1/managed-schema");
assertTrue("Managed schema is missing", fileContent.contains("DO NOT EDIT"));
// Make sure the original non-managed schema is no longer in ZooKeeper
assertFileNotInZooKeeper(zkClient, "/solr/configs/conf1", "schema.xml");
// Make sure the renamed non-managed schema is present in ZooKeeper
fileContent = getFileContentFromZooKeeper(zkClient, "/solr/configs/conf1/schema.xml.bak");
assertTrue("schema file doesn't contain '<schema'", fileContent.contains("<schema"));
} finally {
resetExceptionIgnores();
if (zkClient != null) {
zkClient.close();
}
}
}
private String getFileContentFromZooKeeper(SolrZkClient zkClient, String fileName)
throws IOException, SolrServerException, KeeperException, InterruptedException {
return (new String(zkClient.getData(fileName, null, null, true), "UTF-8"));
}
protected final void assertFileNotInZooKeeper(SolrZkClient zkClient, String parent, String fileName) throws Exception {
List<String> kids = zkClient.getChildren(parent, null, true);
for (String kid : kids) {
if (kid.equalsIgnoreCase(fileName)) {
String rawContent = new String(zkClient.getData(fileName, null, null, true), "UTF-8");
fail("File '" + fileName + "' was unexpectedly found in ZooKeeper. Content starts with '"
+ rawContent.substring(0, 100) + " [...]'");
}
}
fail("File '" + fileName + "' was unexpectedly found in ZooKeeper. Content starts with '"
+ rawContent.substring(0, 100) + " [...]'");
}
}