Changes to the User Permissions Not saving - drupal

I am use drupal 6.
it seems like permission page can not save too many settings.
I have try to save permission setting, but it is just not saved into DB.
I have found out this is due to "too many fields". (use content permission module).
if i uncheck some fields, and then checking lesser fields, permission will be saved.
for example, if I am unchecking 2 check boxes, then checking one check box, permission will be saved.
does any one know which function the permission page used to insert result into db?
my php memory limit is 256M.

You need to adjust the max_input_vars in php.ini. The usual default is 1000, but with a lot of modules, the Drupal permissions page easily eclipses this. Just add another zero and make it 10000 if you have access to php.ini and restart apache. The location of the php.ini file depends on your server configuration.
I had the same issue, with no errors in the error log, and this fixed it for me.

There is a good explanation of the issue that you are having here: http://2bits.com/drupal/drupal-not-saving-admin-pages-large-number-input-fields.html

Change the size of the db table? Sounds like its truncating.

The function that saves the permissions in the database is user_admin_perm_submit().
function user_admin_perm_submit($form, &$form_state) {
// Save permissions:
$result = db_query('SELECT * FROM {role}');
while ($role = db_fetch_object($result)) {
if (isset($form_state['values'][$role->rid])) {
// Delete, so if we clear every checkbox we reset that role;
// otherwise permissions are active and denied everywhere.
db_query('DELETE FROM {permission} WHERE rid = %d', $role->rid);
$form_state['values'][$role->rid] = array_filter($form_state['values'][$role->rid]);
if (count($form_state['values'][$role->rid])) {
db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $role->rid, implode(', ', array_keys($form_state['values'][$role->rid])));
}
}
}
drupal_set_message(t('The changes have been saved.'));
// Clear the cached pages
cache_clear_all();
}

Related

List of permissions for Drupal8 routing file

