How do I hide a `ir.actions.act_window` defined in another module - odoo

Pretty simple question. In odoo/addons/portal/wizard/portal_wizard_views.xml there is the following action:
<act_window id="partner_wizard_action"
name="Grant portal access"
binding_model="res.partner"
res_model="portal.wizard"
view_mode="form" target="new"
groups="base.group_partner_manager"/>
How do I hide it??
More Information
Other answers I've seen recommend unlinking the record completely, but not only could I not figure out the best way to do this, most importantly I would like to remove the action in such a way so that if my module is uninstalled, the action is show again as if nothing ever happened. I don't want my module doing anything to other modules that would require them to be reinstalled. Especially in this case, since the portal module is depended up by sale and account, among other critical modules.
I've also seen answers recommending just redefining the record with the same id but prefixed with the other module's name in order to override the action. In this case I guess that would look something like this:
<act_window id="portal.partner_wizard_action"
name="Grant portal access 2"
binding_model="res.partner"
res_model="portal.wizard"
view_mode="form" target="new"
groups="base.group_partner_manager"/>
However, I couldn't even get this to work. It doesn't replace the existing action in the contextual menu; instead it just adds a new action, resulting in there now being two (both "Grant portal access" and "Grant portal access 2"). And I'm not sure how I would hide the action using this method either.
Edit: I found that for some unknown reason the original action in my Odoo instance no longer had an external ID. That is why it wasn't being "overridden" when I tried redefining the record. I resolved this my uninstalling my custom module, deleting both of the actions, and then updating the portal module. This caused the action to be re-created with the external ID present again, and when I reinstalled my custom module I could then override it.
However, this doesn't solve my problem of updating the action in a "non-destructive" way. When I uninstall my custom module, changes that it made to the action persist until the original portal module is upgraded again. This is bad, because someone uninstalling the custom module would need to know that the portal module must be upgraded to revert some of the changes.

I figured it out... sort of.
First, for some reason the original partner_wizard_action from the portal module in my case had somehow lost it's external ID/ref/xml_id. I have no clue how that happened, but to resolve it I had to uninstall my custom module, delete the "Grant portal access" action and the "Grant portal access 2" action, and then upgrade the portal module. This re-created the partner_wizard_action with the correct external ID.
I could then override the action as expected with the following code:
<record id="portal.partner_wizard_action" model="ir.actions.act_window">
<field name="binding_model_id" eval="False"/>
</record>
This unbinds the action from the res.partner model, causing the action to no longer show up in the contextual menu. However, it does still exist.
This "solution" comes with a huge caveat, however. When I uninstall my custom module now, the action does not get reverted to how it was before it was overridden. So it will still be hidden, unless the portal module is explicitly upgraded again.
To get around this, I'm considering writing a uninstall_hook in my module manifest to set the action's binding_model_id back to the correct value. It sucks that there doesn't seem to be a better way to do this, however.
Edit: I was successfully able to have the action revert itself at module uninstallation using the following uninstall_hook:
from odoo import api, SUPERUSER_ID
def uninstall_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
env.ref("portal.partner_wizard_action").binding_model_id = env.ref("base.model_res_partner").id
In case you are not aware, you would put this function in __init__.py at the root of your module and then add "uninstall_hook": "uninstall_hook" to your __manifest__.py file.

To hide an action, you can:
1- Set the binding model (binding_model_id) to False as you did.
2- Add a group with no user so the following expression is evaluated to True:
action_groups and not action_groups & user_groups
3- Add the active field (default=True) to hide action from searches then alter the _get_bindings method (because actions are fetched using an SQL query
) and change the where clause to:
where m.model = %s and active is true
4- It is also possible to alter the fieds_view_get method to filter the toolbar actions
Adding groups may require reverting changes after module uninstallation

Related

Yesod.Auth no authentication and no authorization

