How to show records created by that users on index page in yii2? - yii2-basic-app

I am using yii2 basic and implemented RBAC.
I have two roles admin and fieldofficer and created permissions and rules and assigned users. Now when admin logs in, on index page he should be able to see all records as well as his created records in grid.
Whereas when fieldofficer logs in, he should be able to see only his created records in index page.
How to accomplish this?

You need to pre-load the user's id into the Search Model. If security is an issue (ie: you don't want other user's to be able to bypass this no matter what), then you will need to detect if the user's id has been passed to the query, and force it back to the user you want (ie: the one logged in). In most situations, your going to need the extra security, and should.
Replace UserPlan with whatever your model is. Since you didn't post code, I have no clue what it is :)
Before: Original Index Example (as generated by Gii):
public function actionIndex()
{
$searchModel = new UserPlanSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
After: Locked to the currently logged in user:
public function actionIndex()
{
$searchModel = new UserPlanSearch();
$searchModel->user_id = Yii::$app->user->id;
// override (so users can't bypass)
$queryParams = Yii::$app->request->queryParams;
if ( isset($queryParams['UserPlan']['user_id']) ) {
$queryParams['UserPlan']['user_id'] = Yii::$app->user->id;
}
$dataProvider = $searchModel->search($queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
Also, you should post code when posting to StackOverflow unless you want a bunch of down votes. Just asking questions, is against the rules. They want to see what you have tried so far, and some code to go by.

Related

Is it possible to add a role to a user with alanning:roles in meteor from an template event?

I am fairly new to Meteor and have been having real trouble with this issue.
I would like to have a select element which updates the users role (once logged in) depending on the option selected. I'm storing the value of the option as a variable when the select is changed and trying to take this value as the name of the role to add to the user.
When I run my app and change the select, the role seems to pop up for a second (viewed in Mongol) before disappearing again. I created a small test to display an alert of the role for the user, which shows up containing the name of the role but once you OK it, the role has disappeared. Am I missing something here?
Here is my template containing the select element...
<template name="select">
<select id="select">
<option value="working">Looking for work</option>
<option value="hiring">Hiring</option>
</select>
</template>
And here is the client side code for the change event
Template.select.events({
'change #select': function (event) {
//remove any current roles added to the user as it will be either
//one or the other
Roles.removeUsersFromRoles( Meteor.userId(), 'working', 'hiring' );
//add a role to the current user with the value from select box
var value = $(event.target).val();
Roles.addUsersToRoles( Meteor.user(), value );
//each of these alerts displays correctly depending on the select
//value
var test = Roles.userIsInRole( Meteor.user(), 'hiring' ); // true
if (test===true){
alert('in hiring role');
}
var test2 = Roles.userIsInRole( Meteor.user(), 'working' ); // true
if (test2===true){
alert('in working role');
}
// either working or hiring
alert(Roles.getRolesForUser(Meteor.userId()));
// alert displays count of 1 when you select 'hiring'
alert(Roles.getUsersInRole('hiring').count());
}
});
Any help would be much appreciated, have been searching through the documentation and online for several days to no avail. Many thanks :)
You try to add roles in your client. However, the client reflects only the data from the server's Roles collection.
You need therefore to change your code to a server side method, that
a) checks wether the current user is permitted to change roles (warning here, potential security threats when not checking permissions)
b) checks, wether the targeted user exists
c) sets the roles for the given userId
There is a good example in the documentation on how to do that. This is a slightly modified version of it:
Meteor.methods({
'updateRoles'({userId, roles, group}) {
check(userId, String);
check(roles, [String]);
check(group, String);
// a) check permission
if (!this.userId || !Meteor.users.findOne(this.userId) || !Roles.userIsInRole(this.userId, 'update-roles', 'lifted-users'))
throw new Meteor.Error('403', 'forbidden', 'you have no permission to change roles');
// b) check target user
if (!Meteor.users.findOne(userId))
throw new Meteor.Error('404', 'user not found');
// c) update user's roles
Roles.setUserRoles(userId, roles, group);
return true;
}
});
This method assumes, that there is a special role/group combination for users, that are allowed to change roles. This should be only a very few people, like admins.
Also note, that this method sets the user roles by using Roles.setUserRoles. If you want to extend the roles you need to use Roles.addUserToRoles.
You can then call this method from your client like every Meteor method:
Template.select.events({
'change #select': function (event) {
// get value from select box
var roles = [$(event.target).val()];
// TODO create a second select for the group
var group = 'defaultUsers'
var userId = Meteor.userId();
Meteor.call('updateRoles', { userId, roles, group }, (err, res) => {
// handle err / res
console.log(Roles.userIsInRole(userId, roles, group)); // should return true
});
}
});
Note, that Roles on the client is a collection which is immediately subscribed to. Changes are reflected reactively. If you do not see the changes immediately

Interaction between two forms in a single controller

