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 = [
|
private static $url_handlers = [
|
||||||
'GET sets' => 'readCampaigns',
|
'GET sets' => 'readCampaigns',
|
||||||
|
'POST set/$ID/publish' => 'publishCampaign',
|
||||||
'POST set/$ID' => 'createCampaign',
|
'POST set/$ID' => 'createCampaign',
|
||||||
'GET set/$ID/$Name' => 'readCampaign',
|
'GET set/$ID/$Name' => 'readCampaign',
|
||||||
'PUT set/$ID/publish' => 'publishCampaign',
|
|
||||||
'PUT set/$ID' => 'updateCampaign',
|
'PUT set/$ID' => 'updateCampaign',
|
||||||
'DELETE set/$ID' => 'deleteCampaign',
|
'DELETE set/$ID' => 'deleteCampaign',
|
||||||
];
|
];
|
||||||
@ -66,7 +66,7 @@ class CampaignAdmin extends LeftAndMain implements PermissionProvider {
|
|||||||
'itemListViewEndpoint' => $this->Link('set/:id/show'),
|
'itemListViewEndpoint' => $this->Link('set/:id/show'),
|
||||||
'publishEndpoint' => [
|
'publishEndpoint' => [
|
||||||
'url' => $this->Link('set/:id/publish'),
|
'url' => $this->Link('set/:id/publish'),
|
||||||
'method' => 'put'
|
'method' => 'post'
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -431,6 +431,12 @@ JSON;
|
|||||||
* @return SS_HTTPResponse
|
* @return SS_HTTPResponse
|
||||||
*/
|
*/
|
||||||
public function publishCampaign(SS_HTTPRequest $request) {
|
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');
|
$id = $request->param('ID');
|
||||||
if(!$id || !is_numeric($id)) {
|
if(!$id || !is_numeric($id)) {
|
||||||
return (new SS_HTTPResponse(json_encode(['status' => 'error']), 400))
|
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();
|
$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);
|
return Convert::raw2json($combinedClientConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,9 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
|||||||
this.addCampaign = this.addCampaign.bind(this);
|
this.addCampaign = this.addCampaign.bind(this);
|
||||||
this.createFn = this.createFn.bind(this);
|
this.createFn = this.createFn.bind(this);
|
||||||
this.publishApi = backend.createEndpointFetcher({
|
this.publishApi = backend.createEndpointFetcher({
|
||||||
url: this.props.config.publishEndpoint.url,
|
url: this.props.sectionConfig.publishEndpoint.url,
|
||||||
method: this.props.config.publishEndpoint.method,
|
method: this.props.sectionConfig.publishEndpoint.method,
|
||||||
|
defaultData: { SecurityID: this.props.config.SecurityID },
|
||||||
payloadSchema: {
|
payloadSchema: {
|
||||||
id: { urlReplacement: ':id', remove: true },
|
id: { urlReplacement: ':id', remove: true },
|
||||||
},
|
},
|
||||||
@ -27,7 +28,7 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
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);
|
this.props.actions.showCampaignView(ctx.params.id, ctx.params.view);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -55,7 +56,7 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
|||||||
* @return object
|
* @return object
|
||||||
*/
|
*/
|
||||||
renderIndexView() {
|
renderIndexView() {
|
||||||
const schemaUrl = this.props.config.forms.editForm.schemaUrl;
|
const schemaUrl = this.props.sectionConfig.forms.editForm.schemaUrl;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="cms-middle no-preview">
|
<div className="cms-middle no-preview">
|
||||||
@ -80,7 +81,7 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
|||||||
renderItemListView() {
|
renderItemListView() {
|
||||||
const props = {
|
const props = {
|
||||||
campaignId: this.props.campaignId,
|
campaignId: this.props.campaignId,
|
||||||
itemListViewEndpoint: this.props.config.itemListViewEndpoint,
|
itemListViewEndpoint: this.props.sectionConfig.itemListViewEndpoint,
|
||||||
publishApi: this.publishApi,
|
publishApi: this.publishApi,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,7 +106,7 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
|||||||
* @return object - Instanciated React component
|
* @return object - Instanciated React component
|
||||||
*/
|
*/
|
||||||
createFn(Component, props) {
|
createFn(Component, props) {
|
||||||
const campaignViewRoute = this.props.config.campaignViewRoute;
|
const campaignViewRoute = this.props.sectionConfig.campaignViewRoute;
|
||||||
|
|
||||||
if (props.component === 'GridField') {
|
if (props.component === 'GridField') {
|
||||||
const extendedProps = Object.assign({}, props, {
|
const extendedProps = Object.assign({}, props, {
|
||||||
@ -149,19 +150,23 @@ class CampaignAdminContainer extends SilverStripeComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CampaignAdminContainer.propTypes = {
|
CampaignAdminContainer.propTypes = {
|
||||||
config: React.PropTypes.shape({
|
sectionConfig: React.PropTypes.shape({
|
||||||
forms: React.PropTypes.shape({
|
forms: React.PropTypes.shape({
|
||||||
editForm: React.PropTypes.shape({
|
editForm: React.PropTypes.shape({
|
||||||
schemaUrl: React.PropTypes.string,
|
schemaUrl: React.PropTypes.string,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
config: React.PropTypes.shape({
|
||||||
|
SecurityID: React.PropTypes.string,
|
||||||
|
}),
|
||||||
sectionConfigKey: React.PropTypes.string.isRequired,
|
sectionConfigKey: React.PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
function mapStateToProps(state, ownProps) {
|
function mapStateToProps(state, ownProps) {
|
||||||
return {
|
return {
|
||||||
config: state.config.sections[ownProps.sectionConfigKey],
|
config: state.config,
|
||||||
|
sectionConfig: state.config.sections[ownProps.sectionConfigKey],
|
||||||
campaignId: state.campaign.campaignId,
|
campaignId: state.campaign.campaignId,
|
||||||
view: state.campaign.view,
|
view: state.campaign.view,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user