Is there a way to disable CSRF validation for some actions of the controller keeping it enabled for the other ones?
In my case I have several configurable Action classes, that are intended to be injected into controllers. I can't pass csrf validation token into the AJAX request because the thing I'm working with is external (made not by me) WYSIWYG plugin at the frontend. Yes, I can still disable csrf validation of the whole controller using these actions, but it may be insecure.
For the specific controller / actions you can disable CSRF validation like so:
use Yii;
...
Yii::$app->controller->enableCsrfValidation = false;
Or inside a controller:
$this->enableCsrfValidation = false;
Take a look at $enableCsrfValidation property of yii\web\Controller.
Update:
Here is some specification.
If you want to disable CSRF validation for individual action(s) you need to do it in beforeAction event handler because CSRF token is checked before action runs (in beforeAction of yii\web\Controller).
/**
* #inheritdoc
*/
public function beforeAction($action)
{
if ($action->id == 'my-method') {
$this->enableCsrfValidation = false;
}
return parent::beforeAction($action);
}
Official docs:
beforeAction()
For me this is what worked
public function beforeAction($action) {
if($action->id == 'my-action') {
Yii::$app->request->enableCsrfValidation = false;
}
return parent::beforeAction($action);
}
Put this inside your controller, just replace index with whatever action you want to disable csrf on.
public function beforeAction()
{
if ($this->action->id == 'index') {
$this->enableCsrfValidation = false;
}
return true;
}
i have tried this and it worked .
Go to the specific controller and write this at the top.
public $enableCsrfValidation = false;
Related
We have a template-based form that uses the various Angular Material controls (matInput, mat-select, etc). We want to create a 'read-only' type view for some users. My immediate thought was to simply check a user's privileges and then loop through all form controls and set them to disable if need be.
This appears to work for text input type controls but is not working for selects and checkboxes. Plus this grays-out the controls which isn't necessarily what we want.
Any ideas on how to best accomplish this? Perhaps somehow disable keyboard and mouse input within the form might be what we want but I have no idea how to go about this.
I think it is possible, but you will have to check all control types, for example MatInput exposes readonly property, it allows us to create simple directive which will switch readonly state for entire form:
import {Directive, ContentChildren, QueryList, AfterContentInit, Input} from '#angular/core';
import {NgModel} from '#angular/forms';
#Directive({
selector: 'form[readonly]'
})
export class FormReadonlyDirective implements AfterContentInit
{
#ContentChildren(NgModel)
public inputs:QueryList<NgModel>;
private controls:any[];
private _readonly:boolean = false;
public ngAfterContentInit():void
{
this.controls = this.getControls();
this.inputs.changes.subscribe(() =>
{
this.setReadonly(this.readonly);
});
this.setReadonly(this.readonly);
}
#Input()
public get readonly():boolean
{
return this._readonly;
}
public set readonly(value:boolean)
{
this._readonly = value != null && value !== false && `${value}` !== 'false';
this.setReadonly(value);
}
private setReadonly(value:boolean):void
{
if(this.controls != null)
{
this.controls.forEach(control =>
{
//todo: check
control.readonly = value;
});
}
}
private getControls():any[]
{
return this.inputs.map(control => control.valueAccessor);
}
}
Not tested, but you get the idea.
I am using bootstrap-tokenfield http://sliptree.github.io/bootstrap-tokenfield/ with jquery autocomplete. I want tagging with autocomplete content(from dropdown only). When user is inputting something and hit enter key it automatically creates tags. I dont want to allow this feature to the users. Is there any option/flag to set it? Any help would be appreciated. Thanks in advance.
Using listener tokenfield:createtoken you can validate the token before creating it.
Info: http://sliptree.github.io/bootstrap-tokenfield/#events
$('#tokenfield').on('tokenfield:createtoken', function (event) {
var exists = false;
$.each(yourSource, function(index, value) {
if (event.attrs.value === value) {
exists = true;
}
});
if(!exists) {
event.preventDefault(); //prevents creation of token
}
});
I have a RichFaces component that I want to render after an Ajax call which sets a JavaScript variable to either true or false.
When the variable is false, I don't want the panel to render. Is there any way to input the result of this variable (or any JS function call) in the rendered attribute of a component?
Richfaces renders components on the server side. So you have to pass your
parameter to server side. There are some ways to achieve this.
Create a hidden input on the page and link it to a flag in your bean. Something like,
class YourBean {
private boolean visible = false;
//getter,setter
}
On the page,
<h:selectBooleanCheckbox id="hiddeninput" style="visibility:hidden"
value="#{yourBean.visible}"/>
<rich:component id="compid" rendered="#{yourBean.visible}" />
<a:commandButton onclick="document.getElementById('hiddeninput').checked=true"
reRender="compid"/>
Or create two methods which sets flag to true or false.
class YourBean {
private boolean visible = false;
public void makeInvisible() {
visible = false;
}
public void makeVisible() {
visible = true;
}
}
On the page,
<rich:component id="compid" rendered="#{yourBean.visible}" />
<a:commandButton action="#{yourBean.makeInvisible()}" reRender="compid"/>
Option 1:
You can show/hide using JavaScript/jQuery from oncomplete attribute on ajax request.
Option 2 (better): you change a boolean property value in backend action's method, and use its value in rendered attribute.
RichFaces reRender can take an EL expression:
reRender="#{bean.componentsToUpdate}"
So, another option, you can decide in runtime (based on input) whether to render a particular component.
I started implementing MVVM for one of my Silverlight applications.
(I'm not using any toolkit).
My page contains a section with two combo boxes. Selecting an item in one of these combos triggers a search that updates a grid visible below the combos.
Each combo's selected item is bound to a property in my view model. The setter of these properties raise the INotifyPropertyChanged property change and updates the data bound to the grid automatically.
Everything was fine until I needed to add a reset button which purpose is to reset the search parameters i.e.: each combo box should not indicate any item and the grid should be empty.
If the reset function in the viewmodel updates the backing fields, the UI won't reflect the changes as RaisePropertyChanged will not be called.
If the reset function in the viewmodel updates the properties, the UI will reflect the changes but the grid will be updated twice: when reseting the first property to null and also for the second
Any help appreciated
/// <summary>Selected user.</summary>
public User SelectedUser
{
get { return _selectedUser; }
set
{
_selectedUser = value;
RaisePropertyChanged("SelectedUser");
UpdateProducts();
}
}
/// <summary>Selected product category.</summary>
public ProductCategory SelectedProductCategory
{
get { return _selectedProductCategory; }
set
{
_selectedProductCategory = value;
RaisePropertyChanged("SelectedProductCategory");
UpdateProducts();
}
}
// Reset option 1
public void Reset()
{
_selectedUser = null;
_selectedProductCategory = null;
_products = null;
}
// Reset option 2
public void Reset()
{
SelectedUser = null;
SelectedProductCategory = null;
// No need to update Products which has already been updated twice...
}
This is something that really urks me in many frameworks, WPF included. What you need is some concept of delaying the response to change notifications so that the user never sees intermediate states. However, you can't change the way WPF responds to your notifications, so the best you can do is to delay your notifications until "after the dust has settled". In your case, you will want to change both of the backing fields before any notifications are sent. Your reset method can encode this idea as follows:
public void Reset()
{
_selectedUser = null;
_selectedProductCategory = null;
_products = null;
RaisePropertyChanged("SelectedUser");
RaisePropertyChanged("SelectedProductCategory");
}
In my opinion, the way WPF synchronously updates the display in response to notifications of change is just plain wrong. Their DependencyProperty system gives them an opportunity to merely mark dependencies as dirty and perform recalculation at a later time.
I use the idea of marking as dirty and asynchronous recalculation as a general solution to the problem you've noted in this question and these days I could not imagine programming without it. It's a shame that more frameworks do not work this way.
You can raise a single PropertyChanged event for all properties after you updated the backing fields:
RaisePropertyChanged(String.Empty);
If you use the backing Fields you would have to call
RaisePropertyChanged("SelectedUser");
RaisePropertyChanged("SelectedProductCategory");
in the Reset() method.
I am binding to a SiteMapDataSource (hierarchical).
I am overriding PerformDataBinding to grab the data from the datasource.
Everything works great on page load. But when I perform a postback anywhere on the page, the PerformDataBinding method does not get called, and in effect, not rendering any menu items (PerformDataBinding wasn't called).
No clue why this is happening, but I have a fix for it. Amazingly, every example of a HierarchicalDataBoundControl I could find (even from msdn) was doing this. However, here is a workaround.
private bool dataBound = false;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (this.Page.IsPostBack)
{
this.DataBound += delegate { dataBound = true; };
this.Page.Load += delegate { if (!dataBound) DataBind(); };
}
}