Need help for Logout user if browser close - yii2

I try many types of code Like Using javascript,jquery but not possible
Need your help
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "\o/";
e = e || window.event;
var y = e.pageY || e.clientY;
if(y < 0){
createCookie("Window closed","YES",1);
} else{
createCookie("Window refress","YES",1);
}
});
in YIi2 Main.php
'enableAutoLogin' => false,
All thinks not working... :-(
Please check Image

You can see maximum login time with disable auto login to force logout user:
'user' => [
'enableAutoLogin' => false,
'authTimeout' => 300,
],
'session' => [
'timeout' => 300,
],
see authTimeout-detail
with this config, when user be in page and do nothing after 5 min(300 sec), the login session has been expired, and when user close his/her browser and did not open it before 5 min, the session will expired!
Note: Do not change autoRenewCookie to false
Or try this:
$(window).unload( function () {
jQuery.ajax({url:"logout_url", async:false})
} );

Related

#MetaMask / detect-provider: handle Accounts Changed

I'm using #metamask/detect-provider, when I use the second account of my Metamask wallet, this second account is not considered in execution. This is the first account that is always taken in the execution
accountsChanged event will be emitted whenever you change the account. So write a callback to handle it. I just set it in a state.
useEffect(() => {
// you have to write code to detect provider. [#metamask/detect-provider][1]
// if there is no accound set it null as default
provider &&
provider.on("accountsChanged", () => setAccount(accounts[0] ?? null));
}, []);
or
useEffect(() => {
window.ethereum &&
window.ethereum.on("accountsChanged", () => setAccount(accounts[0] ?? null));
}, []);

Dropdown in list data

This is my code:
[
'attribute' => 'status',
'value' => function ($model) {
return Html::dropDownList('status', ['10' => 'Active', '20' => 'Deactive']);
},
],
I just want dropdown in status column. If record is active or deactive it will be selected.
You need to use 'format' => 'raw' for the column options and your definition for the dropDownList() is wrong you need to have the selection string as the second parameter and the dropdown options as the third parameter. Change your code to below:
[
'attribute' => 'status',
'format' => 'raw',
'value' => function ($model) {
return Html::dropDownList('status', $model->status, ['10' => 'Active', '20' => 'Deactive']);
},
],
EDIT
You didnt had in the initial requirements that you waned to update the status too when the drop down is changed. You can bind ajax call to the drop-down.
Add the following javascript on top of your view where you are initializing the GridView.
NOTE: Change the url:'controller/update-status?id'+id in the ajax call to the relative controller where you want to update the status for the row, but dont remove the id
$js = <<<JS
$(document).on('ready pjax:success',function(){
$(".switch-status").on('change',function(){
var data={};
data[$(this).attr("name")]=$(this).val();
var id=$(this).closest("tr").data('key');
$.ajax({
method:'post',
url:'/controller/update-status?id='+id,
data:data,
success:function(data){
if(!data.success){
alert(data.message);
}else{
alert("Status updated.");
}
},
error:function(jqXHR, textStatus, errorThrown ){
alert(errorThrown);
}
});
});
});
JS;
$this->registerJs($js, yii\web\View::POS_END);
Then inside your GridView column for status change the dropdown to the following
return Html::dropDownList(Html::getInputName($model, 'active'), $model->active, [10 => 'Active', 20 => 'Deactive'], ['class' => 'switch-status']);
And the go to your controller and add the action code for updating the status
Note: Change the Model in the first line $model = Model::findOne($id); name with the respective model you are using.
public function actionUpdateStatus($id) {
$model = Affiliate::findOne($id);
$app = Yii::$app;
$request = $app->request;
if($request->IsAjax && $request->isPost) {
Yii::$app->response->format = Response::FORMAT_JSON;
if($model->load($request->post()) && $model->save()) {
return ['success' => true];
} else {
return [
'success' => false,
'message' => implode('<br />', ArrayHelper::getColumn($model->errors, '0'))
];
}
}
}
Use content property to render HTML elements. For example:
[
'attribute' => 'status',
'content' => function ($model) {
return Html::dropDownList('status', $model->status, ['10' => 'Active', '20' => 'Deactive']);
},
],

fetch data from url with $.get() give me 404- url manager

i have this function in index.php view file.(see it below)
as you see after click button it get data with get method
if my url be http://example.com/admin/site-developer/index
after click button in console i get error
GET http://example.com/admin/site-developer/site-developer/get-note?developer_id=7 404 (Not Found)
but with url without index at end it work correctly
http://example.com/admin/site-developer
if change $.(get) url to
$.get("get-note",{developer_id: Id},function(data) {}
after click http://example.com/admin/site-developer
give me
GET http://example.com/admin/get-note?developer_id=7 404 (Not Found)
error but if i add index to end of url it works corrctly
this is complete function code:
$('#noteBtn').on('click',function(e) {
$.get("site-developer/get-note",{developer_id: Id},function(data) {
var data = JSON.parse(data);
var elm = "";
$.each( data, function( i, val ) {
elm = elm+'<div id="id-'+i+'"><div>'+val.note+'</div><div>'+val.created_at+'</div></div>';
});
$("#developer_note").html(elm);
})
;})
i think maybe its url manager problem??
here is my url manager config
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
'/'=>'site/index',
'login' => 'site/login',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<id:\d+>' => '<controller>/view',
],
],
action getnote
public function actionGetNote($developer_id)
{
$model = DevelopersNote::findAll(['developer_id' => $developer_id]);
echo Json::encode($model);
}
Seems that you url is not build properly
Assuming you javascript code is inside a php file
try use UrlHelper
<?php
use yii\helpers\Url;
?>
$('#noteBtn').on('click',function(e) {
<?php echo 'var myUrl = "' . Url::to(['site-developer/get-note']) . '";
' ; ?>
$.get(myUrl ,{developer_id: Id},function(data) {
var data = JSON.parse(data);
var elm = "";
$.each( data, function( i, val ) {
elm = elm+'<div id="id-'+i+'"><div>'+val.note+'</div><div>'+val.created_at+'</div></div>';
});
$("#developer_note").html(elm);
})
;})
for check your problem with the code above try use this way
$('#noteBtn').on('click',function(e) {
var myUrl "http://example.com/admin/site-developer/get-note";
$.get(myUrl ,{developer_id: Id},function(data) {
var data = JSON.parse(data);
var elm = "";
$.each( data, function( i, val ) {
elm = elm+'<div id="id-'+i+'"><div>'+val.note+'</div><div>'+val.created_at+'</div></div>';
});
$("#developer_note").html(elm);
})
;})

