Forums

Home » Liferay Portal » English » 3. Development

Combination View Flat View Tree View
Threads [ Previous | Next ]
toggle
Michael Oliver
Self Registration Portlet
April 27, 2012 4:46 PM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

Hi we are trying to create a portlet that allows guest users to fill in a form give information like Organization Name, username, email and some expando fields on both the organization and user.

We are getting the following exception when posting.

1binding organization expando fields!
208:28:00,138 ERROR [ExpandoBridgeImpl:507] com.liferay.portal.security.auth.PrincipalException
3com.liferay.portal.security.auth.PrincipalException
4    at com.liferay.portlet.expando.service.permission.ExpandoColumnPermissionImpl.check(ExpandoColumnPermissionImpl.java:35)
5    at com.liferay.portlet.expando.service.permission.ExpandoColumnPermissionUtil.check(ExpandoColumnPermissionUtil.java:32)


Here is the code in question. You can see by the log entry above where in the code we get when the exception is thrown.

I suspect that the guest user(aka unauthenticated user) is posting the form that user does't have adequate permissions to bind the expando fields.

 1
 2public class OrganizationCreationServiceImpl implements
 3        OrganizationCreationService {
 4
 5    private Logger logger = Logger.getLogger(this.getClass());
 6    private static final int STATUS_ID = 12017;
 7    private static final String ORG_ADMIN_ROLE_NAME = "Regular Superadmin";
 8   
 9    @Override
10    public Organization createOrganization(OrgAccountForm form, RequestContext context)
11            throws PortalException, SystemException {
12        long adminId = getAdminId();
13
14        ServiceContext serviceContext;
15        try {
16            
17            System.out.println("ADDING ORGANIZATION");
18            ExternalContext externalContext = context.getExternalContext();
19            PortletRequest nativeRequest = (PortletRequest) externalContext.getNativeRequest();
20            serviceContext = ServiceContextFactory.getInstance(
21                    Organization.class.getName(), nativeRequest);
22            
23
24            bindOrganizationExpandoFields(form, serviceContext);
25            Organization org = OrganizationLocalServiceUtil.addOrganization(adminId, 0,
26                    form.getName(), OrganizationConstants.TYPE_REGULAR_ORGANIZATION,
27                    false, 0, 0, STATUS_ID, "", false, serviceContext);
28            return org;
29            
30        } catch (PortalException e) {
31            e.printStackTrace();
32            throw e;
33        } catch (SystemException e) {
34            e.printStackTrace();
35            throw e;
36        }
37
38    }
39   
40    private void bindOrganizationExpandoFields(OrgAccountForm form, ServiceContext context){
41        System.out.println("binding organization expando fields!");
42
43        Map<String, Serializable> expandoFields = context.getExpandoBridgeAttributes();
44       
45        String[] timezone_types = {form.getTimezone()};
46       
47        expandoFields.put("timezone", timezone_types);
48        expandoFields.put("description", form.getDescription());
49        expandoFields.put("website", form.getWebsite());
50        expandoFields.put("phoneNumber", form.getPhoneNumber());
51        expandoFields.put("addressLine1", form.getAddressLine1());
52        expandoFields.put("addressLine2", form.getAddressLine2());
53        expandoFields.put("country", form.getCountry());
54        expandoFields.put("state", form.getState());
55        expandoFields.put("city", form.getCity());
56        expandoFields.put("postalCode", form.getPostalCode());
57        expandoFields.put("phoneArea", form.getPhoneArea());
58        expandoFields.put("email", form.getOrgEmail());
59        expandoFields.put("userLimit", form.getUserLimit());
60       
61        context.setExpandoBridgeAttributes(expandoFields);
62       
63    }
Hitoshi Ozawa
RE: Self Registration Portlet
April 27, 2012 5:19 PM
Answer

Hitoshi Ozawa

Rank: Liferay Legend

Posts: 7990

Join Date: March 23, 2010

Recent Posts

I suspect that the guest user(aka unauthenticated user) is posting the form that user does't have adequate permissions to bind the expando fields.


So, what is the question? It seems you've already have it figured out.
Michael Oliver
RE: Self Registration Portlet
April 28, 2012 12:18 AM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

Well no, we are still getting the exception, although I have a suspicion I don't have a solution. Thanks.
Michael Oliver
RE: Self Registration Portlet
April 28, 2012 3:11 PM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

Obviously we cannot simply raise the permissions on the guess user, even if we could for security reasons. So the self registration form in a portlet displayed on the public pages posts to a service. In that service we must assume the identify of a user that has the permissions to save the expando fields and add the organization and user from the self registration form.

I am sure I can eventually find out how to do it, but I have searched the source tree and as yet haven't found a method to assume an identity above yourself. I have seen the opposite where an admin can impersonate a subordinate.

So the question is:

How do we assume the identify of a user during our processing of the post from the self registration form that has adequate permissions to bind the form values to the expando fields, create a new organization and admin user for that organization?
Hitoshi Ozawa
RE: Self Registration Portlet
April 28, 2012 3:48 PM
Answer

Hitoshi Ozawa

Rank: Liferay Legend

Posts: 7990

Join Date: March 23, 2010

Recent Posts

I usually only use custom fields when there's no programming involved. It's a nice quick solution to add field without programming.

When there's some programming involved, I just create a new entity to wrap liferay's services. I found expando to have some restrictions.
Michael Oliver
RE: Self Registration Portlet
April 28, 2012 7:13 PM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

Hitoshi,

While I appreciate that there is more than one way to solve a problem and I am sure your approach would work. It doesn't answer my question on how to assume the identify of a user during the processing of a post from a self registration page, so we don't run into the permissions problem?

We have other hooks into organisation and user services to synchronize with an external system and we have the expando fields working for that already. So while thanks for your input, it doesn't help because we are not going to drop the expando fields and the code that we have working.
Stian Sigvartsen
RE: Self Registration Portlet
April 29, 2012 4:43 AM
Answer

Stian Sigvartsen

Rank: Junior Member

Posts: 97

Join Date: August 27, 2010

Recent Posts

Hi Michael.

Hitoshi's approach meets your requirements as I understand them. Because you are wanting to assume the identity of another user for the self registration process anyway, authentication would not be adding any real value. The only thing you might want to benefit from, is recording which user actually created the various entities through the Service Builder services. The local interfaces to these services will enable you to achieve this by passing a user ID to the methods. Local interfaces to services never require authentication, so you will not run into permissions problems.

So you simply need to wrap (using decorator pattern) calls methods on the local interfaces of various out of the box Liferay services in a new Service Builder service and make this only available through a local interface. This will be sufficient for calling it from your portlet. I would recommend that you have the new Service Builder service in the same plug-in project as your portlet. And I would recommend switching off the remote interface for this new service to increase security overall.

In theory you can actually skip creating a new Service Builder service altogether and just call the out of the box services directly from your portlet, but its nice to keep this new logic encapsulated as a service which can be made available remotely in the future (with authentication).

There should be a service for the Expando entities, though I haven't personally used it.

-Stian
Michael Oliver
RE: Self Registration Portlet
April 29, 2012 3:12 PM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

Thanks Stan,

first of all the self registration portlet is always an unathenticated user on a public page so not sure what you mean by "The only thing you might want to benefit from, is recording which user actually created the various entities through the Service Builder services."

Next, as I said we already have two hooks extending the organization and user services we use to synchronize with an external service and they use expando fields and we don't want to throw that work away, which I believe would be necessary to implement the decorator / custom fields approach and correct me if I am wrong.

So we are getting the Principal exception listed above when posting the form from the self registration portlet, however if I post that form when logged in as an admin user, we do NOT get that exception.

So, I repeat my question. Is there a way to post the form as an admin user from a public page? I did find one possible solution but haven't been able to test it yet, which is the "doAsUserId" it seems like setting that value on the url to our self registration portlet would meet my needs without having to move from expando fields to custom fields and entiry wrappers.
Michael Oliver
RE: Self Registration Portlet
April 29, 2012 10:57 PM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

Stan and Hitoshi,

As I mentioned we already have used expando fields on both organization and user. One of my concerns is that custom fields are accessible in the control panel, and if an admin were to edit a custom field definition he could break everything, but he cannot edit expando field definitions.

if the doAsUserId tag and PortalUtil.getDoAsUserId doesn't work, then we might need to follow your recommendation despite all the work we have done already. Do you have an example to help guide us?
Sandeep Nair
RE: Self Registration Portlet
April 29, 2012 11:37 PM
Answer

Sandeep Nair

Rank: Liferay Legend

Posts: 1691

Join Date: November 5, 2008

Recent Posts

What is getAdminId?
Michael Oliver
RE: Self Registration Portlet
April 30, 2012 12:18 AM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

Let me get you right. You are a liferay legend and you are asking "What is getAdminId?" from a "new member"?

Are you being cute or just demonstrating your superiority because you know something I don't?
Sandeep Nair
RE: Self Registration Portlet
April 30, 2012 12:24 AM
Answer

Sandeep Nair

Rank: Liferay Legend

Posts: 1691

Join Date: November 5, 2008

Recent Posts

Sorry being liferay legend doesnt mean i know it all. If you live you learn. I dont know if its a inheritted method from class you are using, or is it a private method that returns a guest userid.

Anyway if its a private method, then then you can use UserLocalServiceUtil.getUserByScreename(long companyId, String screenName).getUserId() The screename would be screen name of user who is Omni Admin or having Administrator role

Thanks & Regards,
Sandeep
Michael Oliver
RE: Self Registration Portlet
April 30, 2012 12:33 AM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

Sandeep,

I couldn't tell what you were saying because I hadn't mentioned "getAdminId" and neither did Stan or Hitoshi. Yes thanks I did know about getUserbyScreename() and assumed I would use that to setDoAsUserId. I found a reference to doAsUserId that lets you set that property on a URL for a portlet and impersonate that user on that portlet.

What I don't know and haven't been able to find is an example of how to use it or confirmation that it is the way to solve my problem with permissions on expando field binding.
Neil Griffin
RE: Self Registration Portlet
April 30, 2012 1:59 PM
Answer

Neil Griffin

LIFERAY STAFF

Rank: Liferay Legend

Posts: 1993

Join Date: July 26, 2005

Recent Posts

Just wanted to mention that the Liferay Faces project has a jsf2-registration-portlet that has an expando. Even if you don't develop with JSF, it might be helpful for you to review the Java portions of the project.
Michael Oliver
RE: Self Registration Portlet
April 30, 2012 2:11 PM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

Neil,

Actually we prefer JSF so thank you thank you thank you!

Ollie
Neil Griffin
RE: Self Registration Portlet
April 30, 2012 2:17 PM
Answer

Neil Griffin

LIFERAY STAFF

Rank: Liferay Legend

Posts: 1993

Join Date: July 26, 2005

Recent Posts

My pleasure. Let me know how it works out. If you have any problems, please post them in the Liferay Faces category.
David H Nebinger
RE: Self Registration Portlet
April 30, 2012 2:21 PM
Answer

David H Nebinger

Rank: Liferay Legend

Posts: 6270

Join Date: September 1, 2006

Recent Posts

Michael Oliver:
I couldn't tell what you were saying because I hadn't mentioned "getAdminId"


Just to clarify, you do use getAdminId() in your source that you pasted above...
Michael Oliver
RE: Self Registration Portlet
April 30, 2012 2:40 PM
Answer

Michael Oliver

Rank: Junior Member

Posts: 59

Join Date: April 19, 2012

Recent Posts

David H Nebinger:
Michael Oliver:
I couldn't tell what you were saying because I hadn't mentioned "getAdminId"


Just to clarify, you do use getAdminId() in your source that you pasted above...


Ah, right you are. I didn't realize I hadn't copied all the code which is why I didn't understand response, as I was asking how to impersonate admin, not how to get the AdminId and this may not be the best way to do it, but it wasn't my question either sorry for the confusion.

 1private long getAdminId() throws PortalException, SystemException {
 2        long userId = -1;
 3        try {
 4            long companyId = getDefaultCompanyId();
 5            
 6            long roleId = RoleLocalServiceUtil.getRole(companyId,
 7                    "Administrator").getRoleId();
 8            logger.debug("Role Id: " + roleId);
 9
10            userId = UserLocalServiceUtil.getRoleUsers(roleId).get(0)
11                    .getUserId();
12            logger.debug("User Id: " + userId);
13        } catch (PortalException e) {
14            e.printStackTrace();
15            throw e;
16        } catch (SystemException e) {
17            e.printStackTrace();
18            throw e;
19        }
20        return userId;
21
22    }