I'am writing a web app for personal use with Yesod. I don't want authentication and no log in.
What is the best way to achieve this?
remove the Auth library from the application
use a default hidden user that automatically logs in at startup (Auth.dummy?)
or something else....
Assuming you're using a recent version of the scaffolded site, you should be able to look in src/Foundation.hs for the definition of isAuthorized. Replace the entire definition with:
isAuthorized _ _ = return Authorized
or even remove it entirely, since the above definition is the default.
That should be sufficient to allow access to all pages. Next, search your code for uses of maybeAuth* and requireAuth* functions. Make sure that pages that use maybeAuth* work as expected if they get back Nothing. Remove any uses of requireAuth* and any dependencies on its return value.
Afterwards, you can clean up unneeded code, but this is entirely optional:
In Foundation.hs, you can:
remove Yesod.Auth.Dummy and Yesod.Auth.OpenId imports
remove the definition of muser <- maybeAuthPair from defaultLayout
remove login/logout/profile pages from the navbar (menuItems)
remove the authRoute definition in the instance Yesod App
remove AuthR and ProfileR from the breadcrumb
remove the instance YesodAuth App, the definition of isAuthenticated, and the instance YesodAuthPersist App
In NoFoundation.hs, you can remove the Yesod.Auth import.
In Settings.hs, remove the appAuthDummyLogin field and the reference to it in instance FromJSON AppSettings
In config/routes.yesodroutes remove /auth and /profile routes
Remove src/Handler/Profile.hs and the import Handler.Profile from Application.hs.
Stamp out any remaining references to maybeAuth* functions or references to the ProfileR route.

TYPO3 error «action is not allowed by this plugin»

I'm trying to make an Ajax-call to my Controller.
I placed a hidden link in my form like this:
<f:link.action action="ajaxCheckEmailExistsFE" controller="Profiles" class="hidden" id="checkEmailExistsAjaxLink"></f:link.action>
In my Javascript, I extract the href from this link:
var target = $('#checkEmailExistsAjaxLink').attr('href');
And then send my request with jQuery's $.post method.
When the link is called, I get the infamous error
The action \"ajaxCheckEmailExistsFE\" (controller \"Profiles\") is not allowed by this plugin. Please check TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php
But the action is clearly set in ext_localconf.php!
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'MyVendor.MyExt',
'MyPlugin',
[
'Profiles' => 'editFE, showFE, updateFE, ajaxCheckEmailExistsFE'
],
// non-cacheable actions
[
'Profiles' => 'editFE, showFE, updateFE, ajaxCheckEmailExistsFE'
]
);
The same workflow works perfectly in BE-Mode.
I had the same problem with the updateFE-Action. When the form was submitted, I got the same error like above. I had to add it to the switchable-controller-actions in my flexform (-> <numIndex index="1">Profiles->editFE;Profiles->updateFE</numIndex>) - which is equally odd.
Why is this happening???
This is TYPO3 9.5
[Edit] For the time being, I ended up adding the action to the switchable-controller-actions just like I did for the updateFE-Action.
This is VERY cumbersome, though, since I have to set the plugin-action on the page every time I add a new action.
If anybody has a better solution, I'd be extremely thankful!
Indeed, this IS cumbersome, but it is also the only working way for switchable actions in TYPO3 extbase controllers. This check is intended to ensure that specific actions are only callable when you are in the "correct" plugin, as you may have several plugins inside one extension, which then may utilize different actions. So in the end, this feature prevents one plugin to call an action which should only be callable inside another plugin of the same extension.
If you do not need the editor to switch action sets of your plugins though, you can remove this config part from your flexform, which will solve the need to edit this for new actions.
As a famous example, take a look into the config of the news extension. There is one plugin which allows list+detail view, and different ones for just list or just detail view. So as an admin, you have to choice of structuring your website (routing and templates) for different news setups.
Even in the TYPO3 community, there are voices to get rid of this feature, so maybe it will be solved in future versions.

Odoo11 - Restrict user assignment to project team members

I downloaded the .exe file of the community edition of odoo 11, installed it on a windows server and configured rules, that projects can only be seen by users who are assigned to the project as team members.
That works fine!
Now, in a task I want to restrict the options in the "assigned to" dropdown of a task: In the dropdown I want to see only users, who are actually assigned to that project. At the moment I can see all existing users and can assign the task to any of them.
In the form view I tried to restrict the list as follows by adding the domain attribute:
<field name="user_id" class="o_task_user_field" domain="('user_id','in', [project.members])" />
This gives an error on save.
Field 'project' used in attributes must be present in view but is missing
Update: 2. approach:
I tried to update the field user_id in model project.task and set the domain as follows:
('project_id.members','in', [user.id])
But I got the error (translated from german): you cannot make changes in a basic field!
How can I limit the options in the dropdown (without making code changes as I don´t have the code forked from github)?
Any help appreciated!
Thanks
For this you just need to update one onchange and in that add domain. No need to add it from xml. There is by default onchange_projectmethod is there. In that you just inherit it and add one line..
result.update({'domain':{'user_id':[('project_ids','in',project_id)]}})

