Get user details in liferay layout listener - liferay

I'm creating a listener for liferay Layout model. I want to get the page creating/updating user details to the log. Here is a snippet from my code.
public class LayoutListener extends BaseModelListener<Layout> {
private final static Logger log = Logger.getLogger(LayoutListener.class);
#Override
public void onAfterRemove(Layout layout) throws ModelListenerException {
// Need to find user deatils here.
if (log.isInfoEnabled()) {
log.info("Page -- " + layout.getName() + " -- removed.");
}
super.onAfterRemove(layout);
}
}
How can I get the relevant user who is deleting the page inside this method?
PS - I was able to get user from accessing the current thread. But I need to know a proper way to do this.

Well here is how liferay fetches it for listeners in its Audit EE plugin:
if(PrincipalThreadLocal.getName() != null) {
userId = GetterUtil.getLong(PrincipalThreadLocal.getName());
}
And we are also using the same thing in our custom listeners for Blogs and Documents.

Related

Liferay module listener : Unable to get who made a change to the model

I have to create custom auditing for the User model to track by whom the user has been deleted. I have tried to create a Liferay module listener for the User model, but I am not able to get the detail by whom the user is being deleted.
Is there any way to get details about who made a change to the User model in Liferay module listener?
My Liferay environment detail
Liferay portal : liferay-ce-portal-tomcat-7.0-ga5
Database : postgres (PostgreSQL) 9.5.17
IDE : eclipse-oxygen 4.7.3a
/*
* Below is the sample code that I have tried to create the Liferay module listener for the User model
*/
package com.test.useraudit.modellistner;
import org.osgi.service.component.annotations.Component;
import com.liferay.portal.kernel.exception.ModelListenerException;
import com.liferay.portal.kernel.model.BaseModelListener;
import com.liferay.portal.kernel.model.ModelListener;
import com.liferay.portal.kernel.model.User;
#Component(
immediate = true,
service = ModelListener.class
)
public class CustomUserModelListner extends BaseModelListener<User>{
#Override
public void onBeforeRemove(User user) throws ModelListenerException{
System.out.println("In onBeforeRemove method");
System.out.println("User detail :");
System.out.println(user);
super.onBeforeRemove(user);
}
#Override
public void onAfterRemove(User user) throws ModelListenerException{
System.out.println("In onAfterRemove method");
System.out.println("User detail :");
System.out.println(user);
super.onAfterRemove(user);
}
}
Yes it's possible.
There's an implicit thread local variable called ServiceContext that contains the calling context details.
Sample:
#Override
public void onBeforeRemove(User user) throws ModelListenerException{
ServiceContext serviceContext =
ServiceContextThreadLocal.getServiceContext();
System.out.println("Calling user:" + serviceContext.getUserId());
}
Yes it’s possible and that’s included OOTB in Liferay. The delete events already it’s trace. You can see the Audit Event and System Event table.
You could use the Audit Event Framework for your customisations.

Acumatica: Sign Out User After Process Completion

I am trying to sign out a user once a process is completed, I tried using the PXAccess or the PXAccessInfo classes in order to do so but did not manage to find a correct way in logging out a user. Are there any other means in signing out a user which I might have glossed over?
I adapted the standard SignOut code so it can be run from a graph extension instead of a Aspx.cs web page. It is equivalent to this SignOut menu item:
In this example I put the code in SOOrderEntry Initialize override so it signs out the current user as soon as you navigate to the SalesOrderEntry graph. You can put it in an Action event handler but I haven't tested it in a PXLongOperation context which runs in a separate thread context:
public class SOOrderEntry_Extension:PXGraphExtension<SOOrderEntry>
{
public override void Initialize()
{
System.Web.UI.Page page = System.Web.HttpContext.Current.Handler as System.Web.UI.Page;
if (page != null)
{
PX.Data.PXLogin.LogoutUser(PX.Data.PXAccess.GetUserName(), page.Session.SessionID);
PX.Common.PXContext.Session.SetString("UserLogin", string.Empty);
string absoluteLoginUrl = PX.Export.Authentication.AuthenticationManagerModule.Instance.SignOut();
page.Session.Abandon();
PX.Data.Auth.ExternalAuthHelper.SignOut(System.Web.HttpContext.Current, absoluteLoginUrl);
PX.Export.Authentication.FormsAuthenticationModule.
RedirectToLoginPage(PX.Data.Auth.ExternalAuthHelper.SILENT_LOGIN + "=None", true);
}
}
}

How to extend OrchardCMS to show/hide navigation and content from intranet vs internet users

