Intercept user visits a group - liferay

I am new to liferay and I need to enhance my User Object with a Map(groupId, lastVisitedDate) after a user visited a group.
Any ideas when, where and how I can intercept this request and enhance my user with the called groupId and the current Date?

I solved my issue by creating a hook which extends the portal.properties.
In this properties file I created this property
servlet.service.events.pre=org.my.company.project.event.MyCustomAction
the MyCustomAction Class extends Action.
This is how I got the necessary informations
#Override
public void run(HttpServletRequest request, HttpServletResponse response)
throws ActionException {
try {
User user = PortalUtil.getUser(request);
ThemeDisplay themeDisplay = (ThemeDisplay) request
.getAttribute(WebKeys.THEME_DISPLAY);
Group group = themeDisplay.getLayout().getGroup();
[...]
} catch (Exception e) {
throw new ActionException(e);
}
}

Related

Liferay : How can I land to custom url on signout

I'm not sure if I can achieve this by simply configuration or I need to override LogoutAction for it.
I've configured multiple organisation and each organisation has there own site which I want to navigate to my custom url for different site instead of default url on logout from liferay.
[EDITED]
I want to navigate on different url for each site, not a common url.
Thanks
For this you can use default.logout.page.path property (in portal-ext.properties file)
default.logout.page.path=
#default.logout.page.path=/web/guest/logout
I think you can achieve this by overriding LogoutPostAction through a hook.
Define your LogoutPostAction class in portal.properties of your hook:
logout.events.post=com.my.action.MyLogoutPostAction
Here is a sample code for the class to redirect to your desired page:
public class MyLogoutPostAction extends Action {
#Override
public void run(HttpServletRequest request, HttpServletResponse response)
throws ActionException {
try {
doRun(request, response);
}
catch (Exception e) {
throw new ActionException(e);
}
}
protected void doRun(HttpServletRequest request, HttpServletResponse response)
throws Exception {
long groupId = PortalUtil.getScopeGroupId(httpReq);
// code to fetch the Group
// ....
// ....
//
String postLogoutURL = "create your own URL";
// if required: add a parameter
postLogoutURL = HttpUtil.setParameter(postLogoutURL, "my_param", "my_param_value");
// redirect to that URL
response.sendRedirect(postLogoutURL);
}
}
The only thing that can be a road block with this approach would be if Liferay has lost context of the current group from which the user was logged-out. I have not tested the code.

Customize CreateAccountAction in Liferay Portal