I'm trying to work with two forms in a single controller in Symfony2. The page is displaying a list of e-mail addresses with checkboxes to select them.
The first form is a research form and the second is used to remove e-mail addresses. There is also a pagination in my page.
My problem is that I can't remove an e-mail address with a research when the e-mail address is not displayed in the first page.
public function emailsAction(Request $request, $paginationParams)
{
$searchForm = $this->createForm(new SearchFormType(), null, array());
$searchForm->handleRequest($request);
if ($searchForm->isValid()) {
// FETCH E-MAILS WITH SEARCH
} else{
// FETCH E-MAILS WITHOUT SEARCH
}
// here I slice the result depending on the pagination params
$removeForm = $this->createForm(new RemoveFormType(), null, array(
'emails' => $emails
));
$removeForm->handleRequest($request);
if ($removeForm->isValid())
{
$formData = $removeForm->getData();
// here I remove the e-mails
}
...
$params['remove_form'] = $manageSubscribersForm->createView();
$params['search_form'] = $searchAbonneActuForm->createView();
return $this->renderView('my_template.html.twig', $params);
}
If I understand it correctly, the problem is that my removeForm is created with the spliced array and without the search applied when handling the removeForm.
When I search for a name, say johnsmith, it displays me on page 1, one result which is johnsmith#email.com.
If johnsmith#email.com is on page 2 without search, the removeForm handling my request is created with a spliced array not containing johnsmith, so the removeForm is not considered valid.
How should I do to create my removeForm, taking account of the search done before when submitting the removeForm? Or maybe I'm doing this wrong ?
I'm not a native english speaker so if anything is not clear, feel free to ask.
You can use a hidden field with the current page index, that will help you make your search again.
Or you can use an event listener to modify the form field before the submission for the validation.

Autopublish removed but why can I still retrieve data from db?

I have a simple Meteor/MongoDB project using the 'roles' package where I optain data from the db to the client. The roles package seems to work fine and the browser shows the right data depending on who is logged in, just like it should do. Then when running 'meteor remove autopublish' in the terminal inside my applications directory I get 'autopublish removed' just like it should. Still I can retrieve data from the server just as before(!?)
I have all of my db calls from the client/client.js.
The server/server.js does nothing (I do have publish/subscribe code but uncomment for now) and same goes for the common js file in main directory.
How can this be? Am I perhaps retrieving data from minimongo somehow? I have also removed insecure even if I don't think that matters in this case(?) Thanks in advance.
EDIT: Here's the code:
client.js:
//when uncomment the subscribe's you should not get access to the server/db, but 'data' that holds all the inlogg info still shows. The 'movies' on the other hand doesn't, just like it shouldn't.
//Meteor.subscribe('data');
//Meteor.subscribe('movies');
/*############# Get User Data ###############*/
Template.userLoggedIn.id = function () {
return Meteor.userId();
};
Template.userLoggedIn.email = function () {
var email = Meteor.users.findOne({_id: Meteor.userId()});
return email.emails[0].address;
};
Template.userLoggedIn.profile = function () {
var profile = Meteor.users.findOne({_id: Meteor.userId()});
return profile.profile.name;
};
Template.userLoggedIn.role = function () {
var role = Meteor.users.findOne({_id: Meteor.userId()});
return role.roles[0];
};
/*############# ###############*/
Template.movies.movies = function() {
var movies = Movies.find().fetch();
return movies;
}
server.js:
Meteor.publish('data', function () {
return Meteor.users.find();
});
Meteor.publish('movies', function() {
return Movies.find();
});
Thanks for providing the code - I see how this could be confusing. The users section of the docs should be written to explicitly say this, but what's happening is the current user is always published. So even if you don't write a publish function for users (or your have your subscribe commented out), you should expect to see the current user on the client. Because your template code only looks for Meteor.userId(), I would expect it to still work.
Assuming you have other users in the database, you can quickly check that they are not being published by running: Meteor.users.find().count() in your browser console. If it returns 1 then you are only publishing the current user (or 0 if you are logged out).

Field validations in sugarcrm