I have certain pages that I want accessible only to users that are accessing the site from within a given IP range. For all other users, these pages should be inaccessible, and their respective links not visible in the menu/navigation.
I'm new to OrchardCMS, can someone provide some general guidance and point me in the right direction?
There two aspects to answer your question.
1. To check access to orchard content items and menu item relative to it:
To achieve this, you can implement new IAuthorizationServiceEventHandler to replace the default roles based authorization service, the best sample for you is ContentMenuItemAuthorizationEventHandler which you can find under Orchard.ContentPicker module, I included a sample code to explain the usage of this handler:
public class CustomAuthorizationEventHandler :
IAuthorizationServiceEventHandler{
public ContentMenuItemAuthorizationEventHandler() {
}
public void Checking(CheckAccessContext context) { }
public void Adjust(CheckAccessContext context) {
//Here you can put your business to grant user or not
context.Granted = true; //Roles service will look to this value to grant access to the user
context.Adjusted = true;
}
public void Complete(CheckAccessContext context) {}
}
2. To check access to some actions.
To achieve this, you can implement new IAuthorizationFilter to check access to some actions in your system:
public class CustomAuthorizationFilter : FilterProvider, IAuthorizationFilter {
public void OnAuthorization(AuthorizationContext filterContext) {
if (!Granted) {
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
The solutions mentioned by #mdameer are ok, but you will run into difficulties when using containers, lists, projections and stuff.
I had a similar task but with date time ranges. See my question and answer to the task to get an idea how to tackle this via a custom part:
How to skip displaying a content item in Orchard CMS?

Is it possible to exclude a url from Application Insights?

We have an Azure web role deployed that has been using Application Insights (ver. 1.0.0.4220), however, we're going over our data quota. Is it possible to configure Application Insights ignore a specific URL?
We have a status web service that gets a huge amount of traffic but never throws any errors. If I could exclude this one service URL I could cut my data usage in half.
Out of the box it is not supported. Sampling feature is coming but that would not be configurable by specific url. You can implement your own channel that would have your custom filtering. Basically your channel will get event to be sent, you check if you want to send it or not and then if yes pass to standard AI channel. Here you can read more about custom channels.
There are two things that changed since this blog post has been written:
channel should implement only ITelemetryChannel interface (ISupportConfiguration was removed)
and instead of PersistenceChannel you should use Microsoft.ApplicationInsights.Extensibility.Web.TelemetryChannel
UPDATE: Latest version has filtering support: https://azure.microsoft.com/en-us/blog/request-filtering-in-application-insights-with-telemetry-processor/
My team had a similiar situation where we needed to filter out urls that were successful image requests (we had a lot of these which made us hit the 30k datapoints/min limit).
We ended up using a modified version of the class in Sergey Kanzhelevs blog post to filter these out.
We created a RequestFilterChannel class which is an instance of ServerTelemetryChannel and extended the Send method. In this method we test each telemetry item to be sent to see if it is an image request and if so, we prevent it from being sent.
public class RequestFilterChannel : ITelemetryChannel, ITelemetryModule
{
private ServerTelemetryChannel channel;
public RequestFilterChannel()
{
this.channel = new ServerTelemetryChannel();
}
public void Initialize(TelemetryConfiguration configuration)
{
this.channel.Initialize(configuration);
}
public void Send(ITelemetry item)
{
if (item is RequestTelemetry)
{
var requestTelemetry = (RequestTelemetry) item;
if (requestTelemetry.Success && isImageRequest((RequestTelemetry) item))
{
// do nothing
}
else
{
this.channel.Send(item);
}
}
else
{
this.channel.Send(item);
}
}
public bool? DeveloperMode
{
get { return this.channel.DeveloperMode; }
set { this.channel.DeveloperMode = value; }
}
public string EndpointAddress
{
get { return this.channel.EndpointAddress; }
set { this.channel.EndpointAddress = value; }
}
public void Flush()
{
this.channel.Flush();
}
public void Dispose()
{
this.channel.Dispose();
}
private bool IsImageRequest(RequestTelemetry request)
{
if (request.Url.AbsolutePath.StartsWith("/image.axd"))
{
return true;
}
return false;
}
}
Once the class has been created you need to add it to your ApplicationInsights.config file.
Replace this line:
<TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel"/>
with a link to your class:
<TelemetryChannel Type="XXX.RequestFilterChannel, XXX" />
Alternatively, you can disable the automated request collection and keep only exception auto-collection, just remove the RequestTrackingModule line from applicationinsights.config.
If you still need to collect some of the requests, not just filter all out, you can then call TrackRequest() (in the object of TelemetryClient class) from your code in the appropriate place after you know that you certainly need to log this request to AI.
Update: Filtering feature has been released some time ago and allows for exclusion of certain telemetry items way easier.

Create Orchard ContentItem programmatically from Command

I've written the following simple command inside my module. The Faq type has one custom part with a single field, and one BodyPart. After _cm.Create(item) is run, the item has an Id assigned but I can't find any trace of it in the database and it doesn't appear in Orchard's content tab. Why does the item get an Id but isn't found in the database? And does it need a driver, view, and placement info before it appears in the content tab?
public class ApiCommands : DefaultOrchardCommandHandler
{
private readonly IContentManager _cm;
public ApiCommands(IContentManager cm)
{
_cm = cm;
}
[CommandName("api seed")]
public void Seed()
{
var item = _cm.New("Faq");
item.As<FaqPart>().Question = "Why is the sky blue?";
item.As<BodyPart>().Text = "Shut up and do your homework.";
_cm.Create(item);
}
}
My custom part has no driver this is the Handler:
public FaqHandler(IRepository<FaqPartRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
}
It turns out my type didn't attach a CommonPart. After I attached one and set the Owner property of the part, I was able to save it.

Resources