I'm trying to add "User Group" Selection field while creating a user (Self User Registration form - create_account.jsp).
Here Custom fields is not helpful because Usergroup is already exists in db. I want to insert into existing Users_UserGroups table.
I'm using below hook:
But User is not added in the group and no exception is printed.
Please suggest me for any other way to achieve this.
public class CustomCreateAccountAction extends BaseStrutsPortletAction
{
public void processAction(StrutsPortletAction originalStrutsPortletAction, PortletConfig portletConfig, ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception
{
System.out.println("My Custom Process Action Method is Called");
String emailid=ParamUtil.getString(actionRequest, "emailAddress");
long[] userGroupIds = null;
originalStrutsPortletAction.processAction(originalStrutsPortletAction, portletConfig, actionRequest,actionResponse);
System.out.println("This is after user is registered");
if (SessionErrors.isEmpty(actionRequest))
{
ThemeDisplay themeDisplay =(ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
long newlyCreatedUserId=UserLocalServiceUtil.getUserIdByEmailAddress(themeDisplay.getCompanyId(), emailid);
long userIds[]={newlyCreatedUserId};
long dummygroupid=16206;
System.out.println("TEST UserID="+newlyCreatedUserId);
System.out.println("TEST GroupID="+dummygroupid);
//Everything went well until here.
UserServiceUtil.addUserGroupUsers(dummygroupid, userIds);
//below sysout is not printed. and no exception or user in group db created.
System.out.println("user added to group");
}
}
public String render(StrutsPortletAction originalStrutsPortletAction, PortletConfig portletConfig, RenderRequest renderRequest, RenderResponse renderResponse) throws Exception
{
System.out.println("My Custom Render Method is Called");
return originalStrutsPortletAction.render(null, portletConfig, renderRequest, renderResponse);
}
}
for more info please have a look at this thread.
Using UserLocalServiceUtil instead of UserServiceUtil worked. Basically, the difference is that *ServiceUtil checks permissions and *LocalServiceUtil does not.
I'm not sure this is the best idea, but you can use the hook for both modify the user creación jsp and save the value via model listener on user create/modify.
Regsrds

web api 2 - Passing data from action filter to action as an argument

In order to avoid getting the user data on every action I've create an custom action filter that gets the user by its ID and then passes to the action.
public class UserDataAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
...
// getting the user and storing it in the request properties
object user = userBLL.GetUserById(userId);
actionContext.Request.Properties.Add("User", user);
}
}
And the I can get the user object in the action method like this:
[Authorize]
[UserData]
[HttpGet]
[Route("dosomething")]
public IHttpActionResult DoSomething()
{
// retrieve the user
object user;
Request.Properties.TryGetValue("User", out user);
User u = (User)user;
return Ok();
}
However, in MVC it's possible to use ActionParameters in the filter to store something that will be used by the action method, like so:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
...
// Create object parameter.
filterContext.ActionParameters["User"] = userBLL.GetUserById(userId);
}
And then use the User object as if it were part of the original request:
[AddActionParameter]
public ActionResult Index(User user)
{
// Here I can access the user setted on the filter
...
return View();
}
So, my question is: There is a way in Web API 2 to pass the User object from the action filter to the action as an argument, just like in MVC?
With ASP.NET Web API, you can create a parameter binding to receive an object, User in your case. You don't have to create a filter for this. So, you will create a binding like this.
public class UserParameterBinding : HttpParameterBinding
{
public UserParameterBinding(HttpParameterDescriptor descriptor) :
base(descriptor) { }
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider,
HttpActionContext context,
CancellationToken cancellationToken)
{
SetValue(context, new User() { // set properties here });
return Task.FromResult<object>(null);
}
}
Then, to use the binding, you will configure it, like this.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// snip
config.ParameterBindingRules.Insert(0, d =>
d.ParameterType == typeof(User) ? new UserParameterBinding(d) : null);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
With that, wherever you have User as action method parameter, it will automatically bind the instance you are creating inside UserParameterBinding to that parameter.

How to destroy a session after data is presented in a jsf page

I have this problem: I´m making this wonderfull tutorial The NetBeans E-commerce Tutorial . But instead of make it in JSP as is presented, i´m making a JSF version. Just to undertands the logic in construction an application like that.
In certain part the ControllerServlet.java, has this code:
int orderId = orderManager.placeOrder(name, email, phone, address, cityRegion, ccNumber, cart);
// if order processed successfully send user to confirmation page
if (orderId != 0) {
// dissociate shopping cart from session
cart = null;
// end session
session.invalidate();
// get order details
Map orderMap = orderManager.getOrderDetails(orderId);
// place order details in request scope
request.setAttribute("customer", orderMap.get("customer"));
request.setAttribute("products", orderMap.get("products"));
request.setAttribute("orderRecord", orderMap.get("orderRecord"));
request.setAttribute("orderedProducts", orderMap.get("orderedProducts"));
userPath = "/confirmation";
// otherwise, send back to checkout page and display error
As you can see, the author invalidates the session, in order to permit another purchase order. I made an Managed Bean with session scope in order to mantain the data avalaible throught the whole session. But when I try to clean up the session, as in the tutorial the author does, I can´t receive the data for confirmation.
Then, I made a different managed bean in order to have one to process the order (CartManagerBean), and another one to present the confirmation (ConfirmationMBean). I just injected the confirmatioBean into the cartBean to pass the orderId, necessary to present the data. In the confirmationBean, I made a cleanUp() method that invalidates the session.
But always, the data is not presented. So if any one can tell me what to do, I´ll appreciate.
Here is the part of my cartBean's code that pass the data to the confirmation bean:
...
#ManagedProperty(value ="#{confirmationBean}")
private ConfirmationMBean confirmationBean;
...
public String makeConfirmation() {
FacesContext fc = FacesContext.getCurrentInstance();
if (!cartMap.isEmpty()) {
int orderId = orderManager.placeOrder(name, email, phone, address, credicard, cartMap);
// if order processed successfully send user to confirmation page
if (orderId != 0) {
// get order details
confirmationBean.setOrderId(orderId);
// dissociate shopping cart from session
cartMap.clear();
// end session
//fc.getExternalContext().invalidateSession();
}
}
return "confirmation";
}
As you can see, I commented the part that invalidates the session. Here is the code that I implemented for the ConfirmationMBean:
#ManagedBean(name = "confirmationBean")
#SessionScoped
public class ConfirmationMBean implements Serializable{
private Customer customer;
private List<OrderedProduct> orderedProducts;
private CustomerOrder orderRecord;
private List<Product> products;
private int orderId;
#EJB
private OrderManager orderManager;
public void cleanUp(){
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().invalidateSession();
}
private void init(){
Map<String, Object> orderMap = orderManager.getOrderDetails(orderId);
customer = (Customer) orderMap.get("customer");
orderRecord = (CustomerOrder) orderMap.get("orderRecord");
orderedProducts = (List<OrderedProduct>) orderMap.get("orderedProducts");
products = (List<Product>) orderMap.get("products");
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public List<OrderedProduct> getOrderedProducts() {
return orderedProducts;
}
public void setOrderedProducts(List<OrderedProduct> orderedProducts) {
this.orderedProducts = orderedProducts;
}
public CustomerOrder getOrderRecord() {
return orderRecord;
}
public void setOrderRecord(CustomerOrder orderRecord) {
this.orderRecord = orderRecord;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
init();
cleanUp();
}
}
As you can see, when the orderId is setted by the preceding bean, the data is requested from the database, and populates the variables to present in the facelet. ¿Where or how I have to use the cleanUp method in order to obtain the same result that the tutorial?
Thanks in advance.
Put the bean where you're invoking the action in the request scope instead of session scope and get hold of the desired session scoped bean as a (managed) property.
#ManagedBean
#RequestScoped
public class SubmitConfirmationBean {
#ManagedProperty("#{cartBean}")
private CartBean cartBean;
// ...
}
And reference it by #{submitConfirmationBean.cartBean...} instead of #{cartBean...}.
Alternatively, explicitly put the desired session scoped bean in the request scope in the same action method as where you're invalidating the session:
externalContext.getRequestMap().put("cartBean", cartBean);
This way the #{cartBean...} will refer the request scoped one instead of the session scoped one which is newly recreated at that point because you destroyed the session. The request scoped one is lost by next request anyway.

Is WCF Service EntitySetRights.AllRead Secure?

I have the following code inside MyDataService.svc.cs (This is an example from DevExpress):
namespace MyDataService {
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[JSONPSupportBehavior]
public class DataService : DataService<TestDataEntities>, IServiceProvider {
public static void InitializeService(DataServiceConfiguration config) {
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
public object GetService(Type serviceType) {
if (serviceType == typeof(IDataServiceStreamProvider)) {
return new ImageStreamProvider();
}
return null;
}
protected override void OnStartProcessingRequest(ProcessRequestArgs args) {
CustomBasicAuth.Authenticate(HttpContext.Current);
if (HttpContext.Current.User == null)
throw new DataServiceException(401, "Invalid login or password");
base.OnStartProcessingRequest(args);
}
}
}
So while this is will check the Entity for a username and password, how safe is it that config.SetEntitySetAccessRule is set to AllRead. Wouldn't someone just be able to see this information on a url such as www.website.com/MyDataService.svc/Customer (where Customer is the table). If this is not so can someone please fill in the conceptual gap I am facing. Thanks!
You are correct that all entities will be returned when queried - AllRead just disallows insert updates and deletes.
You will need to use Query Interceptor to add your logic to restrict users to the set of data they have permission to view, for example adding a check user id to the query.

Resources