I just started using SugarCRM CE for the first time (Version 6.5.15 (Build 1083)). I'm quite impressed with the ease of use when adding new fields or modules, but there's one quite indispensable thing that seems to be missing: Validation of user input.
I would for example like to check a lot of things:
Check if a emailadres has a valid format, using some regular expression
Check if a postalcode exists (maybe do a webswervice call to validate it)
Do a calculation to see if a citizen service number is valid
etc.
The only thing I seem to be able to do in studio is make a field required or not, there doesn't seem to be any standard way to execute a validation on a field.
All I can find when I google on it is lots of ways to hack into the source code, like this one: http://phpbugs.wordpress.com/2010/01/22/sugarcrm-adding-javascript-validation-on-form-submit/ And even then I don't find any examples that actually do a validation.
Am I just missing something? Or is editing source code the only way to add this?
I don't think the "standard" validations are available in the CE edition.
What surprises me is that you can't define a validation somewhere and attach it to a field. I kind of expected this, since the rest of the system is very well structured (modules, packages, etc..)
I now for instance created a 11-check, this is a very specific check for a dutch bank account number. to get this to work, I did the following (based upon examples I found googling around):
I added the bank account to contacts in studio and after that edited \custom\modules\Contacts\metadata\editviewdefs.php
I added the following snippets:
'includes'=> array(
array('file'=>'custom/modules/Contacts/customJavascript.js')),
array (
0 =>
array(
'customCode' =>
'<input title="Save [Alt+S]" accessKey="S" onclick="this.form.action.value=\'Save\'; return check_custom_data();" type="submit" name="button" value="'.$GLOBALS['app_strings']['LBL_SAVE_BUTTON_LABEL']>',
),
1 =>
array(
'customCode' =>
'<input title="Cancel [Alt+X]" accessKey="X" onclick="this.form.action.value=\'index\'; this.form.module.value=\''.$module_name.'\'; this.form.record.value=\'\';" type="submit" name="button" value="'.$GLOBALS['app_strings']['LBL_CANCEL_BUTTON_LABEL'].'">'
)
),
And in customJavascript.js i placed this code:
function check_custom_data()
{
if (!eleven_check(document.getElementById("bankaccount_c").value)){
alert ('Bank account not valid');
return false;
} else {
return check_form('EditView');
}
function eleven_check(bankaccount) {
bankaccount=bankaccount.replace(/\D/, "");
charcount=bankaccount.length;
var som=0;
for (i=1; i<10; i++) {
getal=bankaccount.charAt(i-1);
som+=getal*(10-i);
}
if (som % 11==0 && charcount==9) {
return true
} else {
return false
}
}
}
This check now works the way I want it to work, but I'm wondering if this is the best way to add a validation. this way of adding a validation doesn't however accommodate PHP validations, for instance, if I want to validate against some data in the database for one or another reason, I would have to use ajax calls to get that done.
Email validation is in the pro edition, I had assumed it was in CE as well but I'm not 100% sure.
The other 2 are a lot more specific - postcode validation would depend upon your country so would be difficult to roll out. For these you will need to write your own custom validation.
I know its late, but maybe still someone needs this.
You can just add your custom javascript validation as a callback in your vardefs like this:
'validation' =>
array (
'type' => 'callback',
'callback' => 'function(formname,nameIndex){if($("#" + nameIndex).val()!=999){add_error_style(formname,nameIndex,"Only 999 is allowed!"); return false;}; return true;}',
),
I documented it here as its not well documented elsewhere:
https://gunnicom.wordpress.com/2015/09/21/suitecrm-sugarcrm-6-5-add-custom-javascript-field-validation/
You can add custom validation code to the following file: ./custom/modules/.../clients/base/views/record/record.js
There you can add validation code. In this example, I will validate if the phone_number is not empty when an accounts has a customer-type:
EXAMPLE CODE IN RECORD.JS:
({
extendsFrom: 'RecordView',
initialize: function (options) {
app.view.invokeParent(this, {type: 'view', name: 'record', method: 'initialize', args:[options]});
//add validation
this.model.addValidationTask('check_account_type', _.bind(this._doValidateCheckType, this));
},
_doValidateCheckType: function(fields, errors, callback) {
//validate requirements
if (this.model.get('account_type') == 'Customer' && _.isEmpty(this.model.get('phone_office')))
{
errors['phone_office'] = errors['phone_office'] || {};
errors['phone_office'].required = true;
}
callback(null, fields, errors);
}
})
Don't forget to repair en rebuild!
The full documentation can be found here

Cakephp 2.1 Facebook Connect And Auth

I'm using the below plugin in my app to get facebook connect working with auth.
https://github.com/webtechnick/CakePHP-Facebook-Plugin
The thing is I want to save user data into users table manually.
So I'm trying like this
public function beforeFacebookSave(){
//$this->Auth->autoRedirect = false;
debug($this->Connect->user('email'));
$this->Connect->authUser['User']['email'] = $this->Connect->user('email');
$this->Connect->authUser['User']['username'] = $this->Connect->user('username');
//Must return true or will not save.
$this->redirect(array('controller' => 'users', 'action' => 'beforefbsave', '?' => array('param1' => $this->Connect->user('email'))));
//return true;
}
The redirect is getting into a loop and getting an error
The page isn't redirecting properly
Is this a proper way or have follow some other method to get this done?
there is a documentation on page:
https://github.com/webtechnick/CakePHP-Facebook-Plugin
beforeFacebookSave handle the user to save into the users table. If returned false, creation is haulted.
//Add an email field to be saved along with creation.
function beforeFacebookSave(){
$this->Connect->authUser['User']['email'] = $this->Connect->user('email');
return true; //Must return true or will not save.
}
so if i were you i' d look on the next section:
beforeFacebookLogin Handle the user before logging the user into Auth.
function beforeFacebookLogin($user){
//Logic to happen before a facebook login
}
and instead of redirection use direct functions from your model.