Im trying to hide unnecessary parts from drop-down menu.
To be precise Notifications, Shared Content, My Submissions, My Workflow Tasks etc..
I was able to remove them via
Control panel -> Users -> Roles -> User -> Permissions
Is there way to achieve same result through Hooks or through config file?
Im running docker with liferay/portal:7.3.0-ga1 image and therefore need to be able to achieve this without GUI.
After various research i came up with this:
private void removePermissions() throws PortalException {
List<String> portletList = Arrays.asList("com_liferay_users_admin_web_portlet_MyOrganizationsPortlet",
"com_liferay_my_account_web_portlet_MyAccountPortlet",
"com_liferay_portal_workflow_web_internal_portlet_UserWorkflowPortlet",
"com_liferay_portal_workflow_task_web_portlet_MyWorkflowTaskPortlet",
"com_liferay_notifications_web_portlet_NotificationsPortlet",
"com_liferay_sharing_web_portlet_SharedAssetsPortlet",
"com_liferay_oauth2_provider_web_internal_portlet_OAuth2ConnectedApplicationsPortlet"
);
String primKey = String.valueOf(company.getPrimaryKey());
for (String portlet : portletList) {
ResourcePermissionLocalServiceUtil.removeResourcePermission(
companyId,
portlet,
ResourceConstants.SCOPE_COMPANY,
primKey,
userRole.getRoleId(),
"ACCESS_IN_CONTROL_PANEL");
}
}
companyId, userRole can be achieved via RoleLocalServiceUtil and CompanyLocalServiceUtil. PrimKey is differs based on scope, this blog helped me a lot understanding it. I sniffed names of portlets through developer console when removing permissions through GUI. I haven't found cleaner solution.
Related
Im trying to use the Genexus Extensions SDK to place buttons on the IDE, in this case, i want to place it in the "context" menu, avaliable only in objects of type "Webpanel/Webcomponent" and "Transaction", Just like WorkWithPlus does here:
So far, digging up into the avaliable documentation, i've noticed that you need tu put the context type string into the xml tag and the GUID of the package that you're aiming to add the menu item, such as below in GeneXusPackage.package:
The Context ID above will add the item into the "Folder View" Context.
My questions:
Where can I find a list with all the possible ID Context strings?
What is that package attribute for, where can i get it's possible values?
I am using the SDK for Genexus 16 U11
I'm sorry to say that there is no extensive list of all the menus available. I'd never thought of it until now, and I see how it could be useful, so we'll definitely consider making it part of the SDK so that any package implementor may use it for reference.
In the meantime, in order to add a new command in the context menu you mentioned, you have to add it to the command group that is listed as part of that menu. That group is KBObjectGrp which is provided by the core shell package whose id is 98121D96-A7D8-468b-9310-B1F468F812AE.
First define your command in your .package file inside a Commands section:
<Commands>
<CommandDefinition id='MyCommand' context='selection'/>
</Commands>
Then add it to the KBObjectGrp mentioned earlier.
<Groups>
<Group refid='KBObjectGrp' package='98121D96-A7D8-468b-9310-B1F468F812AE'>
<Command refid='MyCommand' />
</Group>
</Groups>
Then in order to make your command available only to the objects you said before, you have to code a query handler for the command, that will rule when the command is enabled, disabled, or not visible at all. You can do that in the Initialize method of your package class.
public override void Initialize(IGxServiceProvider services)
{
base.Initialize(services);
CommandKey myCmdKey = new CommandKey(Id, "MyCommand");
AddCommand(myCmdKey, ExecMyCommand, QueryMyCommand);
}
private bool QueryMyCommand(CommandData data, ref CommandStatus status)
{
var selection = KBObjectSelectionHelper.TryGetKBObjectsFrom(data.Context).ToList();
status.Visible(selection.Count > 0 && selection.All(obj => obj.Type == ObjClass.Transaction || obj.Type == ObjClass.WebPanel));
return true;
}
private bool ExecMyCommand(CommandData data)
{
// Your command here
return true;
}
I'm using some helper classes here in order to get the objects from the selection, and then a class named ObjClass which exposes the guid of the most common object types. If you feel something isn't clear enough, don't hesitate to reach out.
Decompiling the Genexus dll and looking for the resource called package, you can infer what the names are.
It's cumbersome but it works
How can I best make the Application Inisghts' Instrumentation Key configurable in a way that allows an Azure Administrator to manage the settings for an App Services deployment of an MVC5 web application? Is there a certain event in an MVC application initialization where this should be done or is it okay to do it at pretty much any point? I am using the Trace Listener integration as well.
By default, the Instrumentation Key (iKey) is set in the ApplicationInsights.config file. Additionally, if you include the JavaScript portions, the iKey is again set in the _Layout.cshtml file. This is two different places with an iKey that you need to manage.
I want to be able to manage this key via the App Services -> Application settings tab of the Azure Portal. The reasons are:
I want to deploy multiple instances of this applications, each with its own unique iKey
I want to change this iKey periodically (because reasons)
I don't want this iKey stored in our code repository (it's okay for a "dev" iKey to be in code repo) nor do I want it to be managed by our build automation (again, because reasons)
Here is the implementation that I am currently using, and it seems to work. However, I had other implementations that seemed to set the iKey either too early or too late as it seemed it would use the iKey in the physical web.config file deployed to Azure instead of pulling from the Application settings tab from the Portal. Are there better options to do this in a best practice sort of way?
ApplicationInsights.config
<!-- Find the following node and *remove* it. It will have a GUID in it.
If you leave this, you may receive some errors even with all of the
other changes. -->
<InstrumentationKey>{GUID HERE}</InstrumentationKey>
Global.asax.cs
protected void Application_Start()
{
// Add this first line below
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey =
ConfigurationManager.AppSettings["ai:InstrumentationKey"];
// Showing the rest of this so you can see the order of operations
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
AutomapperConfig.Init();
}
web.config
<!-- Add the following to <appSettings> and put your iKey value in here. -->
<add key="ai:InstrumentationKey" value="*****" />
_Layout.cshtml (in the <head> section of the HTML. NOTE TO FUTURE READERS: I recommend you don't use this entire snippet but instead just use the line that begins instrumentationKey: and integrate that line into whatever the modern version is for the rest of this JS snippet!):
<script type = 'text/javascript' >
var appInsights=window.appInsights||function(config)
{
function r(config){ t[config] = function(){ var i = arguments; t.queue.push(function(){ t[config].apply(t, i)})} }
var t = { config:config},u=document,e=window,o='script',s=u.createElement(o),i,f;for(s.src=config.url||'//az416426.vo.msecnd.net/scripts/a/ai.0.js',u.getElementsByTagName(o)[0].parentNode.appendChild(s),t.cookie=u.cookie,t.queue=[],i=['Event','Exception','Metric','PageView','Trace','Ajax'];i.length;)r('track'+i.pop());return r('setAuthenticatedUserContext'),r('clearAuthenticatedUserContext'),config.disableExceptionTracking||(i='onerror',r('_'+i),f=e[i],e[i]=function(config, r, u, e, o) { var s = f && f(config, r, u, e, o); return s !== !0 && t['_' + i](config, r, u, e, o),s}),t
}({
instrumentationKey:'#(Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey)'
});
window.appInsights=appInsights;
appInsights.trackPageView();
</script>
All of the methods you specified are great. Our recommendation is to use a web.config app setting and using this in the global.asax.cs for standard initialization. No telemetry will be sent before the initlization as we hook into OnBeginRequest().
https://learn.microsoft.com/en-us/azure/application-insights/app-insights-api-custom-events-metrics#a-namedynamic-ikeya-dynamic-instrumentation-key
Another method that might work well is to set the APPINSIGHTS_INSTRUMENTATIONKEY environment variable as it's picked up by the SDK. Of course that depends on if you have multiple apps on the same machine.
https://github.com/Microsoft/ApplicationInsights-dotnet/blob/v2.2.0/src/Core/Managed/Net40/Extensibility/Implementation/TelemetryConfigurationFactory.cs#L22
[Edit]
You can get the current build-def via the IServiceProvider. See this answer.
[/Edit]
I'm trying to add a custom editor for one of our TFS Xaml build workflows.
I started by following this excelent tutorial by Ewald Hofman.
Everything worked as expected, when I click on the [...] button for the workflow parameter the credential dialog is displayed.
What I want to do:
I want to display a selectable list/tree of test suites that are available in the TFS team project. Just like in the Default Labs Workflow:
Obviously, for this to work, I have to be able to communicate the the TFS over its .Net-API (Is it possible to do via SOAP/REST?).
But whenI started to alter the example to fit to my scenario, I naivly tried using the IServiceProvider to get ahold of an IBuildService instance.
public override object EditValue(ITypeDescriptorContext context, ServiceProvider provider, object value)
{
if (provider != null)
{
IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
IBuildServer bs = (IBuildServer)provider.GetService(typeof(IBuildServer));
...
This approach did not work, bs is null after this statement.
Then I tried to connect to the TestManagement like this:
var pr = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://tfs:8080/tfs/DefaultCollection/ProjectName"));
var TcmService = pr.GetService<ITestManagementService>();
var t = TcmService.GetTeamProject("ProjectName");
But this failed with a HTTP 404 error that is displayed when I click the edit [...] buttton of the workflow parameter. The url is correct, if i open the page in a browser, the Team Webaccess page is displayed.
TL;DR:
I would like to be able to display a list of test suites of the current tfs in a custom worfklow parameter editor, but I am failing to connect to the TFS.
Other approach:
This site (and some others) recommend using builtin editors. Is it possible to use the builtin editor window of the labs workflow paramaters (the one in the first screenshot)?
Thanks in advance.
Appearantly I was just stupid.
var pr = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://tfs:8080/tfs/DefaultCollection/ProjectName"));
The project name must not be in this URL. With the line below it works just fine.
var pr = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://tfs:8080/tfs/DefaultCollection"));
See my followup question
Somewhere in my Vaadin application, I'm getting this exception as soon as I connect using a second browser
Caused by: java.lang.RuntimeException: A connector with id 22 is already registered!
at com.vaadin.ui.ConnectorTracker.registerConnector(ConnectorTracker.java:133)
It happens always in the same place but I don't know why exactly as the reason for this must be somewhere else.
I think I might be stealing UI components from the other session - which is not my intention.
Currently, I don't see any static instances of UI components I might be using in multiple sessions.
How can I debug this? It's become quite a large project.
Any hints to look for?
Yes, this usually happens because you are attaching a component already attached in other session.
Try logging the failed connector with a temporal ConnectorTracker, So the next time that it happens, you can catch it.
For example:
public class SomeUI extends UI {
private ConnectorTracker tracker;
#Override
public ConnectorTracker getConnectorTracker() {
if (this.tracker == null) {
this.tracker = new ConnectorTracker(this) {
#Override
public void registerConnector(ClientConnector connector) {
try {
super.registerConnector(connector);
} catch (RuntimeException e) {
getLogger().log(Level.SEVERE, "Failed connector: {0}", connector.getClass().getSimpleName());
throw e;
}
}
};
}
return tracker;
}
}
I think I might be stealing UI components from the other session - which is not my intention. Currently, I don't see any static instances of UI components I might be using in multiple sessions.
That was it. I was actually stealing UI components without prior knowledge.
It was very well hidden in a part which seems to be same for all instances. Which is true: the algorithm is the same.
Doesn't mean I should've reused the same UI components as well...
Thanks to those who took a closer look.
Here is how I fixed it -
1) look for components you have shared across sessions. For example if you have declared a component as static it will be created once and will be shared.
2) if you are not able to find it and want a work around until you figure out the real problem, put your all addComponent calls in try and in catch add following code -
getUI().getConnectorTracker().markAllConnectorsDirty();
getUI().getConnectorTracker().markAllClientSidesUnititialized();
getPage().reload():
This will clear old connectors and will reload the page properly only when it fails. For me it was failing when I was logged out and logged in back.
Once you find the real problem you can fix it till then inform your customers about the reload.
**** note - only solution is to remove shared components this is just a work around.
By running your application in debug mode (add ?debug at the end of URL in browser) you will be able to browse to the component, e.g:
-UIConnector(0)
--VerticalLayoutConnector(1)
---...
---LabelConnector(22)
where 22 is id from your stack trace. Find this component in your code and make sure that it is not static (yes, I saw such examples).
I want to specify my service name in the app.config without needing to recomple and install/uninstall my service repeatedly.
But just retrieving service name from app.config, the service seems ignoring it. Are there any special tricks how to obtain this?
Thanks in advance.
I mean classic windows service. I don't think any code is needed here. I just want to retrieve the service name from app.config dynamically.
After searching a while on the internet and reading articles, it became clearer to me that A service name can't be specified in the app.config in so dynamic way, instead sc command can be used to perform a similar solution. You can specify other configuration variables in the app.config and use sc to rename it
sc.exe create "servicename" binPath="myservicepath.exe"
I am not sure what scenario you have in mind. You would like the name of your Windows service to change. Fair enough. When would it change?
Imagine you have found the solution and created such a Windows service. I presume in your scenario you would install it at least the first time. Then you do not want to uninstall/install it. But presumably you would like to start/stop and do other things with it. Will one of those actions cause the name of the service to change?
If so, I imagine you could launch a process that uninstalls and installs it with a different name for you transparently, based on some kind of naming logic.
I don't see how else you could do it.
Or just come up with a really generic name to cover all possibilities (which might be incredibly simple or incredibly difficult).
http://www.codeproject.com/Articles/21320/Multiple-Instance-NET-Windows-Service
<add key="ServiceName" value="I"/>
[RunInstaller(true)]
public class ServiceInstaller1 : Installer
{
internal static string ServiceNameDefault = "My Service";
internal static string ServiceName = GetConfigurationValue("ServiceName");
/// <summary>
/// Public Constructor for WindowsServiceInstaller.
/// - Put all of your Initialization code here.
/// </summary>
public ServiceInstaller1()
{
var serviceProcessInstaller = new ServiceProcessInstaller();
var serviceInstaller = new ServiceInstaller();
//# Service Account Information
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
//serviceProcessInstaller.Username = null;
//serviceProcessInstaller.Password = null;
//# Service Information
serviceInstaller.DisplayName = ServiceName;
serviceInstaller.StartType = ServiceStartMode.Manual;
//# This must be identical to the WindowsService.ServiceBase name
//# set in the constructor of WindowsService.cs
serviceInstaller.ServiceName = ServiceName;
Installers.Add(serviceProcessInstaller);
Installers.Add(serviceInstaller);
}
private static string GetConfigurationValue(string key)
{
Assembly service = Assembly.GetAssembly(typeof(Service));
Configuration config = ConfigurationManager.OpenExeConfiguration(service.Location);
if (config.AppSettings.Settings[key] != null)
return ServiceNameDefault + " " + config.AppSettings.Settings[key].Value;
else
return ServiceNameDefault;
}
}
Assuming you mean Windows Service, the answer is no. The service has to be installed in the registry, and the name is one of the registry keys.
I'm afraid that what you are trying to do its not possible. It actually seems to go against the nature of a Windows Service purpose and current behavior.
After a windows service is installed the name can't be changed without re-installing it again. What actually names the service is an element called service installer. Which by now, I assume you know what it is and where its located.
However there are ways of manipulating an installed service by using Windows Management Instrumentation (WMI). Maybe this combined with Izabela's recommendation become the right path to your solution.
I would recommend you to read the following tutorial, you might find an alternate way of achieving what you're trying to do.
http://www.serverwatch.com/tutorials/article.php/1576131/Windows-Services-Management-With-WMI-Part-1.htm