mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
Use SecurityID in destructive campaign actions
Using POST rather than PUT because SecurityToken->checkRequest() doesn't accept PUT data (it's only in the request body, not in $_POST and HTTPRequest->requestVars()).
This commit is contained in:
parent
572d8427e0
commit
e840ba805e
@ -27,9 +27,9 @@ class CampaignAdmin extends LeftAndMain implements PermissionProvider {
|
||||
|
||||
private static $url_handlers = [
|
||||
'GET sets' => 'readCampaigns',
|
||||
'POST set/$ID/publish' => 'publishCampaign',
|
||||
'POST set/$ID' => 'createCampaign',
|
||||
'GET set/$ID/$Name' => 'readCampaign',
|
||||
'PUT set/$ID/publish' => 'publishCampaign',
|
||||
'PUT set/$ID' => 'updateCampaign',
|
||||
'DELETE set/$ID' => 'deleteCampaign',
|
||||
];
|
||||
@ -66,7 +66,7 @@ class CampaignAdmin extends LeftAndMain implements PermissionProvider {
|
||||
'itemListViewEndpoint' => $this->Link('set/:id/show'),
|
||||
'publishEndpoint' => [
|
||||
'url' => $this->Link('set/:id/publish'),
|
||||
'method' => 'put'
|
||||
'method' => 'post'
|
||||
]
|
||||
]);
|
||||
}
|
||||
@ -431,6 +431,12 @@ JSON;
|
||||
* @return SS_HTTPResponse
|
||||
*/
|
||||
public function publishCampaign(SS_HTTPRequest $request) {
|
||||
// Protect against CSRF on destructive action
|
||||
if(!SecurityToken::inst()->checkRequest($request)) {
|
||||
return (new SS_HTTPResponse(json_encode(['status' => 'error']), 400))
|
||||
->addHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
$id = $request->param('ID');
|
||||
if(!$id || !is_numeric($id)) {
|
||||
return (new SS_HTTPResponse(json_encode(['status' => 'error']), 400))
|
||||
|
@ -194,6 +194,10 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
$combinedClientConfig['sections'][$className] = Injector::inst()->get($className)->getClientConfig();
|
||||
}
|
||||
|
||||
// Get "global" CSRF token for use in JavaScript
|
||||
$token = new SecurityToken();
|
||||
$combinedClientConfig[$token->getName()] = $token->getValue();
|
||||
|
||||
return Convert::raw2json($combinedClientConfig);
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,9 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
||||
this.addCampaign = this.addCampaign.bind(this);
|
||||
this.createFn = this.createFn.bind(this);
|
||||
this.publishApi = backend.createEndpointFetcher({
|
||||
url: this.props.config.publishEndpoint.url,
|
||||
method: this.props.config.publishEndpoint.method,
|
||||
url: this.props.sectionConfig.publishEndpoint.url,
|
||||
method: this.props.sectionConfig.publishEndpoint.method,
|
||||
defaultData: { SecurityID: this.props.config.SecurityID },
|
||||
payloadSchema: {
|
||||
id: { urlReplacement: ':id', remove: true },
|
||||
},
|
||||
@ -27,7 +28,7 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.ss.router(`/${this.props.config.campaignViewRoute}`, (ctx) => {
|
||||
window.ss.router(`/${this.props.sectionConfig.campaignViewRoute}`, (ctx) => {
|
||||
this.props.actions.showCampaignView(ctx.params.id, ctx.params.view);
|
||||
});
|
||||
}
|
||||
@ -55,7 +56,7 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
||||
* @return object
|
||||
*/
|
||||
renderIndexView() {
|
||||
const schemaUrl = this.props.config.forms.editForm.schemaUrl;
|
||||
const schemaUrl = this.props.sectionConfig.forms.editForm.schemaUrl;
|
||||
|
||||
return (
|
||||
<div className="cms-middle no-preview">
|
||||
@ -80,7 +81,7 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
||||
renderItemListView() {
|
||||
const props = {
|
||||
campaignId: this.props.campaignId,
|
||||
itemListViewEndpoint: this.props.config.itemListViewEndpoint,
|
||||
itemListViewEndpoint: this.props.sectionConfig.itemListViewEndpoint,
|
||||
publishApi: this.publishApi,
|
||||
};
|
||||
|
||||
@ -105,7 +106,7 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
||||
* @return object - Instanciated React component
|
||||
*/
|
||||
createFn(Component, props) {
|
||||
const campaignViewRoute = this.props.config.campaignViewRoute;
|
||||
const campaignViewRoute = this.props.sectionConfig.campaignViewRoute;
|
||||
|
||||
if (props.component === 'GridField') {
|
||||
const extendedProps = Object.assign({}, props, {
|
||||
@ -149,19 +150,23 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
||||
}
|
||||
|
||||
CampaignAdminContainer.propTypes = {
|
||||
config: React.PropTypes.shape({
|
||||
sectionConfig: React.PropTypes.shape({
|
||||
forms: React.PropTypes.shape({
|
||||
editForm: React.PropTypes.shape({
|
||||
schemaUrl: React.PropTypes.string,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
config: React.PropTypes.shape({
|
||||
SecurityID: React.PropTypes.string,
|
||||
}),
|
||||
sectionConfigKey: React.PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
config: state.config.sections[ownProps.sectionConfigKey],
|
||||
config: state.config,
|
||||
sectionConfig: state.config.sections[ownProps.sectionConfigKey],
|
||||
campaignId: state.campaign.campaignId,
|
||||
view: state.campaign.view,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user