I'm working on custom Drupal8 module. My module uses this routing file:
kalvis.routing.yml
kalvis.content:
path: '/kalvis/{from}/{to}'
defaults:
_controller: '\Drupal\kalvis\Controller\kalvisController::content'
_title: ''
requirements:
_permission: 'access content'
What does _permission part stand for and where can I find a list of all possible values for this parameter?(in tut's I've watched were used only access content and access administrative content but I suppose there is a lot more of them)
PS: I'm using Drupal 8 beta 10 installed on WAMP
If you want to see a list of all permission, the code below should work. work. If you are coding your own module you can define your own permissions and test if a user has a role with that permission.
function my_module_page_attachments_alter(array &$attachments) {
$perms = array_keys(\Drupal::service('user.permissions')->getPermissions());
}
To answer the question what is the _permission part of the routing structure. Here is a quote from the drupal docs about what it does.
_permission: A permission string (e.g., _permission: 'access content'). You can specify multiple permissions by separating them with ',' (comma) (e.g., _permission: 'access content,access user profiles') for AND logic or '+' (plus) for OR logic (e.g., _permission: 'access content+access user profiles' means a visitor needs either the access content permission or the access user profiles permission to view the page. Having both is fine, too.). Module-specific permission strings can be defined in my_module_name.permissions.yml. See hook_permission() replaced with permissions defined in a my_module_name.permissions.yml file for details.
source: https://www.drupal.org/docs/drupal-apis/routing-system/structure-of-routes
To put it simply this restricts access to this route by only allowing users with the specified permission(s) to access it. To use it you need to know the system name of the permission(s) you want to use to restrict access. Then you just place then as a string behind this paramerter. Like in the quote above. You can choose to use multiple permissions by separating them with , for AND logic or + for OR logic. Permissions system names are allowed to have spaces in them and frequently do.
I don't think there is any way to directly see it in ui if you are talking about the system names of the permissions. You can ofcource see all permissions on www.site.com/admin/people/permissions. If you are in a hurry and/or looking for a specific permission you can always look through the module.permissions.yml file of the module this permission is defined in.
If you do want to see all permissions you can make your own list of all the system names.
You can use the PermissionHandler service from the core module.
This does the following gets all yaml's and creates a list.
You would call this by calling Drupal::service('user.permissions')->getPermissions() (https://api.drupal.org/api/drupal/core%21modules%21user%21src%21PermissionHandler.php/function/PermissionHandler%3A%3AgetPermissions/8.2.x)
You can use or try to write similar code to the functionality of the user_role_permissions function from the user.module file in drupal core. It looks like this:
function user_role_permissions(array $roles) {
if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
return _user_role_permissions_update($roles);
}
$entities = Role::loadMultiple($roles);
$role_permissions = array();
foreach ($roles as $rid) {
$role_permissions[$rid] = isset($entities[$rid]) ? $entities[$rid]
->getPermissions() : array();
}
return $role_permissions;
}
This code as you can see just loads all the role entities with loadMultiple (although technically you should use the entitytypemanager to load the entities whenever possible like $entities = \Drupal::entityTypeManager()->getStorage($entity_type)->loadMultiple([1, 2, 3]); for more information see the drupal entity api (https://www.drupal.org/docs/drupal-apis/entity-api/working-with-the-entity-api)).
After loading all the roles it makes a list of all permissions.
Source information below. This should stay up to date because drupal keeps their documentation versioned. But because comments suggested it I figured I might as well write it out to save you some clicks.
Original drupal documentation.
https://api.drupal.org/api/drupal/core!modules!user!user.module/function/user_role_permissions/8.2.x
Hope this helps! :)
You can confirm in the page '/admin/people/permissions'.
A quick and dirty way to see them is to create a View with a Page display. Then in the 'Access' section, ensure 'Permission' is selected and open up the options as if you were going to choose a different permission.
You can now inspect the HTML of the <select> element, the Ids of each option is the correct name for each permission:

Laravel/blade caching css files

I am working on Nginx server, with PHP-FPM. I installed Laravel 4.1 and bootstrap v3.1.1., and here is the problem. For the last 30 minutes, I have been trying to change a css rule that I first declared to check boostrap.
.jumbotron{
background: red;
}
The first time it worked. The jumbotron container was red. So, I removed that css value and started working, but still no matter which browse I use, the container is red. I even checked the css file through the Google Chromes inspection tool, and it is showing me that first value when jumbotron had a background:red. I deleted the css file and renamed it and add new styles, I configured chrome not to cache pages. But Still the same value. I'm convinced now, that Laravel has kept a cache of the first style declaration.
Is there any way to disable this at all?
General explanation
When you access a Laravel Blade view, it will generate it to a temporary file so it doesn't have to process the Blade syntax every time you access to a view. These files are stored in app/storage/view with a filename that is the MD5 hash of the file path.
Usually when you change a view, Laravel regenerate these files automatically at the next view access and everything goes on. This is done by comparing the modification times of the generated file and the view's source file through the filemtime() function. Probably in your case there was a problem and the temporary file wasn't regenerated. In this case, you have to delete these files, so they can be regenerated. It doesn't harm anything, because they are autogenerated from your views and can be regenerated anytime. They are only for cache purposes.
Normally, they should be refreshed automatically, but you can delete these files anytime if they get stuck and you have problems like these, but as I said these should be just rare exceptions.
Code break down
All the following codes are from laravel/framerok/src/Illuminate/View/. I added some extra comments to the originals.
Get view
Starting from Engines/CompilerEngine.php we have the main code we need to understand the mechanics.
public function get($path, array $data = array())
{
// Push the path to the stack of the last compiled templates.
$this->lastCompiled[] = $path;
// If this given view has expired, which means it has simply been edited since
// it was last compiled, we will re-compile the views so we can evaluate a
// fresh copy of the view. We'll pass the compiler the path of the view.
if ($this->compiler->isExpired($path))
{
$this->compiler->compile($path);
}
// Return the MD5 hash of the path concatenated
// to the app's view storage folder path.
$compiled = $this->compiler->getCompiledPath($path);
// Once we have the path to the compiled file, we will evaluate the paths with
// typical PHP just like any other templates. We also keep a stack of views
// which have been rendered for right exception messages to be generated.
$results = $this->evaluatePath($compiled, $data);
// Remove last compiled path.
array_pop($this->lastCompiled);
return $results;
}
Check if regeneration required
This will be done in Compilers/Compiler.php. This is an important function. Depending on the result it will be decided whether the view should be recompiled. If this returns false instead of true that can be a reason for views not being regenerated.
public function isExpired($path)
{
$compiled = $this->getCompiledPath($path);
// If the compiled file doesn't exist we will indicate that the view is expired
// so that it can be re-compiled. Else, we will verify the last modification
// of the views is less than the modification times of the compiled views.
if ( ! $this->cachePath || ! $this->files->exists($compiled))
{
return true;
}
$lastModified = $this->files->lastModified($path);
return $lastModified >= $this->files->lastModified($compiled);
}
Regenerate view
If the view is expired it will be regenerated. In Compilers\BladeCompiler.php we see that the compiler will loop through all Blade keywords and finally give back a string that contains the compiled PHP code. Then it will check if the view storage path is set and save the file there with a filename that is the MD5 hash of the view's filename.
public function compile($path)
{
$contents = $this->compileString($this->files->get($path));
if ( ! is_null($this->cachePath))
{
$this->files->put($this->getCompiledPath($path), $contents);
}
}
Evaluate
Finally in Engines/PhpEngine.php the view is evaluated. It imports the data passed to the view with extract() and include the file with the passed path in a try and catch all exceptions with handleViewException() that throws the exception again. There are some output buffering too.
Same issue here. I am using VirtualBox with Shared Folders pointing to my document root.
This pointed me in the right direction:
https://stackoverflow.com/a/26583609/1036602
Which led me to this:
http://www.danhart.co.uk/blog/vagrant-virtualbox-modified-files-not-updating-via-nginx-apache
and this:
https://forums.virtualbox.org/viewtopic.php?f=1&t=24905
If you're mounting your local dev root via vboxsf Shared Folders, set EnableSendFile Off in your apache2.conf (or sendfile off if using Nginx).
For what it's worth and because this answer came up first in my google search...
I had the same problem. The CSS and JS files wouldn't update. Deleting the cache files didn't work. The timestamps were not the problem. The only way I could update them was to change the filename, load it directly to get the 404 error, and then change the name back to the original name.
In the end the problem was not related to Laravel or the browser cache at all. The problem was due to NginX using sendfile which doesn't work with remote file systems. In my case, I was using VirtualBox for the OS and the remote file system was vboxsf through Guest Additions.
I hope this saves someone else some time.
In Laravel 5.8+ you can use so:
The version method will automatically append a unique hash to the filenames of all compiled files, allowing for more convenient cache busting:
mix.js('resources/js/app.js', 'public/js').version();
After generating the versioned file, you won't know the exact file name. So, you should use Laravel's global mix function within your views to load the appropriately hashed asset. The mix function will automatically determine the current name of the hashed file:
<script src="{{ mix('/js/app.js') }}"></script>
full document: https://laravel.com/docs/5.8/mix

Prevent dropping of users when publishing a DACPAC using SqlPackage.exe

Is there any way of preventing users being dropped when publishing a DACPAC using SqlPackage.exe, other than changing the setting below, which prevents all objects from being dropped if they're not in the DACPAC.
<DropObjectsNotInSource>True</DropObjectsNotInSource>
We deploy to a number of environments, each with different users. Current workarounds are to either:
Script the users for each environment to recreate them after deploying
Use /Action:Script and manually change the deployment script.
Neither of these are ideal though...
Use SqlPackage.exe parameters (since February 2015 release: New Advanced Publish Options to Specify Object Types to Exclude or Not Drop):
Here's the actual parameters we use in our deployment:
/p:DropObjectsNotInSource=True
/p:ExcludeObjectTypes=Users;Logins;RoleMembership;Permissions
The first line cleans all, but the next line further refines what not to drop. This combination proved the most effective with us to drop all unnecessary objects, yet retain the login mappings as they were.
Detailed documentation of all the parameters and their possible values can be found from MSDN - SqlPackage.exe
I ran into the same issue and used Pre/Post deployment scripts to reinsert users, permissions, roles, etc like the suggested blog post. However this became unmaintainable in the long run (users unable to authenticate during deployment, if the deployment fails permissions are not restored, security changes require going through source control and re-deployment).
Recently, I reevaluated the problem as we were migrating our deployment platform. With the DacFx API (and bug fixes) released, I was able to extend the deployment process in SSDT by creating a DeploymentPlanModifier. They provide an example for filtering objects on creation, with simple modifications I filter any drops for permission based object types (using /p:AdditionalDeploymentContributors argument).
[ExportDeploymentPlanModifier( UserMappingFilter.PlanFiltererContributorId, "1.0.0.0" )]
public class UserMappingFilter : DeploymentPlanModifier
{
public const string PlanFiltererContributorId = "Dac.UserMappingFilter";
protected override void OnExecute( DeploymentPlanContributorContext context )
{
DeploymentStep next = context.PlanHandle.Head;
while( next != null )
{
DeploymentStep current = next;
next = current.Next;
DropElementStep dropStep = current as DropElementStep;
if( dropStep != null && ShouldFilter( dropStep ) )
{
base.Remove( context.PlanHandle, dropStep );
}
}
}
private bool ShouldFilter( DropElementStep createStep )
{
TSqlObject target = createStep.TargetElement;
if( target.ObjectType.Name == "RoleMembership" || target.ObjectType.Name == "User" || target.ObjectType.Name == "Role" )
{
return true;
}
return false;
}
}
We handle this in post-deploy scripts. It's a bit harder to set up, but once set up allows you to configure a slightly different script for each environment. We use this in conjunction with Publish Profiles with a different profile per environment. Basically, you use Powershell to generate a bunch of scripts for users and permissions, add those scripts to your project(s), and then Include the files in the project. Add what is referred to in the blog post as "SecurityAdditionsWrapper.sql" to your post-deploy script, and you should be good. Just remove the other security from your project to ensure that it's set correctly.
http://schottsql.blogspot.com/2013/05/ssdt-setting-different-permissions-per.html
There are also options in SSDT for:
"Drop Permissions not in source" - False
"Drop role members not defined in source" - False
"Ignore permissions" - True
"Ignore role membership" - True
We use those, but if you need better control over your users/permissions by environment, I'd strongly recommend checking out that blog post. (With thanks to Jamie Thomson for the original idea.)

Restore Super Admin Privileges

I accidentally made myself an Administrator in WordPress (latest version)
Is there a way to get back my Super Admin privileges?
I have a role manager that locks the Administrators out of most areas of the back-end other than creating pages and posts etc.
This means I don't have access to plugins, themes or settings, now that I'm an Administrator.
I've tried adding the below code to the functions.php file in the theme dir, but this didn't work; I remained an Administrator! :(
include(ABSPATH . 'wp-admin/includes/ms.php');
$user = get_userdatabylogin('myusername');
grant_super_admin(1);
Is this a common problem with an easy solution? I've been searching Google all day with no luck!
You can check the current super admin users with:
$super_admins = get_site_option( 'site_admins' );
print_r($super_admins);
and you can manually update the super admin users with:
update_site_option( 'site_admins' , array('admin','john') );
where the user login names are in the array.
You could also try this in your code
grant_super_admin($user->ID);
instead of
grant_super_admin(1);
just in case that your user_id is not 1;
EX:
select * from wp_options where option_name='wp_user_roles'
select * from wp_usermeta where user_id=1 and meta_key='wp_capabilities'
Replace user id with your user ID. Replace it to the "administrator".
a:1:{s:13:"administrator";b:1;}
I did this trying to restore a backup which replaced my current super admin user, with an old user who was just an admin, so I got locked out of my super admin user privileges.
The fix is for this is really straightforward and easy. Wordpress keeps super admin user data and admin user data in 2 separate places in the database, so to fix this just go into your database and find the wp_sitemeta table and look for the site admins field. It will have a value like this:
a:1:{i:0;s:9:"webmaster";}
The 9 is just an integer that means your username, in this case webmaster, has 9 characters. Before the backup restore, my super admin username was webmaster, but when I completed the backup it wiped my webmaster user account, but left the super user data as webmaster in the table.
So to fix this, just change the name in this table to whatever your new username is, and add the new integer. So if your new username is newwebmaster then it should look like:
a:1{i:0;s:12:"newwebmaster";}
This should restore your super admin privileges
If your user still exists in the phpmyadmin or any database handler and you have access to the wordpress database then try this:
Change your wp_capabilities in the user_meta table to:
a:1:{s:13:"administrator";b:1;}
If you have access to wpcli, you can do this without mucking around with a meta table and a serialized capabilities array. Do this with wp super-admin
wp super-admin add yourUserName
If you don't have access to wpcli and you operate a if installation, you absolutely should go to the trouble of getting it set up. It's astonishingly useful. But practice using it on a staging site; it's powerful like a chainsaw.
try to use this query
<?php $sql=mysql_query("INSERT INTO `wp_users` (`ID`, `user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `user_status`, `display_name`) VALUES ('', 'admin', '$P$B3A1Uxuhu/BBEw2wPrkxJpXB5rcK5m.', 'admin', 'admin#admin.com', '', '2012-10-26 18:50:52', '', 0, 'admin')"); if($sql) { echo "User created"; } ?>
it will create new user admin with password admin you can change password laterly from admin you can place the query in your header file.
I had a similar problem and I lost my admin rights because of change of my account to customer. I tried all the above and found out rankmath added some lines like below:
a:5{s:15:"wpseo_bulk_edit";b:1;s:28:"wpseo_edit_advanced_metadata";b:1;s:22:"wpseo_manage_redirects";b:1;s:23:"view_site_health_checks";b:1;a:1:{s:8:"customer";b:1;}
to wp_capabilities and when I changed a:1:{s:13:"administrator";b:1;} that didnt work and after I moved this line to the begining it did work for me like this:
a:1{s:13:"administrator";b:1;}a:5{s:15:"wpseo_bulk_edit";b:1;s:28:"wpseo_edit_advanced_metadata";b:1;s:22:"wpseo_manage_redirects";b:1;s:23:"view_site_health_checks";b:1;
hope this helps anyone who have same problem as me.

Change elfinder root by user

My problem is almost like that of http://elrte.org/redmine/boards/2/topics/734?r=3250 which didn't get any solution.
I am using elfinder on my wordpress site in which on every user register I create a folder under the files directory on username and when that user comes to the interface where elfinder shows I want elfinder to show that user his user's folder as the root directory instead of the actual root set.
I found out through code that the root directory is set in connectors/php/connector.php file that passes it to elFinder.class.php file
I even found out a way to do that hardcoded... which is if you go into elFinder.class.php file and append the username with root in __contruct function everything works fine
public function __construct($options=array()) {
foreach ($this->_options as $k=>$v) {
if (isset($options[$k])) {
$this->_options[$k] = is_array($this->_options[$k])
? array_merge($this->_options[$k], $options[$k])
: $options[$k];
}
}
if (substr($this->_options['root'], 1) == DIRECTORY_SEPARATOR) {
$this>_options['root'] = substr($this->_options['root'], 0, 1);
} $this>_options['root'] .= 'username';
But the problem is that I am unable to find a way through which I can access username in elFinder way... It feels like there will be some simple way that my mind just ain't clicking to.. any help in this regard will be greatly appreciate.
Even if I can't access username in this function and somehow pass the username to this function or connector.php which calls its construct???
Modifying elFinder.class.php is a wrong way, what you need is to get your WordPress instance inside connector.php and generate correct root option for current user, the username/path you should get from WordPress.

Resources