CSRF protection for gdata extension
This commit is contained in:
parent
b52c009491
commit
24feda600a
@ -109,17 +109,20 @@ Refine.GDataSourceUI.prototype._listDocuments = function() {
|
|||||||
this._elmts.progressPage.show();
|
this._elmts.progressPage.show();
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
$.post(
|
Refine.wrapCSRF(function(token) {
|
||||||
"command/core/importing-controller?" + $.param({
|
$.post(
|
||||||
"controller": "gdata/gdata-importing-controller",
|
"command/core/importing-controller?" + $.param({
|
||||||
"subCommand": "list-documents"
|
"controller": "gdata/gdata-importing-controller",
|
||||||
}),
|
"subCommand": "list-documents",
|
||||||
null,
|
"csrf_token": token
|
||||||
function(o) {
|
}),
|
||||||
self._renderDocuments(o);
|
null,
|
||||||
},
|
function(o) {
|
||||||
"json"
|
self._renderDocuments(o);
|
||||||
);
|
},
|
||||||
|
"json"
|
||||||
|
);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Refine.GDataSourceUI.prototype._renderDocuments = function(o) {
|
Refine.GDataSourceUI.prototype._renderDocuments = function(o) {
|
||||||
|
@ -71,33 +71,36 @@ Refine.GDataImportingController.prototype.startImportingDocument = function(doc)
|
|||||||
var dismiss = DialogSystem.showBusy($.i18n('gdata-import/preparing'));
|
var dismiss = DialogSystem.showBusy($.i18n('gdata-import/preparing'));
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
$.post(
|
Refine.postCSRF(
|
||||||
"command/core/create-importing-job",
|
"command/core/create-importing-job",
|
||||||
null,
|
null,
|
||||||
function(data) {
|
function(data) {
|
||||||
$.post(
|
Refine.wrapCSRF(function(token) {
|
||||||
"command/core/importing-controller?" + $.param({
|
$.post(
|
||||||
"controller": "gdata/gdata-importing-controller",
|
"command/core/importing-controller?" + $.param({
|
||||||
"subCommand": "initialize-parser-ui",
|
"controller": "gdata/gdata-importing-controller",
|
||||||
"docUrl": doc.docSelfLink,
|
"subCommand": "initialize-parser-ui",
|
||||||
"docType": doc.type
|
"docUrl": doc.docSelfLink,
|
||||||
}),
|
"docType": doc.type,
|
||||||
null,
|
"csrf_token": token
|
||||||
function(data2) {
|
}),
|
||||||
dismiss();
|
null,
|
||||||
|
function(data2) {
|
||||||
if (data2.status == 'ok') {
|
dismiss();
|
||||||
self._doc = doc;
|
|
||||||
self._jobID = data.jobID;
|
|
||||||
self._options = data2.options;
|
|
||||||
|
|
||||||
self._showParsingPanel();
|
if (data2.status == 'ok') {
|
||||||
} else {
|
self._doc = doc;
|
||||||
alert(data2.message);
|
self._jobID = data.jobID;
|
||||||
}
|
self._options = data2.options;
|
||||||
},
|
|
||||||
"json"
|
self._showParsingPanel();
|
||||||
);
|
} else {
|
||||||
|
alert(data2.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"json"
|
||||||
|
);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
"json"
|
"json"
|
||||||
);
|
);
|
||||||
@ -315,31 +318,34 @@ Refine.GDataImportingController.prototype._updatePreview = function() {
|
|||||||
this._parsingPanelElmts.dataPanel.hide();
|
this._parsingPanelElmts.dataPanel.hide();
|
||||||
this._parsingPanelElmts.progressPanel.show();
|
this._parsingPanelElmts.progressPanel.show();
|
||||||
|
|
||||||
$.post(
|
Refine.wrapCSRF(function(token) {
|
||||||
"command/core/importing-controller?" + $.param({
|
$.post(
|
||||||
"controller": "gdata/gdata-importing-controller",
|
"command/core/importing-controller?" + $.param({
|
||||||
"jobID": this._jobID,
|
"controller": "gdata/gdata-importing-controller",
|
||||||
"subCommand": "parse-preview"
|
"jobID": this._jobID,
|
||||||
}),
|
"subCommand": "parse-preview",
|
||||||
{
|
"csrf_token": token
|
||||||
"options" : JSON.stringify(this.getOptions())
|
}),
|
||||||
},
|
{
|
||||||
function(result) {
|
"options" : JSON.stringify(this.getOptions())
|
||||||
if (result.status == "ok") {
|
},
|
||||||
self._getPreviewData(function(projectData) {
|
function(result) {
|
||||||
self._parsingPanelElmts.progressPanel.hide();
|
if (result.status == "ok") {
|
||||||
self._parsingPanelElmts.dataPanel.show();
|
self._getPreviewData(function(projectData) {
|
||||||
|
self._parsingPanelElmts.progressPanel.hide();
|
||||||
|
self._parsingPanelElmts.dataPanel.show();
|
||||||
|
|
||||||
new Refine.PreviewTable(projectData, self._parsingPanelElmts.dataPanel.unbind().empty());
|
new Refine.PreviewTable(projectData, self._parsingPanelElmts.dataPanel.unbind().empty());
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
self._parsingPanelElmts.progressPanel.hide();
|
self._parsingPanelElmts.progressPanel.hide();
|
||||||
alert('Errors:\n' +
|
alert('Errors:\n' +
|
||||||
(result.message) ? result.message : Refine.CreateProjectUI.composeErrorMessage(job));
|
(result.message) ? result.message : Refine.CreateProjectUI.composeErrorMessage(job));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"json"
|
"json"
|
||||||
);
|
);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Refine.GDataImportingController.prototype._getPreviewData = function(callback, numRows) {
|
Refine.GDataImportingController.prototype._getPreviewData = function(callback, numRows) {
|
||||||
@ -385,52 +391,55 @@ Refine.GDataImportingController.prototype._createProject = function() {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var options = this.getOptions();
|
var options = this.getOptions();
|
||||||
options.projectName = projectName;
|
options.projectName = projectName;
|
||||||
$.post(
|
Refine.wrapCSRF(function(token) {
|
||||||
"command/core/importing-controller?" + $.param({
|
$.post(
|
||||||
"controller": "gdata/gdata-importing-controller",
|
"command/core/importing-controller?" + $.param({
|
||||||
"jobID": this._jobID,
|
"controller": "gdata/gdata-importing-controller",
|
||||||
"subCommand": "create-project"
|
"jobID": this._jobID,
|
||||||
}),
|
"subCommand": "create-project",
|
||||||
{
|
"csrf_token": token
|
||||||
"options" : JSON.stringify(options)
|
}),
|
||||||
},
|
{
|
||||||
function(o) {
|
"options" : JSON.stringify(options)
|
||||||
if (o.status == 'error') {
|
},
|
||||||
alert(o.message);
|
function(o) {
|
||||||
} else {
|
if (o.status == 'error') {
|
||||||
var start = new Date();
|
alert(o.message);
|
||||||
var timerID = window.setInterval(
|
} else {
|
||||||
function() {
|
var start = new Date();
|
||||||
self._createProjectUI.pollImportJob(
|
var timerID = window.setInterval(
|
||||||
start,
|
function() {
|
||||||
self._jobID,
|
self._createProjectUI.pollImportJob(
|
||||||
timerID,
|
start,
|
||||||
function(job) {
|
self._jobID,
|
||||||
return "projectID" in job.config;
|
timerID,
|
||||||
},
|
function(job) {
|
||||||
function(jobID, job) {
|
return "projectID" in job.config;
|
||||||
window.clearInterval(timerID);
|
},
|
||||||
Refine.CreateProjectUI.cancelImportingJob(jobID);
|
function(jobID, job) {
|
||||||
document.location = "project?project=" + job.config.projectID;
|
window.clearInterval(timerID);
|
||||||
},
|
Refine.CreateProjectUI.cancelImportingJob(jobID);
|
||||||
function(job) {
|
document.location = "project?project=" + job.config.projectID;
|
||||||
alert(Refine.CreateProjectUI.composeErrorMessage(job));
|
},
|
||||||
}
|
function(job) {
|
||||||
|
alert(Refine.CreateProjectUI.composeErrorMessage(job));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
1000
|
||||||
);
|
);
|
||||||
},
|
self._createProjectUI.showImportProgressPanel($.i18n('gdata-import/creating'), function() {
|
||||||
1000
|
// stop the timed polling
|
||||||
);
|
window.clearInterval(timerID);
|
||||||
self._createProjectUI.showImportProgressPanel($.i18n('gdata-import/creating'), function() {
|
|
||||||
// stop the timed polling
|
|
||||||
window.clearInterval(timerID);
|
|
||||||
|
|
||||||
// explicitly cancel the import job
|
// explicitly cancel the import job
|
||||||
Refine.CreateProjectUI.cancelImportingJob(jobID);
|
Refine.CreateProjectUI.cancelImportingJob(jobID);
|
||||||
|
|
||||||
self._createProjectUI.showSourceSelectionPanel();
|
self._createProjectUI.showSourceSelectionPanel();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"json"
|
"json"
|
||||||
);
|
);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,7 @@ $.i18n().load(dictionary, lang);
|
|||||||
var name = window.prompt(prompt, theProject.metadata.name);
|
var name = window.prompt(prompt, theProject.metadata.name);
|
||||||
if (name) {
|
if (name) {
|
||||||
var dismiss = DialogSystem.showBusy($.i18n('gdata-exporter/uploading'));
|
var dismiss = DialogSystem.showBusy($.i18n('gdata-exporter/uploading'));
|
||||||
$.post(
|
Refine.postCSRF(
|
||||||
"command/gdata/upload",
|
"command/gdata/upload",
|
||||||
{
|
{
|
||||||
"project" : theProject.id,
|
"project" : theProject.id,
|
||||||
|
@ -66,7 +66,9 @@
|
|||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<version>${surefire.version}</version>
|
<version>${surefire.version}</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<skip>true</skip>
|
<suiteXmlFiles>
|
||||||
|
<suiteXmlFile>tests/conf/tests.xml</suiteXmlFile>
|
||||||
|
</suiteXmlFiles>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
@ -162,6 +164,12 @@
|
|||||||
<version>6.9.10</version>
|
<version>6.9.10</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>2.23.4</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@ public class UploadCommand extends Command {
|
|||||||
@Override
|
@Override
|
||||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
if(!hasValidCSRFToken(request)) {
|
||||||
|
respondCSRFError(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String token = TokenCookie.getToken(request);
|
String token = TokenCookie.getToken(request);
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
|
14
extensions/gdata/tests/conf/tests.xml
Normal file
14
extensions/gdata/tests/conf/tests.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
|
||||||
|
|
||||||
|
<suite name="GData extension">
|
||||||
|
<test name="tests">
|
||||||
|
<groups>
|
||||||
|
<run>
|
||||||
|
<exclude name="broken" />
|
||||||
|
</run>
|
||||||
|
</groups>
|
||||||
|
<packages>
|
||||||
|
<package name="com.google.refine.extension.gdata.*" />
|
||||||
|
</packages>
|
||||||
|
</test>
|
||||||
|
</suite>
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.google.refine.extension.gdata;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.BeforeMethod;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.google.refine.commands.Command;
|
||||||
|
import com.google.refine.util.ParsingUtilities;
|
||||||
|
|
||||||
|
public class UploadCommandTest {
|
||||||
|
protected HttpServletRequest request = null;
|
||||||
|
protected HttpServletResponse response = null;
|
||||||
|
protected Command command = null;
|
||||||
|
protected StringWriter writer = null;
|
||||||
|
|
||||||
|
@BeforeMethod
|
||||||
|
public void setUpRequestResponse() {
|
||||||
|
request = mock(HttpServletRequest.class);
|
||||||
|
response = mock(HttpServletResponse.class);
|
||||||
|
writer = new StringWriter();
|
||||||
|
command = new UploadCommand();
|
||||||
|
try {
|
||||||
|
when(response.getWriter()).thenReturn(new PrintWriter(writer));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCsrfProtection() throws ServletException, IOException {
|
||||||
|
command.doPost(request, response);
|
||||||
|
Assert.assertEquals(
|
||||||
|
ParsingUtilities.mapper.readValue("{\"code\":\"error\",\"message\":\"Missing or invalid csrf_token parameter\"}", ObjectNode.class),
|
||||||
|
ParsingUtilities.mapper.readValue(writer.toString(), ObjectNode.class));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user