Yii-User and Yii-eauth integration

I am trying to put together an application using yii-user and yii-eauth extensions but I am coming up short. When I create a new webapp and install eauth I can get it to work fine so I know that I am not doing anything wrong on that end. I think the problem lies with my urls. This is a demo of what it is supposed to be like: http://nodge.ru/yii-eauth/demo/login. When someone clicks on say google it should bring you to the google sign in page but on my application I am getting a 404 error that states "The system is unable to find the requested action "login"." The url for this is user/user/login/service/google_oauth whereas the url should read user/login/service/google_oauth. Upon typing this into the browser manually I am redirected to the right page.
So I took a look into the EAuthWidget.php class to see if I could find out where it was getting that extra "user" from but I could not figure it out. I think it may have something to do with the fact that I have this in the user module which is in the /modules/user directory in my webapp. I also tried to use the URLManager to point to the right address but with no luck.
Does anyone have any similar experiences setting this up? Or any suggestions?
You just need to change the widget initialization code in your view(namely change the action property of the widget), somewhat like this:
<h2>Do you already have an account on one of these sites? Click the logo to log in with it here:</h2>
<?php
$this->widget('ext.eauth.EAuthWidget', array('action' => 'login'));
?>
Just to add, keep in mind that this action depends on which view you are including this widget, if the view is protected/views/site/login.php (which is yii's default site login view) then action should be able to go to the yii-user module's login action, so it'll be : 'action'=>'/user/login' , however if you are including this widget in yii-user's protected/modules/user/views/user/login.php then the action will be 'login' as already mentioned.

How can I display Joomla modules within a component?

I have a component with several categories of games and I want to display a different banner depending on the category. I need the banner (and link) to be customizable so it's not simply a case of showing categoryX.jpg or whatever.
I saw this Joomla help page on another question, but it only seems to display a module type, not one specific module. I'd like to use various mod_custom modules and display the one appropriate to the category (I can store each module's ID if necessary).
Any ideas?
This can be done in a 2 step process:
Use the "Load module into article" plugin to allow yourself to access the module using a plugin call like:
{module [*mod_id*]} // where *mod_id* is the module id
Now that you can call a plugin to put your module anywhere, you now need to go to the view code of your/a component you wish to add the module to and add this code:
echo JHTML::_('content.prepare', '{module [*mod_id*]}');
Please see this link - http://www.alltogetherasawhole.org/group/developers/forum/topics/running-joomla-content-plugins - regarding point number 2. I was trying to do the same thing and I found it didn't work, and the reason for this was a comment you can find on the page link above:
"I noticed that some plugin actually expect option=com_content for them to process onPrepareContent properly, so you might actually want to "fool" them by callin JRequet::setVar and restoring the correct values after the trigger."
If you would like to show module within PHP code then use this code, it's worked for me :
<?php echo JHTML::_('content.prepare', '{loadposition position-2}'); ?>
If you want to show module inside html content then just put this code where you want to show module.
{loadposition position-2}
It loads all modules which are assigned to position-2.
You can also use the Joomla Module Renderer
$doc = JFactory::getDocument();
$renderer = $doc->loadRenderer('modules');
$position = 'custom_position_name';
$options = array('style' => 'raw');
echo $renderer->render($position, $options, null);
Just a heads up, Along with being assigned the module position, that module also has to be set to "Display on All pages".
Joomla has this functionality built in. You can use the {loadposition XX} command within your content items. You can specify custom module positions that do not appear in your template to insure that you have the correct module in the correct article.
http://docs.joomla.org/How_do_you_put_a_module_inside_an_article%3F
You could create a new module?
If each category appears in the querystring (catid=X) then you could take a similar approach to https://support.pillwax.com/open-source/doku.php?id=joomla:header_image.
Alternatively, that link might actually do it for you.