Kendo UI Grid, setting page to 1 without double postback

I have the following code on a page.
The problem is that when the "MainSearchSubmit" button is clicked the method "RefreshGrid()" is resulting in 2 subsequent ajax calls to the server. I found this is because the call to "datasource.read()" and "datasource.page(1)" are both posting back to the server (they are both running the read() method of the dataSource).
I still need to set the grid page to 1 when the search button is clicked because otherwise someone can be on page 3, then click the search button, get the updated results, but still be on page 3. They need to be reset to page 1 when the click the search button.
Also I still need to run the read() because otherwise the updated parameters are not passed and the data is not refreshed.
I've found similar posts, some with people suggesting using the .query() method. I tried that (code commented out in "RefreshGrid()" method), but that was also resulting in 2 posts to the server.
Any ideas on how I can fix this?
Code:
<script>
$(document).ready(InitializeNDCMapping);
function InitializeMainMapping() {
$("#MainSearchSubmit").click(function (e) {
RefreshGrid();
e.preventDefault();
});
}
function RefreshGrid() {
$("#MainListGrid").data("kendoGrid").dataSource.read();
$("#MainListGrid").data("kendoGrid").dataSource.page(1);
//Defunct code
//var dataSource1 = $("#NDCListGrid").data("kendoGrid").dataSource;
//dataSource.query({
// read: dataSource1.read(),
// page: dataSource1.Page(1),
// pagesize: dataSource1.PageSize(25)
//});
}
</script>
<div class="search-buttons">
<input type="submit" value="Search" id="MainSearchSubmit" />
<input type="button" value="Reset" onclick="ResetMainSearch()" />
</div>
<div>
#(Html.Kendo().Grid<BackOffice.ViewModels.NDCItem>()
.Name("MainListGrid")
.Filterable()
.Pageable(p => p.PageSizes(new int[] { 25, 50, 100 }).Input(true)
.Messages(m=>m.Empty("No Main-Ingredient found")).Numeric(false))
.Sortable()
.Navigatable()
.Selectable(selectable => selectable.Mode(GridSelectionMode.Single))
.Columns(columns =>
{
columns.Bound(l => l.NDCCode).Title("NDC Code").Width("5%")
.ClientTemplate(#Html.DialogFormLink("#=NDCCode#", Url.Action("NDCMappingEdit", new { NDCCode = "#=NDCCode#", mainMultumDrugCode = "#=MainMultumDrugCode#", drugId = "#=DrugId#", isMapped = "#=IsMapped#" }), "NDC Mapping", "", "", "NDCDialogLink", "1100", "600", "").ToHtmlString());
columns.Bound(l => l.Name).Title("Generic Name").Width("15%");
columns.Bound(l => l.MainCode).Hidden();
columns.Bound(l => l.MainId).Hidden();
columns.Bound(l => l.MainDescription).Title("Main Description").Width("15%");
columns.Bound(l => l.MainIngredientCode).Hidden();
columns.Bound(l => l.MainIngredient).Title("Main Ingredient").Width("15%");
columns.Bound(l => l.MainNumAmount).Title("Main Qty").Width("5%");
columns.Bound(l => l.MainNum).Title("Main Unit").Width("5%");
columns.Bound(l => l.MainDenomAmount).Title("Main Denom").Width("5%");
columns.Bound(l => l.MainDenom).Title("Main Denom Unit").Width("5%");
columns.Bound(l => l.IsMapped).Title("Mapped").Width("5%").Filterable(false).Sortable(false)
.ClientTemplate("<input type='checkbox' name='selected_#=MainCode#' class='chkbx select'" + "#= IsMapped ? 'checked' : ''#" + " />")
.HtmlAttributes(new { #class = "center", #onclick = "return false" })
.HeaderHtmlAttributes(new { #class = "center" });
})
.AutoBind(false)
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.Read(read => read.Action("MainList_Read", "Drug").Data("getRouteParams"))
.Model(model =>
{
model.Field(f => f.MainCode).Editable(false);
model.Field(f => f.MainName).Editable(false);
model.Field(f => f.MainDCCode).Editable(false);
model.Field(f => f.MainId).Editable(false);
model.Field(f => f.MainDescription).Editable(false);
model.Field(f => f.MainIngredientCode).Editable(false);
model.Field(f => f.MainIngredient).Editable(false);
model.Field(f => f.MainNumAmount).Editable(false);
model.Field(f => f.MainNum).Editable(false);
model.Field(f => f.MainDenomAmount).Editable(false);
model.Field(f => f.MainDenom).Editable(false);
model.Field(f => f.IsMapped).Editable(false);
})
.PageSize(25)
.Events(events => events.Error("MainRead_Error"))
)
)
</div>
In the past, when I had similar problems, it was almost always because the click handler was registered twice and even though the user clicked the button once, the handler executed twice.
Where do you call InitializeMainMapping()? Also, I am not sure if this is a copy and paste error, but the InitializeMainMapping() is missing a closing }. Are you getting any javascript errors when the user clicks on the button?
Just a few ideas to get you started.
I was able to find the solution. If the page is already set to 1 and you run...
grid.dataSource.page(1);
This results in a read. Otherwise if the page is not yet set to 1 and you run the code above it doesn't result in a read. So the solution to the issue is below.
if (grid.dataSource.page() != 1) {
grid.dataSource.page(1);
}
grid.dataSource.read( {parameter: "value"} );
Found this solution here:
KendoUI: resetting grid data to first page after button click

Prevent show data from another user

How to prevent all detailView show data from another user ??
For example, this happens when you type an product ID of another user in the URL. The detailView shows the details of the product normally, however belongs to another User, and may even change it and delete it.
You can do something like this in the controller if you don't want to use RBAC :
protected function findModel($id)
{
//Check if the author is the current user
if (($model = Product::findOne($id)) !== null && $model->author_id==Yii::$app->user->id) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
Like this users which are not the author can't view, update or delete the product.
http://www.yiiframework.com/forum/index.php/topic/61915-prevent-show-data-from-another-user/page__view__findpost__p__274644
Several options:
1) simplest one, in the controller before showing the view check that the current user can see the product. If he cannot redirect him (by throwing an error) to a 404 page (or whatever error you want to show).
2) use RBAC to set up roles and what those roles can do. This is the most professional option
3) you may be able to modify the accessfilter to do this too too
If you need to ask how to do this go with option 1.
If you want option 2 or 3 start by reading this http://www.yiiframework.com/doc-2.0/guide-security-authorization.html
An example to what Mihai have suggested.
public function behaviors()
{
return [
'accessControl' => [
'class' => \yii\filters\AccessControl::className(),
'rules' => [
[
'actions' => ['view'],
'allow' => true,
'matchCallback' => function () {
$request = \Yii::$app->request;
$user = \Yii::$app->user->identity;
$product = Product::findOne($request->get('id'));
if ($user && $product->owner_id == $user->id) {
return true;
}
return false;
}
],
[
'allow' => false,
'roles' => ['*'],
],
],
]
];
}